Files
craftlabs-authorization-sdk/native/craft-core/src/error.rs
T
huangping b7a947409a build(native): rename lib to craftlabs_auth_core, add crypto deps
feat(rust): extend error codes for selfhosted licensing (crypto/license state variants)
2026-05-18 22:02:28 +08:00

108 lines
4.2 KiB
Rust

// Error codes for selfhosted + BitAnswer licensing
use crate::CraftResult;
#[derive(Debug, Clone, PartialEq)]
pub enum LicenseError {
// ── 通用 ──
Success,
ConfigMissing(&'static str),
Network(String),
NotInitialized,
// ── 签名 / 加密 ──
InvalidFormat(&'static str),
InvalidSignature,
SignatureMismatch,
CryptoError,
DecryptionFailed,
CorruptedPayload,
LicenseIdMismatch,
// ── 许可状态 ──
NotYetValid,
Expired,
NoCachedLicense,
OfflineGraceExceeded { days_offline: u32, max_days: u32 },
InvalidLicense,
LicenseRevoked,
DeviceLimitReached,
ConcurrentUserLimitReached,
ActivationLimitReached,
// ── 兼容比特 ──
BitAnswerStatus(u32),
// ── 未知 ──
UnknownStatus(u16),
}
impl LicenseError {
/// Map BitAnswer BIT_STATUS (u32) → LicenseError (双线共存保留)
pub fn from_bit_status(status: u32) -> Self {
match status {
0x0000 => LicenseError::Success,
0x0101 => LicenseError::Network("bitanswer network error".into()),
0x0102 => LicenseError::ConfigMissing("bitanswer wrong handle"),
0x0103 => LicenseError::ConfigMissing("bitanswer invalid parameter"),
0x0105 => LicenseError::ConfigMissing("bitanswer application data error"),
0x0114 => LicenseError::InvalidLicense,
0x011C => LicenseError::InvalidLicense,
0x0701 => LicenseError::Expired,
0x0705 => LicenseError::LicenseRevoked,
0x0706 => LicenseError::InvalidLicense,
0x0712 => LicenseError::DeviceLimitReached,
0x0123 => LicenseError::LicenseRevoked,
0x0503 => LicenseError::InvalidLicense,
0x0504 => LicenseError::InvalidLicense,
0x0509 => LicenseError::Expired,
0x0107 => LicenseError::Network("bitanswer server busy".into()),
0x0108 => LicenseError::Network("bitanswer server down".into()),
0x0141 => LicenseError::Network("bitanswer timeout".into()),
_ => LicenseError::BitAnswerStatus(status),
}
}
pub fn message(&self) -> &'static str {
match self {
LicenseError::Success => "ok",
LicenseError::ConfigMissing(_) => "config missing",
LicenseError::Network(_) => "network error",
LicenseError::NotInitialized => "not initialized",
LicenseError::InvalidFormat(_) => "invalid format",
LicenseError::InvalidSignature => "invalid signature",
LicenseError::SignatureMismatch => "signature verification failed",
LicenseError::CryptoError => "crypto error",
LicenseError::DecryptionFailed => "decryption failed",
LicenseError::CorruptedPayload => "corrupted payload",
LicenseError::LicenseIdMismatch => "license id mismatch",
LicenseError::NotYetValid => "license not yet valid",
LicenseError::Expired => "license expired",
LicenseError::NoCachedLicense => "no cached license",
LicenseError::OfflineGraceExceeded { .. } => "offline grace period exceeded",
LicenseError::InvalidLicense => "invalid license",
LicenseError::LicenseRevoked => "license revoked",
LicenseError::DeviceLimitReached => "device limit reached",
LicenseError::ConcurrentUserLimitReached => "concurrent user limit reached",
LicenseError::ActivationLimitReached => "activation limit reached",
LicenseError::BitAnswerStatus(_) => "bitanswer error",
LicenseError::UnknownStatus(_) => "unknown error",
}
}
pub fn is_success(&self) -> bool {
matches!(self, LicenseError::Success)
}
}
/// Convert LicenseError to C ABI CraftResult
pub fn to_craft_result(error: LicenseError) -> CraftResult {
if error.is_success() {
CraftResult { success: 1, message: std::ptr::null() }
} else {
let msg = format!("{}\0", error.message());
let msg_ptr = msg.as_ptr() as *const std::os::raw::c_char;
std::mem::forget(msg);
CraftResult { success: 0, message: msg_ptr }
}
}