Skip to main content

moonpool_sim/storage/
provider.rs

1//! Simulated storage provider implementation.
2
3use super::file::SimStorageFile;
4use crate::SimulationError;
5use crate::sim::WeakSimWorld;
6use async_trait::async_trait;
7use moonpool_core::{OpenOptions, StorageProvider};
8use std::io;
9
10/// Map a SimulationError to an appropriate io::Error kind.
11fn map_sim_error(e: SimulationError) -> io::Error {
12    let msg = e.to_string();
13    if msg.contains("already exists") {
14        io::Error::new(io::ErrorKind::AlreadyExists, msg)
15    } else if msg.contains("not found") {
16        io::Error::new(io::ErrorKind::NotFound, msg)
17    } else {
18        io::Error::other(msg)
19    }
20}
21
22/// Simulated storage provider for deterministic testing.
23///
24/// This provider wraps a `WeakSimWorld` and implements the `StorageProvider`
25/// trait to enable deterministic storage simulation with fault injection.
26///
27/// # Example
28///
29/// ```ignore
30/// let sim = SimWorld::new();
31/// let provider = SimStorageProvider::new(sim.weak());
32///
33/// let file = provider.open("test.txt", OpenOptions::create_write()).await?;
34/// ```
35#[derive(Debug, Clone)]
36pub struct SimStorageProvider {
37    sim: WeakSimWorld,
38}
39
40impl SimStorageProvider {
41    /// Create a new simulated storage provider.
42    pub fn new(sim: WeakSimWorld) -> Self {
43        Self { sim }
44    }
45}
46
47#[async_trait(?Send)]
48impl StorageProvider for SimStorageProvider {
49    type File = SimStorageFile;
50
51    async fn open(&self, path: &str, options: OpenOptions) -> io::Result<Self::File> {
52        let sim = self
53            .sim
54            .upgrade()
55            .map_err(|_| io::Error::other("simulation shutdown"))?;
56
57        // open_file schedules OpenComplete event with latency
58        let file_id = sim.open_file(path, options, 0).map_err(map_sim_error)?;
59
60        Ok(SimStorageFile::new(self.sim.clone(), file_id))
61    }
62
63    async fn exists(&self, path: &str) -> io::Result<bool> {
64        let sim = self
65            .sim
66            .upgrade()
67            .map_err(|_| io::Error::other("simulation shutdown"))?;
68        Ok(sim.file_exists(path))
69    }
70
71    async fn delete(&self, path: &str) -> io::Result<()> {
72        let sim = self
73            .sim
74            .upgrade()
75            .map_err(|_| io::Error::other("simulation shutdown"))?;
76        sim.delete_file(path).map_err(map_sim_error)
77    }
78
79    async fn rename(&self, from: &str, to: &str) -> io::Result<()> {
80        let sim = self
81            .sim
82            .upgrade()
83            .map_err(|_| io::Error::other("simulation shutdown"))?;
84        sim.rename_file(from, to).map_err(map_sim_error)
85    }
86}