Skip to main content

yog_storage/
store.rs

1//! A handle to a store: typed values by key.
2
3use std::io;
4use std::path::Path;
5
6use yog_data::Schema;
7use yog_sync::{Arc, Mutex};
8
9use crate::Scope;
10use crate::shelf::{self, Shelf};
11
12/// A mod's store of a scope: values of any [`Schema`] type by key, kept in
13/// memory and written when it's flushed. Handles to one store share it.
14#[derive(Clone)]
15pub struct Store {
16    shelf: Arc<Mutex<Shelf>>,
17}
18
19impl Store {
20    /// `mod_id`'s store of `scope` under `root` (the game's folder or the world's).
21    pub fn open(root: &Path, mod_id: &str, scope: Scope<'_>) -> Self {
22        Store {
23            shelf: shelf::file(scope.path(root, mod_id)),
24        }
25    }
26
27    /// `mod_id`'s session store: kept while the game runs, never written.
28    pub fn session(mod_id: &str) -> Self {
29        Store {
30            shelf: shelf::session(mod_id),
31        }
32    }
33
34    /// The value at `key`, if there's one of type `T`.
35    pub fn get<T: Schema>(&self, key: &str) -> Option<T> {
36        yog_data::read_value(self.shelf.lock().values.get(key)?).ok()
37    }
38
39    /// The value at `key`, or `T`'s default.
40    pub fn get_or_default<T: Schema + Default>(&self, key: &str) -> T {
41        self.get(key).unwrap_or_default()
42    }
43
44    /// `value` at `key`.
45    pub fn set<T: Schema>(&self, key: &str, value: &T) {
46        let mut shelf = self.shelf.lock();
47        shelf.values.insert(key, value.write());
48        shelf.dirty = true;
49    }
50
51    /// The value at `key` changed by `change` (its default when there's none); what `change` returns.
52    pub fn update<T: Schema + Default, R>(&self, key: &str, change: impl FnOnce(&mut T) -> R) -> R {
53        let mut value = self.get_or_default(key);
54        let out = change(&mut value);
55        self.set(key, &value);
56        out
57    }
58
59    /// Takes the value at `key` out; whether there was one.
60    pub fn remove(&self, key: &str) -> bool {
61        let mut shelf = self.shelf.lock();
62        let removed = shelf.values.remove(key).is_some();
63        shelf.dirty |= removed;
64        removed
65    }
66
67    pub fn contains(&self, key: &str) -> bool {
68        self.shelf.lock().values.get(key).is_some()
69    }
70
71    /// Every key, in the order they were first set.
72    pub fn keys(&self) -> Vec<String> {
73        self.shelf.lock().values.keys().map(str::to_owned).collect()
74    }
75
76    /// Writes it now if it changed (else it's written with every store, see [`crate::flush_all`]).
77    pub fn flush(&self) -> io::Result<()> {
78        self.shelf.lock().flush()
79    }
80}