openhawk_core/
platform.rs1#[derive(Debug, Clone, PartialEq)]
5pub enum Os {
6 Windows,
7 MacOs,
8 Linux,
9 Other(String),
10}
11
12#[derive(Debug, Clone, PartialEq)]
13pub enum Arch {
14 X86_64,
15 Arm64,
16 Other(String),
17}
18
19#[derive(Debug, Clone, PartialEq)]
20pub enum IpcMechanism {
21 UnixDomainSocket,
22 NamedPipe,
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub enum SnapshotStrategy {
27 ApfsReflink,
28 BtrfsCow,
29 FileCopyFallback,
30}
31
32#[derive(Debug, Clone)]
33pub struct PlatformConfig {
34 pub os: Os,
35 pub arch: Arch,
36 pub ipc: IpcMechanism,
37 pub snapshot_strategy: SnapshotStrategy,
38 pub keychain_available: bool,
39}
40
41impl PlatformConfig {
42 pub fn detect() -> Self {
43 let os = detect_os();
44 let arch = detect_arch();
45 let ipc = detect_ipc(&os);
46 let snapshot_strategy = detect_snapshot_strategy(&os);
47 let keychain_available = detect_keychain(&os);
48 PlatformConfig { os, arch, ipc, snapshot_strategy, keychain_available }
49 }
50}
51
52fn detect_os() -> Os {
53 #[cfg(target_os = "macos")]
54 return Os::MacOs;
55 #[cfg(target_os = "windows")]
56 return Os::Windows;
57 #[cfg(target_os = "linux")]
58 return Os::Linux;
59 #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
60 return Os::Other(std::env::consts::OS.to_string());
61}
62
63fn detect_arch() -> Arch {
64 #[cfg(target_arch = "x86_64")]
65 return Arch::X86_64;
66 #[cfg(target_arch = "aarch64")]
67 return Arch::Arm64;
68 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
69 return Arch::Other(std::env::consts::ARCH.to_string());
70}
71
72pub fn detect_ipc(os: &Os) -> IpcMechanism {
73 match os {
74 Os::Windows => IpcMechanism::NamedPipe,
75 _ => IpcMechanism::UnixDomainSocket,
76 }
77}
78
79pub fn detect_snapshot_strategy(os: &Os) -> SnapshotStrategy {
80 match os {
81 Os::MacOs => SnapshotStrategy::ApfsReflink,
82 Os::Linux => SnapshotStrategy::BtrfsCow,
83 _ => SnapshotStrategy::FileCopyFallback,
84 }
85}
86
87pub fn detect_keychain(os: &Os) -> bool {
88 matches!(os, Os::MacOs | Os::Windows)
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_detect_returns_current_os() {
97 let config = PlatformConfig::detect();
98 #[cfg(target_os = "macos")]
99 assert_eq!(config.os, Os::MacOs);
100 #[cfg(target_os = "windows")]
101 assert_eq!(config.os, Os::Windows);
102 #[cfg(target_os = "linux")]
103 assert_eq!(config.os, Os::Linux);
104 }
105
106 #[test]
107 fn test_detect_returns_current_arch() {
108 let config = PlatformConfig::detect();
109 #[cfg(target_arch = "x86_64")]
110 assert_eq!(config.arch, Arch::X86_64);
111 #[cfg(target_arch = "aarch64")]
112 assert_eq!(config.arch, Arch::Arm64);
113 }
114
115 #[test]
116 fn test_macos_subsystem_config() {
117 let config = PlatformConfig {
118 os: Os::MacOs,
119 arch: Arch::Arm64,
120 ipc: detect_ipc(&Os::MacOs),
121 snapshot_strategy: detect_snapshot_strategy(&Os::MacOs),
122 keychain_available: detect_keychain(&Os::MacOs),
123 };
124 assert_eq!(config.ipc, IpcMechanism::UnixDomainSocket);
125 assert_eq!(config.snapshot_strategy, SnapshotStrategy::ApfsReflink);
126 assert!(config.keychain_available);
127 }
128
129 #[test]
130 fn test_windows_subsystem_config() {
131 let config = PlatformConfig {
132 os: Os::Windows,
133 arch: Arch::X86_64,
134 ipc: detect_ipc(&Os::Windows),
135 snapshot_strategy: detect_snapshot_strategy(&Os::Windows),
136 keychain_available: detect_keychain(&Os::Windows),
137 };
138 assert_eq!(config.ipc, IpcMechanism::NamedPipe);
139 assert_eq!(config.snapshot_strategy, SnapshotStrategy::FileCopyFallback);
140 assert!(config.keychain_available);
141 }
142
143 #[test]
144 fn test_linux_subsystem_config() {
145 let config = PlatformConfig {
146 os: Os::Linux,
147 arch: Arch::X86_64,
148 ipc: detect_ipc(&Os::Linux),
149 snapshot_strategy: detect_snapshot_strategy(&Os::Linux),
150 keychain_available: detect_keychain(&Os::Linux),
151 };
152 assert_eq!(config.ipc, IpcMechanism::UnixDomainSocket);
153 assert_eq!(config.snapshot_strategy, SnapshotStrategy::BtrfsCow);
154 assert!(!config.keychain_available);
155 }
156
157 #[test]
158 fn test_other_os_subsystem_config() {
159 let other = Os::Other("freebsd".to_string());
160 assert_eq!(detect_ipc(&other), IpcMechanism::UnixDomainSocket);
161 assert_eq!(detect_snapshot_strategy(&other), SnapshotStrategy::FileCopyFallback);
162 assert!(!detect_keychain(&other));
163 }
164
165 #[test]
166 fn test_detected_ipc_matches_os() {
167 let config = PlatformConfig::detect();
168 #[cfg(target_os = "windows")]
169 assert_eq!(config.ipc, IpcMechanism::NamedPipe);
170 #[cfg(not(target_os = "windows"))]
171 assert_eq!(config.ipc, IpcMechanism::UnixDomainSocket);
172 }
173
174 #[test]
175 fn test_detected_snapshot_strategy_matches_os() {
176 let config = PlatformConfig::detect();
177 #[cfg(target_os = "macos")]
178 assert_eq!(config.snapshot_strategy, SnapshotStrategy::ApfsReflink);
179 #[cfg(target_os = "linux")]
180 assert_eq!(config.snapshot_strategy, SnapshotStrategy::BtrfsCow);
181 #[cfg(target_os = "windows")]
182 assert_eq!(config.snapshot_strategy, SnapshotStrategy::FileCopyFallback);
183 }
184
185 #[test]
186 fn test_detected_keychain_matches_os() {
187 let config = PlatformConfig::detect();
188 #[cfg(any(target_os = "macos", target_os = "windows"))]
189 assert!(config.keychain_available);
190 #[cfg(target_os = "linux")]
191 assert!(!config.keychain_available);
192 }
193}