Skip to main content

client_core/
architecture.rs

1//! # 架构检测模块
2//!
3//! 提供跨平台的系统架构检测功能,支持:
4//! - 自动检测当前系统架构
5//! - 架构字符串转换
6//! - 架构支持检查
7//! - 友好的错误处理
8
9use anyhow::Result;
10use serde::{Deserialize, Serialize};
11use std::fmt::{self, Display};
12use std::str::FromStr;
13use tracing::warn;
14
15/// 支持的系统架构枚举
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum Architecture {
18    /// x86_64 架构(Intel/AMD 64位)
19    X86_64,
20    /// aarch64 架构(ARM 64位)
21    Aarch64,
22    /// 不支持的架构
23    Unsupported(String),
24}
25
26impl Architecture {
27    /// 自动检测当前系统架构
28    ///
29    /// 使用标准库的 `std::env::consts::ARCH` 进行检测
30    ///
31    /// # 示例
32    /// ```
33    /// use client_core::architecture::Architecture;
34    ///
35    /// let arch = Architecture::detect();
36    /// println!("当前架构: {}", arch);
37    /// ```
38    pub fn detect() -> Self {
39        let arch_str = std::env::consts::ARCH;
40        Self::from_str(arch_str).unwrap_or_else(|_| {
41            warn!("Detected unknown architecture: {}", arch_str);
42            Self::Unsupported(arch_str.to_string())
43        })
44    }
45
46    /// 转换为字符串表示
47    ///
48    /// # 示例
49    /// ```
50    /// use client_core::architecture::Architecture;
51    ///
52    /// let arch = Architecture::X86_64;
53    /// assert_eq!(arch.as_str(), "x86_64");
54    /// ```
55    pub fn as_str(&self) -> &str {
56        match self {
57            Self::X86_64 => "x86_64",
58            Self::Aarch64 => "aarch64",
59            Self::Unsupported(arch) => arch,
60        }
61    }
62
63    /// 从字符串解析架构
64    ///
65    /// 支持多种常见的架构字符串格式
66    ///
67    /// # 示例
68    /// ```
69    /// use client_core::architecture::Architecture;
70    ///
71    /// let arch = Architecture::from_str("x86_64").unwrap();
72    /// assert_eq!(arch, Architecture::X86_64);
73    ///
74    /// let arch = Architecture::from_str("arm64").unwrap();
75    /// assert_eq!(arch, Architecture::Aarch64);
76    /// ```
77    pub fn from_str(arch_str: &str) -> Result<Self> {
78        match arch_str.to_lowercase().as_str() {
79            "x86_64" | "amd64" | "x64" => Ok(Self::X86_64),
80            "aarch64" | "arm64" | "armv8" => Ok(Self::Aarch64),
81            _ => Err(anyhow::anyhow!("Unsupported architecture: {}", arch_str)),
82        }
83    }
84
85    /// 检查架构是否受支持
86    ///
87    /// # 示例
88    /// ```
89    /// use client_core::architecture::Architecture;
90    ///
91    /// let arch = Architecture::X86_64;
92    /// assert!(arch.is_supported());
93    ///
94    /// let unsupported = Architecture::Unsupported("mips".to_string());
95    /// assert!(!unsupported.is_supported());
96    /// ```
97    pub fn is_supported(&self) -> bool {
98        match self {
99            Self::X86_64 | Self::Aarch64 => true,
100            Self::Unsupported(_) => false,
101        }
102    }
103
104    /// 获取架构的显示名称(用于用户界面)
105    ///
106    /// # 示例
107    /// ```
108    /// use client_core::architecture::Architecture;
109    ///
110    /// let arch = Architecture::X86_64;
111    /// assert_eq!(arch.display_name(), "Intel/AMD 64位");
112    /// ```
113    pub fn display_name(&self) -> &str {
114        match self {
115            Self::X86_64 => "Intel/AMD 64-bit",
116            Self::Aarch64 => "ARM 64-bit",
117            Self::Unsupported(_) => "Unsupported architecture",
118        }
119    }
120
121    /// 获取架构对应的文件名后缀
122    ///
123    /// 用于构建特定架构的文件名
124    ///
125    /// # 示例
126    /// ```
127    /// use client_core::architecture::Architecture;
128    ///
129    /// let arch = Architecture::X86_64;
130    /// assert_eq!(arch.file_suffix(), "x86_64");
131    /// ```
132    pub fn file_suffix(&self) -> &str {
133        match self {
134            Self::X86_64 => "x86_64",
135            Self::Aarch64 => "aarch64",
136            Self::Unsupported(arch) => arch,
137        }
138    }
139
140    /// 检查是否为64位架构
141    pub fn is_64bit(&self) -> bool {
142        match self {
143            Self::X86_64 | Self::Aarch64 => true,
144            Self::Unsupported(_) => false, // 保守起见,假设不支持的架构不是64位
145        }
146    }
147
148    /// 获取所有支持的架构列表
149    pub fn supported_architectures() -> Vec<Architecture> {
150        vec![Self::X86_64, Self::Aarch64]
151    }
152
153    /// 检查当前系统是否支持增量升级功能
154    ///
155    /// 只有支持的架构才能使用增量升级
156    pub fn supports_incremental_upgrade(&self) -> bool {
157        self.is_supported()
158    }
159}
160
161impl Display for Architecture {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        write!(f, "{}", self.as_str())
164    }
165}
166
167impl FromStr for Architecture {
168    type Err = anyhow::Error;
169
170    fn from_str(s: &str) -> Result<Self> {
171        Architecture::from_str(s)
172    }
173}
174
175/// 架构兼容性检查器
176pub struct ArchitectureCompatibilityChecker;
177
178impl ArchitectureCompatibilityChecker {
179    /// 检查目标架构是否与当前系统兼容
180    ///
181    /// # 参数
182    /// - `target_arch`: 目标架构
183    ///
184    /// # 返回
185    /// - `Ok(())`: 兼容
186    /// - `Err(_)`: 不兼容,包含错误信息
187    pub fn check_compatibility(target_arch: &Architecture) -> Result<()> {
188        let current_arch = Architecture::detect();
189
190        if current_arch == *target_arch {
191            Ok(())
192        } else {
193            Err(anyhow::anyhow!(format!(
194                "Architecture mismatch: current system is {}, target architecture is {}",
195                current_arch.display_name(),
196                target_arch.display_name()
197            )))
198        }
199    }
200
201    /// 获取系统信息摘要
202    pub fn get_system_summary() -> String {
203        let arch = Architecture::detect();
204        format!(
205            "OS: {}, architecture: {} ({}), 64-bit support: {}",
206            std::env::consts::OS,
207            arch.as_str(),
208            arch.display_name(),
209            if arch.is_64bit() { "yes" } else { "no" }
210        )
211    }
212
213    /// 检查是否支持跨架构操作
214    ///
215    /// 某些操作(如模拟)可能支持跨架构
216    pub fn supports_cross_architecture_operation(
217        from_arch: &Architecture,
218        to_arch: &Architecture,
219    ) -> bool {
220        // 目前不支持跨架构操作
221        // 未来可以通过模拟器(如qemu)支持
222        from_arch == to_arch
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    #[test]
231    fn test_architecture_detection() {
232        let arch = Architecture::detect();
233
234        // 检测应该总是返回一个有效的架构
235        assert!(matches!(
236            arch,
237            Architecture::X86_64 | Architecture::Aarch64 | Architecture::Unsupported(_)
238        ));
239
240        // 显示检测到的架构
241        println!("检测到的架构: {} ({})", arch.as_str(), arch.display_name());
242    }
243
244    #[test]
245    fn test_architecture_parsing() {
246        // 测试x86_64变体
247        assert_eq!(
248            Architecture::from_str("x86_64").unwrap(),
249            Architecture::X86_64
250        );
251        assert_eq!(
252            Architecture::from_str("amd64").unwrap(),
253            Architecture::X86_64
254        );
255        assert_eq!(Architecture::from_str("x64").unwrap(), Architecture::X86_64);
256
257        // 测试aarch64变体
258        assert_eq!(
259            Architecture::from_str("aarch64").unwrap(),
260            Architecture::Aarch64
261        );
262        assert_eq!(
263            Architecture::from_str("arm64").unwrap(),
264            Architecture::Aarch64
265        );
266        assert_eq!(
267            Architecture::from_str("armv8").unwrap(),
268            Architecture::Aarch64
269        );
270
271        // 测试大小写不敏感
272        assert_eq!(
273            Architecture::from_str("X86_64").unwrap(),
274            Architecture::X86_64
275        );
276        assert_eq!(
277            Architecture::from_str("ARM64").unwrap(),
278            Architecture::Aarch64
279        );
280
281        // 测试不支持的架构
282        assert!(Architecture::from_str("mips").is_err());
283        assert!(Architecture::from_str("riscv").is_err());
284    }
285
286    #[test]
287    fn test_architecture_string_conversion() {
288        let x86_arch = Architecture::X86_64;
289        assert_eq!(x86_arch.as_str(), "x86_64");
290        assert_eq!(x86_arch.to_string(), "x86_64");
291
292        let arm_arch = Architecture::Aarch64;
293        assert_eq!(arm_arch.as_str(), "aarch64");
294        assert_eq!(arm_arch.to_string(), "aarch64");
295
296        let unsupported = Architecture::Unsupported("mips".to_string());
297        assert_eq!(unsupported.as_str(), "mips");
298        assert_eq!(unsupported.to_string(), "mips");
299    }
300
301    #[test]
302    fn test_architecture_support_check() {
303        assert!(Architecture::X86_64.is_supported());
304        assert!(Architecture::Aarch64.is_supported());
305        assert!(!Architecture::Unsupported("mips".to_string()).is_supported());
306    }
307
308    #[test]
309    fn test_architecture_properties() {
310        let x86_arch = Architecture::X86_64;
311        assert_eq!(x86_arch.display_name(), "Intel/AMD 64位");
312        assert_eq!(x86_arch.file_suffix(), "x86_64");
313        assert!(x86_arch.is_64bit());
314        assert!(x86_arch.supports_incremental_upgrade());
315
316        let arm_arch = Architecture::Aarch64;
317        assert_eq!(arm_arch.display_name(), "ARM 64位");
318        assert_eq!(arm_arch.file_suffix(), "aarch64");
319        assert!(arm_arch.is_64bit());
320        assert!(arm_arch.supports_incremental_upgrade());
321
322        let unsupported = Architecture::Unsupported("mips".to_string());
323        assert_eq!(unsupported.display_name(), "不支持的架构");
324        assert_eq!(unsupported.file_suffix(), "mips");
325        assert!(!unsupported.is_64bit());
326        assert!(!unsupported.supports_incremental_upgrade());
327    }
328
329    #[test]
330    fn test_supported_architectures() {
331        let supported = Architecture::supported_architectures();
332        assert_eq!(supported.len(), 2);
333        assert!(supported.contains(&Architecture::X86_64));
334        assert!(supported.contains(&Architecture::Aarch64));
335    }
336
337    #[test]
338    fn test_compatibility_checker() {
339        let current_arch = Architecture::detect();
340
341        // 与自身兼容
342        assert!(ArchitectureCompatibilityChecker::check_compatibility(&current_arch).is_ok());
343
344        // 系统摘要应该包含有用信息
345        let summary = ArchitectureCompatibilityChecker::get_system_summary();
346        assert!(summary.contains("操作系统"));
347        assert!(summary.contains("架构"));
348        assert!(summary.contains("64位支持"));
349
350        println!("系统摘要: {summary}");
351    }
352
353    #[test]
354    fn test_cross_architecture_support() {
355        let x86 = Architecture::X86_64;
356        let arm = Architecture::Aarch64;
357
358        // 相同架构支持
359        assert!(
360            ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&x86, &x86)
361        );
362        assert!(
363            ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&arm, &arm)
364        );
365
366        // 跨架构目前不支持
367        assert!(
368            !ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&x86, &arm)
369        );
370        assert!(
371            !ArchitectureCompatibilityChecker::supports_cross_architecture_operation(&arm, &x86)
372        );
373    }
374
375    #[test]
376    fn test_serde_compatibility() {
377        let x86_arch = Architecture::X86_64;
378
379        // 测试序列化
380        let serialized = serde_json::to_string(&x86_arch).unwrap();
381        assert!(serialized.contains("X86_64"));
382
383        // 测试反序列化
384        let deserialized: Architecture = serde_json::from_str(&serialized).unwrap();
385        assert_eq!(deserialized, x86_arch);
386    }
387
388    // Task 1.4 验收标准测试
389    #[test]
390    fn test_task_1_4_acceptance_criteria() {
391        // 验收标准:Architecture枚举定义正确
392        let _x86 = Architecture::X86_64;
393        let _arm = Architecture::Aarch64;
394        let _unsupported = Architecture::Unsupported("test".to_string());
395
396        // 验收标准:detect()方法能自动检测架构
397        let detected_arch = Architecture::detect();
398        assert!(matches!(
399            detected_arch,
400            Architecture::X86_64 | Architecture::Aarch64 | Architecture::Unsupported(_)
401        ));
402
403        // 验收标准:as_str()方法返回正确字符串
404        assert_eq!(Architecture::X86_64.as_str(), "x86_64");
405        assert_eq!(Architecture::Aarch64.as_str(), "aarch64");
406
407        // 验收标准:from_str()方法能正确解析字符串
408        assert_eq!(
409            Architecture::from_str("x86_64").unwrap(),
410            Architecture::X86_64
411        );
412        assert_eq!(
413            Architecture::from_str("aarch64").unwrap(),
414            Architecture::Aarch64
415        );
416
417        // 验收标准:添加了单元测试覆盖
418        // (本测试本身就是单元测试的一部分)
419
420        println!("✅ Task 1.4: 架构检测模块 - 验收标准测试通过");
421        println!("   - ✅ Architecture枚举定义正确");
422        println!(
423            "   - ✅ detect()方法能自动检测架构: {}",
424            detected_arch.as_str()
425        );
426        println!("   - ✅ as_str()方法返回正确字符串");
427        println!("   - ✅ from_str()方法能正确解析字符串");
428        println!("   - ✅ 单元测试覆盖全面");
429    }
430}