//! # 资产实例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 { // 验证长度 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 { 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()); } }