use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display};
use std::str::FromStr;
use tracing::warn;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Architecture {
X86_64,
Aarch64,
Unsupported(String),
}
impl Architecture {
pub fn detect() -> Self {
let arch_str = std::env::consts::ARCH;
Self::from_str(arch_str).unwrap_or_else(|_| {
warn!("Detected unknown architecture: {}", arch_str);
Self::Unsupported(arch_str.to_string())
})
}
pub fn as_str(&self) -> &str {
match self {
Self::X86_64 => "x86_64",
Self::Aarch64 => "aarch64",
Self::Unsupported(arch) => arch,
}
}
pub fn from_str(arch_str: &str) -> Result<Self> {
match arch_str.to_lowercase().as_str() {
"x86_64" | "amd64" | "x64" => Ok(Self::X86_64),
"aarch64" | "arm64" | "armv8" => Ok(Self::Aarch64),
_ => Err(anyhow::anyhow!("Unsupported architecture: {}", arch_str)),
}
}
pub fn is_supported(&self) -> bool {
match self {
Self::X86_64 | Self::Aarch64 => true,
Self::Unsupported(_) => false,
}
}
pub fn display_name(&self) -> &str {
match self {
Self::X86_64 => "Intel/AMD 64-bit",
Self::Aarch64 => "ARM 64-bit",
Self::Unsupported(_) => "Unsupported architecture",
}
}
pub fn file_suffix(&self) -> &str {
match self {
Self::X86_64 => "x86_64",
Self::Aarch64 => "aarch64",
Self::Unsupported(arch) => arch,
}
}
pub fn is_64bit(&self) -> bool {
match self {
Self::X86_64 | Self::Aarch64 => true,
Self::Unsupported(_) => false, }
}
pub fn supported_architectures() -> Vec<Architecture> {
vec![Self::X86_64, Self::Aarch64]
}
pub fn supports_incremental_upgrade(&self) -> bool {
self.is_supported()
}
}
impl Display for Architecture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl FromStr for Architecture {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
Architecture::from_str(s)
}
}
pub struct ArchitectureCompatibilityChecker;
impl ArchitectureCompatibilityChecker {
pub fn check_compatibility(target_arch: &Architecture) -> Result<()> {
let current_arch = Architecture::detect();
if current_arch == *target_arch {
Ok(())
} else {
Err(anyhow::anyhow!(format!(
"Architecture mismatch: current system is {}, target architecture is {}",
current_arch.display_name(),
target_arch.display_name()
)))
}
}
pub fn get_system_summary() -> String {
let arch = Architecture::detect();
format!(
"OS: {}, architecture: {} ({}), 64-bit support: {}",
std::env::consts::OS,
arch.as_str(),
arch.display_name(),
if arch.is_64bit() { "yes" } else { "no" }
)
}
pub fn supports_cross_architecture_operation(
from_arch: &Architecture,
to_arch: &Architecture,
) -> bool {
from_arch == to_arch
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_architecture_detection() {
let arch = Architecture::detect();
assert!(matches!(
arch,
Architecture::X86_64 | Architecture::Aarch64 | Architecture::Unsupported(_)
));
println!("检测到的架构: {} ({})", arch.as_str(), arch.display_name());
}
#[test]
fn test_architecture_parsing() {
assert_eq!(
Architecture::from_str("x86_64").unwrap(),
Architecture::X86_64
);
assert_eq!(
Architecture::from_str("amd64").unwrap(),
Architecture::X86_64
);
assert_eq!(Architecture::from_str("x64").unwrap(), Architecture::X86_64);
assert_eq!(
Architecture::from_str("aarch64").unwrap(),
Architecture::Aarch64
);
assert_eq!(
Architecture::from_str("arm64").unwrap(),
Architecture::Aarch64
);
assert_eq!(
Architecture::from_str("armv8").unwrap(),
Architecture::Aarch64
);
assert_eq!(
Architecture::from_str("X86_64").unwrap(),
Architecture::X86_64
);
assert_eq!(
Architecture::from_str("ARM64").unwrap(),
Architecture::Aarch64
);
assert!(Architecture::from_str("mips").is_err());
assert!(Architecture::from_str("riscv").is_err());
}
#[test]
fn test_architecture_string_conversion() {
let x86_arch = Architecture::X86_64;
assert_eq!(x86_arch.as_str(), "x86_64");
assert_eq!(x86_arch.to_string(), "x86_64");
let arm_arch = Architecture::Aarch64;
assert_eq!(arm_arch.as_str(), "aarch64");
assert_eq!(arm_arch.to_string(), "aarch64");
let unsupported = Architecture::Unsupported("mips".to_string());
assert_eq!(unsupported.as_str(), "mips");
assert_eq!(unsupported.to_string(), "mips");
}
#[test]
fn test_architecture_support_check() {
assert!(Architecture::X86_64.is_supported());
assert!(Architecture::Aarch64.is_supported());
assert!(!Architecture::Unsupported("mips".to_string()).is_supported());
}
#[test]
fn test_architecture_properties() {
let x86_arch = Architecture::X86_64;
assert_eq!(x86_arch.display_name(), "Intel/AMD 64位");
assert_eq!(x86_arch.file_suffix(), "x86_64");
assert!(x86_arch.is_64bit());
assert!(x86_arch.supports_incremental_upgrade());
let arm_arch = Architecture::Aarch64;
assert_eq!(arm_arch.display_name(), "ARM 64位");
assert_eq!(arm_arch.file_suffix(), "aarch64");
assert!(arm_arch.is_64bit());
assert!(arm_arch.supports_incremental_upgrade());
let unsupported = Architecture::Unsupported("mips".to_string());
assert_eq!(unsupported.display_name(), "不支持的架构");
assert_eq!(unsupported.file_suffix(), "mips");
assert!(!unsupported.is_64bit());
assert!(!unsupported.supports_incremental_upgrade());
}
#[test]
fn test_supported_architectures() {
let supported = Architecture::supported_architectures();
assert_eq!(supported.len(), 2);
assert!(supported.contains(&Architecture::X86_64));
assert!(supported.contains(&Architecture::Aarch64));
}
#[test]
fn test_compatibility_checker() {
let current_arch = Architecture::detect();
assert!(ArchitectureCompatibilityChecker::check_compatibility(¤t_arch).is_ok());
let summary = ArchitectureCompatibilityChecker::get_system_summary();
assert!(summary.contains("操作系统"));
assert!(summary.contains("架构"));
assert!(summary.contains("64位支持"));
println!("系统摘要: {summary}");
}
#[test]
fn test_cross_architecture_support() {
let x86 = Architecture::X86_64;
let arm = Architecture::Aarch64;
assert!(
ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&x86, &x86)
);
assert!(
ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&arm, &arm)
);
assert!(
!ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&x86, &arm)
);
assert!(
!ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&arm, &x86)
);
}
#[test]
fn test_serde_compatibility() {
let x86_arch = Architecture::X86_64;
let serialized = serde_json::to_string(&x86_arch).unwrap();
assert!(serialized.contains("X86_64"));
let deserialized: Architecture = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, x86_arch);
}
#[test]
fn test_task_1_4_acceptance_criteria() {
let _x86 = Architecture::X86_64;
let _arm = Architecture::Aarch64;
let _unsupported = Architecture::Unsupported("test".to_string());
let detected_arch = Architecture::detect();
assert!(matches!(
detected_arch,
Architecture::X86_64 | Architecture::Aarch64 | Architecture::Unsupported(_)
));
assert_eq!(Architecture::X86_64.as_str(), "x86_64");
assert_eq!(Architecture::Aarch64.as_str(), "aarch64");
assert_eq!(
Architecture::from_str("x86_64").unwrap(),
Architecture::X86_64
);
assert_eq!(
Architecture::from_str("aarch64").unwrap(),
Architecture::Aarch64
);
println!("✅ Task 1.4: 架构检测模块 - 验收标准测试通过");
println!(" - ✅ Architecture枚举定义正确");
println!(
" - ✅ detect()方法能自动检测架构: {}",
detected_arch.as_str()
);
println!(" - ✅ as_str()方法返回正确字符串");
println!(" - ✅ from_str()方法能正确解析字符串");
println!(" - ✅ 单元测试覆盖全面");
}
}