1 use serde::{Deserialize, Deserializer, Serialize}; 2 3 /// 目标处理器架构 4 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord)] 5 pub enum TargetArch { 6 #[default] 7 X86_64, 8 RiscV64, 9 AArch64, 10 } 11 12 impl TargetArch { 13 /// 期望的目标处理器架构(如果修改了枚举,那一定要修改这里) 14 pub const EXPECTED: [&'static str; 3] = ["x86_64", "riscv64", "aarch64"]; 15 } 16 17 impl TryFrom<&str> for TargetArch { 18 type Error = String; 19 try_from(value: &str) -> Result<Self, Self::Error>20 fn try_from(value: &str) -> Result<Self, Self::Error> { 21 match value.trim().to_ascii_lowercase().as_str() { 22 "x86_64" => Ok(TargetArch::X86_64), 23 "riscv64" => Ok(TargetArch::RiscV64), 24 "aarch64" => Ok(TargetArch::AArch64), 25 _ => Err(format!("Unknown target arch: {}", value)), 26 } 27 } 28 } 29 30 impl From<TargetArch> for &str { from(val: TargetArch) -> Self31 fn from(val: TargetArch) -> Self { 32 match val { 33 TargetArch::X86_64 => "x86_64", 34 TargetArch::RiscV64 => "riscv64", 35 TargetArch::AArch64 => "aarch64", 36 } 37 } 38 } 39 40 impl From<TargetArch> for String { from(val: TargetArch) -> Self41 fn from(val: TargetArch) -> Self { 42 let x: &str = val.into(); 43 x.to_string() 44 } 45 } 46 47 impl<'de> Deserialize<'de> for TargetArch { deserialize<D>(deserializer: D) -> Result<TargetArch, D::Error> where D: Deserializer<'de>,48 fn deserialize<D>(deserializer: D) -> Result<TargetArch, D::Error> 49 where 50 D: Deserializer<'de>, 51 { 52 let s = String::deserialize(deserializer)?; 53 54 let r = TargetArch::try_from(s.as_str()); 55 match r { 56 Ok(v) => Ok(v), 57 Err(_) => Err(serde::de::Error::invalid_value( 58 serde::de::Unexpected::Str(s.as_str()), 59 &format!("Expected one of {:?}", TargetArch::EXPECTED).as_str(), 60 )), 61 } 62 } 63 } 64 65 impl Serialize for TargetArch { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,66 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 67 where 68 S: serde::Serializer, 69 { 70 let string: String = Into::into(*self); 71 serializer.serialize_str(string.as_str()) 72 } 73 } 74 75 #[cfg(test)] 76 mod tests { 77 use super::*; 78 use serde_json; 79 80 #[test] test_default()81 fn test_default() { 82 let default_arch = TargetArch::default(); 83 assert_eq!(default_arch, TargetArch::X86_64); 84 } 85 86 #[test] test_try_from_valid()87 fn test_try_from_valid() { 88 let x86_64 = TargetArch::try_from("x86_64").unwrap(); 89 assert_eq!(x86_64, TargetArch::X86_64); 90 91 let riscv64 = TargetArch::try_from("riscv64").unwrap(); 92 assert_eq!(riscv64, TargetArch::RiscV64); 93 94 let aarch64 = TargetArch::try_from("aarch64").unwrap(); 95 assert_eq!(aarch64, TargetArch::AArch64); 96 } 97 98 #[test] test_try_from_invalid()99 fn test_try_from_invalid() { 100 let result = TargetArch::try_from("unknown"); 101 assert!(result.is_err()); 102 assert_eq!(result.unwrap_err(), "Unknown target arch: unknown"); 103 } 104 105 #[test] test_into_str()106 fn test_into_str() { 107 let x86_64: &str = TargetArch::X86_64.into(); 108 assert_eq!(x86_64, "x86_64"); 109 110 let riscv64: &str = TargetArch::RiscV64.into(); 111 assert_eq!(riscv64, "riscv64"); 112 } 113 114 #[test] test_into_string()115 fn test_into_string() { 116 let x86_64: String = TargetArch::X86_64.into(); 117 assert_eq!(x86_64, "x86_64"); 118 119 let riscv64: String = TargetArch::RiscV64.into(); 120 assert_eq!(riscv64, "riscv64"); 121 } 122 123 #[test] test_deserialize_valid()124 fn test_deserialize_valid() { 125 let json_x86_64 = r#""x86_64""#; 126 let x86_64: TargetArch = serde_json::from_str(json_x86_64).unwrap(); 127 assert_eq!(x86_64, TargetArch::X86_64); 128 129 let json_riscv64 = r#""riscv64""#; 130 let riscv64: TargetArch = serde_json::from_str(json_riscv64).unwrap(); 131 assert_eq!(riscv64, TargetArch::RiscV64); 132 } 133 134 #[test] test_deserialize_invalid()135 fn test_deserialize_invalid() { 136 let json_unknown = r#""unknown""#; 137 let result: Result<TargetArch, _> = serde_json::from_str(json_unknown); 138 assert!(result.is_err()); 139 } 140 141 #[test] test_serialize()142 fn test_serialize() { 143 let x86_64 = TargetArch::X86_64; 144 let serialized_x86_64 = serde_json::to_string(&x86_64).unwrap(); 145 assert_eq!(serialized_x86_64, r#""x86_64""#); 146 147 let riscv64 = TargetArch::RiscV64; 148 let serialized_riscv64 = serde_json::to_string(&riscv64).unwrap(); 149 assert_eq!(serialized_riscv64, r#""riscv64""#); 150 } 151 } 152