adaptive_pipeline_bootstrap/platform/
windows.rs1use super::{Platform, PlatformError};
25use async_trait::async_trait;
26use std::path::{Path, PathBuf};
27
28pub struct WindowsPlatform;
33
34impl WindowsPlatform {
35 pub fn new() -> Self {
37 Self
38 }
39
40 #[cfg(windows)]
41 fn get_memory_info_impl() -> Result<(u64, u64), PlatformError> {
42 use std::mem;
43 use winapi::um::sysinfoapi::{GlobalMemoryStatusEx, MEMORYSTATUSEX};
44
45 unsafe {
46 let mut mem_status: MEMORYSTATUSEX = mem::zeroed();
47 mem_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as u32;
48
49 if GlobalMemoryStatusEx(&mut mem_status) != 0 {
50 Ok((mem_status.ullTotalPhys, mem_status.ullAvailPhys))
51 } else {
52 Err(PlatformError::Other("GlobalMemoryStatusEx failed".to_string()))
53 }
54 }
55 }
56
57 #[cfg(not(windows))]
58 fn get_memory_info_impl() -> Result<(u64, u64), PlatformError> {
59 Err(PlatformError::NotSupported(
61 "Windows APIs not available on this platform".to_string(),
62 ))
63 }
64
65 #[cfg(windows)]
66 fn get_page_size_impl() -> usize {
67 use std::mem;
68 use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
69
70 unsafe {
71 let mut sys_info: SYSTEM_INFO = mem::zeroed();
72 GetSystemInfo(&mut sys_info);
73 sys_info.dwPageSize as usize
74 }
75 }
76
77 #[cfg(not(windows))]
78 fn get_page_size_impl() -> usize {
79 4096
81 }
82
83 #[cfg(windows)]
84 fn get_cpu_count_impl() -> usize {
85 use std::mem;
86 use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
87
88 unsafe {
89 let mut sys_info: SYSTEM_INFO = mem::zeroed();
90 GetSystemInfo(&mut sys_info);
91 sys_info.dwNumberOfProcessors as usize
92 }
93 }
94
95 #[cfg(not(windows))]
96 fn get_cpu_count_impl() -> usize {
97 1
99 }
100
101 #[cfg(windows)]
102 fn is_elevated_impl() -> bool {
103 #[link(name = "shell32")]
105 extern "system" {
106 fn IsUserAnAdmin() -> i32;
107 }
108 unsafe { IsUserAnAdmin() != 0 }
109 }
110
111 #[cfg(not(windows))]
112 fn is_elevated_impl() -> bool {
113 false
115 }
116}
117
118impl Default for WindowsPlatform {
119 fn default() -> Self {
120 Self::new()
121 }
122}
123
124#[async_trait]
125impl Platform for WindowsPlatform {
126 fn page_size(&self) -> usize {
127 Self::get_page_size_impl()
128 }
129
130 fn cpu_count(&self) -> usize {
131 Self::get_cpu_count_impl()
132 }
133
134 fn total_memory(&self) -> Result<u64, PlatformError> {
135 Self::get_memory_info_impl().map(|(total, _)| total)
136 }
137
138 fn available_memory(&self) -> Result<u64, PlatformError> {
139 Self::get_memory_info_impl().map(|(_, available)| available)
140 }
141
142 fn line_separator(&self) -> &'static str {
143 "\r\n"
144 }
145
146 fn path_separator(&self) -> char {
147 ';'
148 }
149
150 fn platform_name(&self) -> &'static str {
151 "windows"
152 }
153
154 fn temp_dir(&self) -> PathBuf {
155 std::env::temp_dir()
156 }
157
158 fn is_elevated(&self) -> bool {
159 Self::is_elevated_impl()
160 }
161
162 fn set_permissions(&self, _path: &Path, _mode: u32) -> Result<(), PlatformError> {
163 Ok(())
166 }
167
168 fn is_executable(&self, path: &Path) -> bool {
169 if let Some(ext) = path.extension() {
170 let ext_lower = ext.to_string_lossy().to_lowercase();
171 matches!(ext_lower.as_str(), "exe" | "bat" | "cmd" | "com" | "ps1" | "msi")
172 } else {
173 false
174 }
175 }
176
177 async fn sync_file(&self, file: &tokio::fs::File) -> Result<(), PlatformError> {
178 file.sync_all().await?;
180 Ok(())
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_windows_platform_basics() {
190 let platform = WindowsPlatform::new();
191
192 assert!(platform.cpu_count() >= 1);
194
195 let page_size = platform.page_size();
197 assert!(page_size >= 512);
198 assert!(page_size <= 65536);
199 }
200
201 #[test]
202 fn test_windows_platform_constants() {
203 let platform = WindowsPlatform::new();
204
205 assert_eq!(platform.line_separator(), "\r\n");
206 assert_eq!(platform.path_separator(), ';');
207 assert_eq!(platform.platform_name(), "windows");
208 }
209
210 #[test]
211 fn test_executable_extensions() {
212 let platform = WindowsPlatform::new();
213
214 assert!(platform.is_executable(Path::new("program.exe")));
215 assert!(platform.is_executable(Path::new("script.bat")));
216 assert!(platform.is_executable(Path::new("script.cmd")));
217 assert!(platform.is_executable(Path::new("installer.msi")));
218 assert!(!platform.is_executable(Path::new("document.txt")));
219 assert!(!platform.is_executable(Path::new("noextension")));
220 }
221
222 #[test]
223 fn test_temp_dir() {
224 let platform = WindowsPlatform::new();
225 let temp = platform.temp_dir();
226 assert!(!temp.as_os_str().is_empty());
228 }
229}