qorzen_oxide/platform/
mod.rs

1// src/platform/mod.rs - Core platform abstraction
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::Arc;
7use tokio::sync::RwLock;
8use uuid::Uuid;
9
10use crate::error::Result;
11use crate::manager::{ManagedState, Manager, ManagerStatus, PlatformRequirements};
12
13#[cfg(not(target_arch = "wasm32"))]
14pub mod native;
15#[cfg(target_arch = "wasm32")]
16pub mod web;
17
18pub mod database;
19pub mod filesystem;
20pub mod network;
21pub mod storage;
22
23// Re-export types
24use crate::platform::database::DatabaseArc;
25use crate::platform::filesystem::FileSystemArc;
26use crate::platform::network::NetworkArc;
27use crate::platform::storage::StorageArc;
28use crate::Error;
29pub use database::{DatabaseProvider, Migration, QueryResult, Row, Transaction};
30pub use filesystem::{FileInfo, FileMetadata, FileSystemProvider};
31pub use network::{NetworkProvider, NetworkRequest, NetworkResponse};
32pub use storage::StorageProvider;
33
34/// Platform capabilities detection
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct PlatformCapabilities {
37    pub has_filesystem: bool,
38    pub has_database: bool,
39    pub has_background_tasks: bool,
40    pub has_push_notifications: bool,
41    pub has_biometric_auth: bool,
42    pub has_camera: bool,
43    pub has_location: bool,
44    pub max_file_size: Option<u64>,
45    pub supported_formats: Vec<String>,
46    pub platform_name: String,
47    pub platform_version: String,
48}
49
50impl Default for PlatformCapabilities {
51    fn default() -> Self {
52        Self {
53            has_filesystem: false,
54            has_database: false,
55            has_background_tasks: false,
56            has_push_notifications: false,
57            has_biometric_auth: false,
58            has_camera: false,
59            has_location: false,
60            max_file_size: None,
61            supported_formats: Vec::new(),
62            platform_name: "unknown".to_string(),
63            platform_version: "unknown".to_string(),
64        }
65    }
66}
67
68/// Main platform manager that coordinates all platform providers
69pub struct PlatformManager {
70    state: ManagedState,
71    filesystem: FileSystemArc,
72    database: DatabaseArc,
73    network: NetworkArc,
74    storage: StorageArc,
75    capabilities: PlatformCapabilities,
76}
77
78impl std::fmt::Debug for PlatformManager {
79    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        f.debug_struct("PlatformManager")
81            .field("capabilities", &self.capabilities)
82            .finish()
83    }
84}
85
86impl PlatformManager {
87    /// Creates a new platform manager with platform-specific providers
88    pub fn new() -> Result<Self> {
89        let capabilities = Self::detect_capabilities();
90
91        #[cfg(not(target_arch = "wasm32"))]
92        let providers = native::create_providers()?;
93
94        #[cfg(target_arch = "wasm32")]
95        let providers = web::create_providers()?;
96
97        Ok(Self {
98            state: ManagedState::new(Uuid::new_v4(), "platform_manager"),
99            filesystem: providers.filesystem,
100            database: providers.database,
101            network: providers.network,
102            storage: providers.storage,
103            capabilities,
104        })
105    }
106
107    /// Detects platform capabilities
108    pub fn detect_capabilities() -> PlatformCapabilities {
109        #[cfg(not(target_arch = "wasm32"))]
110        return native::detect_capabilities();
111
112        #[cfg(target_arch = "wasm32")]
113        return web::detect_capabilities();
114    }
115
116    /// Returns platform capabilities
117    pub fn capabilities(&self) -> &PlatformCapabilities {
118        &self.capabilities
119    }
120
121    /// Returns filesystem provider
122    pub fn filesystem(&self) -> &dyn FileSystemProvider {
123        self.filesystem.as_ref()
124    }
125    pub fn filesystem_arc(&self) -> FileSystemArc {
126        Arc::clone(&self.filesystem)
127    }
128
129    /// Returns database provider
130    pub fn database(&self) -> &dyn DatabaseProvider {
131        self.database.as_ref()
132    }
133    pub fn database_arc(&self) -> DatabaseArc {
134        Arc::clone(&self.database)
135    }
136
137    /// Returns network provider
138    pub fn network(&self) -> &dyn NetworkProvider {
139        self.network.as_ref()
140    }
141
142    /// Returns storage provider
143    pub fn storage(&self) -> &dyn StorageProvider {
144        self.storage.as_ref()
145    }
146}
147
148#[cfg(not(target_arch = "wasm32"))]
149#[async_trait]
150impl Manager for PlatformManager {
151    fn name(&self) -> &str {
152        "platform_manager"
153    }
154
155    fn id(&self) -> Uuid {
156        self.state.id()
157    }
158
159    async fn initialize(&mut self) -> Result<()> {
160        self.state
161            .set_state(crate::manager::ManagerState::Initializing)
162            .await;
163
164        // Platform-specific initialization
165        #[cfg(not(target_arch = "wasm32"))]
166        native::initialize().await?;
167
168        #[cfg(target_arch = "wasm32")]
169        web::initialize().await?;
170
171        self.state
172            .set_state(crate::manager::ManagerState::Running)
173            .await;
174        Ok(())
175    }
176
177    async fn shutdown(&mut self) -> Result<()> {
178        self.state
179            .set_state(crate::manager::ManagerState::ShuttingDown)
180            .await;
181
182        // Platform-specific cleanup
183        #[cfg(not(target_arch = "wasm32"))]
184        native::cleanup().await?;
185
186        #[cfg(target_arch = "wasm32")]
187        web::cleanup().await?;
188
189        self.state
190            .set_state(crate::manager::ManagerState::Shutdown)
191            .await;
192        Ok(())
193    }
194
195    async fn status(&self) -> ManagerStatus {
196        let mut status = self.state.status().await;
197        status.add_metadata(
198            "platform",
199            serde_json::json!(self.capabilities.platform_name),
200        );
201        status.add_metadata(
202            "capabilities",
203            serde_json::to_value(&self.capabilities).unwrap_or_default(),
204        );
205        status
206    }
207
208    fn platform_requirements(&self) -> PlatformRequirements {
209        PlatformRequirements {
210            requires_filesystem: true,
211            requires_network: true,
212            requires_database: true,
213            requires_native_apis: false,
214            minimum_permissions: vec!["platform.access".to_string()],
215        }
216    }
217}
218
219#[cfg(target_arch = "wasm32")]
220#[async_trait(?Send)]
221impl Manager for PlatformManager {
222    fn name(&self) -> &str {
223        "platform_manager"
224    }
225
226    fn id(&self) -> Uuid {
227        self.state.id()
228    }
229
230    async fn initialize(&mut self) -> Result<()> {
231        self.state
232            .set_state(crate::manager::ManagerState::Initializing)
233            .await;
234
235        // Platform-specific initialization
236        #[cfg(not(target_arch = "wasm32"))]
237        native::initialize().await?;
238
239        #[cfg(target_arch = "wasm32")]
240        web::initialize().await?;
241
242        self.state
243            .set_state(crate::manager::ManagerState::Running)
244            .await;
245        Ok(())
246    }
247
248    async fn shutdown(&mut self) -> Result<()> {
249        self.state
250            .set_state(crate::manager::ManagerState::ShuttingDown)
251            .await;
252
253        // Platform-specific cleanup
254        #[cfg(not(target_arch = "wasm32"))]
255        native::cleanup().await?;
256
257        #[cfg(target_arch = "wasm32")]
258        web::cleanup().await?;
259
260        self.state
261            .set_state(crate::manager::ManagerState::Shutdown)
262            .await;
263        Ok(())
264    }
265
266    async fn status(&self) -> ManagerStatus {
267        let mut status = self.state.status().await;
268        status.add_metadata(
269            "platform",
270            serde_json::json!(self.capabilities.platform_name),
271        );
272        status.add_metadata(
273            "capabilities",
274            serde_json::to_value(&self.capabilities).unwrap_or_default(),
275        );
276        status
277    }
278
279    fn platform_requirements(&self) -> PlatformRequirements {
280        PlatformRequirements {
281            requires_filesystem: true,
282            requires_network: true,
283            requires_database: true,
284            requires_native_apis: false,
285            minimum_permissions: vec!["platform.access".to_string()],
286        }
287    }
288}
289
290/// Platform provider collection
291pub struct PlatformProviders {
292    pub filesystem: FileSystemArc,
293    pub database: DatabaseArc,
294    pub network: NetworkArc,
295    pub storage: StorageArc,
296}
297
298/// Mock filesystem implementation for testing
299#[derive(Debug, Default)]
300pub struct MockFileSystem {
301    files: Arc<RwLock<HashMap<String, Vec<u8>>>>,
302}
303
304impl MockFileSystem {
305    pub fn new() -> Self {
306        Self {
307            files: Arc::new(RwLock::new(HashMap::new())),
308        }
309    }
310}
311
312impl filesystem::FileSystemBounds for MockFileSystem {}
313
314#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
315#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
316impl FileSystemProvider for MockFileSystem {
317    async fn read_file(&self, path: &str) -> Result<Vec<u8>> {
318        self.files
319            .read()
320            .await
321            .get(path)
322            .cloned()
323            .ok_or_else(|| Error::platform("mock", "filesystem", "File not found"))
324    }
325
326    async fn write_file(&self, path: &str, data: &[u8]) -> Result<()> {
327        self.files
328            .write()
329            .await
330            .insert(path.to_string(), data.to_vec());
331        Ok(())
332    }
333
334    async fn delete_file(&self, path: &str) -> Result<()> {
335        self.files.write().await.remove(path);
336        Ok(())
337    }
338
339    async fn list_directory(&self, _path: &str) -> Result<Vec<FileInfo>> {
340        Ok(Vec::new())
341    }
342
343    async fn create_directory(&self, _path: &str) -> Result<()> {
344        Ok(())
345    }
346
347    async fn file_exists(&self, path: &str) -> bool {
348        self.files.read().await.contains_key(path)
349    }
350
351    async fn get_metadata(&self, _path: &str) -> Result<FileMetadata> {
352        Ok(FileMetadata {
353            size: 0,
354            is_directory: false,
355            is_readonly: false,
356            created: None,
357            modified: chrono::Utc::now(),
358            accessed: None,
359        })
360    }
361}