131 lines
3.8 KiB
Rust
131 lines
3.8 KiB
Rust
//! # 资产实例ID模块
|
||
//!
|
||
//! Asset Instance ID Module
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 资产实例ID(AIID格式)
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||
pub struct AssetInstanceID {
|
||
/// 系统代码(2位)
|
||
pub system_code: String,
|
||
/// 租户代码(8位)
|
||
pub tenant_code: String,
|
||
/// 资产类型(6位)
|
||
pub asset_type: String,
|
||
/// 实例序列(12位)
|
||
pub instance_seq: String,
|
||
/// 校验和(2位)
|
||
pub checksum: String,
|
||
}
|
||
|
||
impl AssetInstanceID {
|
||
/// 生成资产实例ID
|
||
pub fn generate(
|
||
system_code: &str,
|
||
tenant_code: &str,
|
||
asset_type: &str,
|
||
instance_seq: &str,
|
||
) -> Result<Self, String> {
|
||
// 验证长度
|
||
if system_code.len() != 2 {
|
||
return Err("System code must be 2 characters".to_string());
|
||
}
|
||
if tenant_code.len() != 8 {
|
||
return Err("Tenant code must be 8 characters".to_string());
|
||
}
|
||
if asset_type.len() != 6 {
|
||
return Err("Asset type must be 6 characters".to_string());
|
||
}
|
||
if instance_seq.len() != 12 {
|
||
return Err("Instance sequence must be 12 characters".to_string());
|
||
}
|
||
|
||
// 计算校验和
|
||
let checksum = Self::calculate_checksum(system_code, tenant_code, asset_type, instance_seq);
|
||
|
||
Ok(AssetInstanceID {
|
||
system_code: system_code.to_string(),
|
||
tenant_code: tenant_code.to_string(),
|
||
asset_type: asset_type.to_string(),
|
||
instance_seq: instance_seq.to_string(),
|
||
checksum,
|
||
})
|
||
}
|
||
|
||
/// 计算校验和
|
||
fn calculate_checksum(
|
||
system_code: &str,
|
||
tenant_code: &str,
|
||
asset_type: &str,
|
||
instance_seq: &str,
|
||
) -> String {
|
||
let combined = format!("{}{}{}{}", system_code, tenant_code, asset_type, instance_seq);
|
||
let sum: u32 = combined.chars().map(|c| c as u32).sum();
|
||
format!("{:02}", sum % 100)
|
||
}
|
||
|
||
/// 转换为字符串格式
|
||
pub fn to_string(&self) -> String {
|
||
format!(
|
||
"AIID-{}-{}-{}-{}-{}",
|
||
self.system_code, self.tenant_code, self.asset_type, self.instance_seq, self.checksum
|
||
)
|
||
}
|
||
|
||
/// 从字符串解析
|
||
pub fn from_string(s: &str) -> Result<Self, String> {
|
||
let parts: Vec<&str> = s.split('-').collect();
|
||
if parts.len() != 6 || parts[0] != "AIID" {
|
||
return Err("Invalid AIID format".to_string());
|
||
}
|
||
|
||
Ok(AssetInstanceID {
|
||
system_code: parts[1].to_string(),
|
||
tenant_code: parts[2].to_string(),
|
||
asset_type: parts[3].to_string(),
|
||
instance_seq: parts[4].to_string(),
|
||
checksum: parts[5].to_string(),
|
||
})
|
||
}
|
||
|
||
/// 验证校验和
|
||
pub fn verify(&self) -> bool {
|
||
let expected = Self::calculate_checksum(
|
||
&self.system_code,
|
||
&self.tenant_code,
|
||
&self.asset_type,
|
||
&self.instance_seq,
|
||
);
|
||
self.checksum == expected
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_aiid_generation() {
|
||
let aiid = AssetInstanceID::generate("GN", "CNFIN001", "010121", "2024BLDG001A")
|
||
.expect("Failed to generate AIID");
|
||
|
||
assert_eq!(aiid.system_code, "GN");
|
||
assert_eq!(aiid.tenant_code, "CNFIN001");
|
||
assert!(aiid.verify());
|
||
}
|
||
|
||
#[test]
|
||
fn test_aiid_string_conversion() {
|
||
let aiid = AssetInstanceID::generate("GN", "CNFIN001", "010121", "2024BLDG001A")
|
||
.expect("Failed to generate AIID");
|
||
|
||
let aiid_str = aiid.to_string();
|
||
let restored = AssetInstanceID::from_string(&aiid_str).expect("Failed to parse AIID");
|
||
|
||
assert_eq!(aiid.system_code, restored.system_code);
|
||
assert_eq!(aiid.tenant_code, restored.tenant_code);
|
||
assert!(restored.verify());
|
||
}
|
||
}
|