Skip to main content

duraflow_rs/
store.rs

1use parking_lot::Mutex;
2use std::collections::HashMap;
3use std::fs;
4use std::path::{Path, PathBuf};
5
6/// Object-safe storage backend used by `duraflow-rs`.
7pub trait Storage: Send + Sync {
8    /// Return the raw JSON string stored for `key`, if any.
9    fn get_raw(&self, key: &str) -> Option<String>;
10    /// Store a raw JSON string for `key`.
11    fn save_raw(&self, key: &str, value: &str) -> std::io::Result<()>;
12}
13
14/// In-memory store used for examples and tests.
15pub struct MemoryStore {
16    storage: Mutex<HashMap<String, String>>,
17}
18
19impl MemoryStore {
20    pub fn new() -> Self {
21        Self {
22            storage: Mutex::new(HashMap::new()),
23        }
24    }
25}
26
27impl Default for MemoryStore {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl Storage for MemoryStore {
34    fn get_raw(&self, key: &str) -> Option<String> {
35        self.storage.lock().get(key).cloned()
36    }
37
38    fn save_raw(&self, key: &str, value: &str) -> std::io::Result<()> {
39        self.storage
40            .lock()
41            .insert(key.to_string(), value.to_string());
42        Ok(())
43    }
44}
45
46/// Simple file-backed store: stores each key as a file under a directory.
47/// Keys are sanitized to filesystem-friendly names.
48pub struct FileStore {
49    dir: PathBuf,
50    write_lock: Mutex<()>,
51}
52
53impl FileStore {
54    /// Create a new `FileStore` backed by `dir`. Directory will be created if missing.
55    pub fn new<P: AsRef<Path>>(dir: P) -> std::io::Result<Self> {
56        let dir = dir.as_ref().to_path_buf();
57        fs::create_dir_all(&dir)?;
58        Ok(Self {
59            dir,
60            write_lock: Mutex::new(()),
61        })
62    }
63
64    fn key_path(&self, key: &str) -> PathBuf {
65        let safe: String = key
66            .chars()
67            .map(|c| {
68                if c.is_ascii_alphanumeric() || c == '_' || c == '-' {
69                    c
70                } else {
71                    '_'
72                }
73            })
74            .collect();
75        self.dir.join(safe)
76    }
77}
78
79impl Storage for FileStore {
80    fn get_raw(&self, key: &str) -> Option<String> {
81        let path = self.key_path(key);
82        fs::read_to_string(path).ok()
83    }
84
85    fn save_raw(&self, key: &str, value: &str) -> std::io::Result<()> {
86        let _g = self.write_lock.lock();
87        let path = self.key_path(key);
88        fs::write(&path, value)
89    }
90}