Skip to main content

nestforge_core/
store.rs

1use std::sync::{Arc, RwLock};
2
3/*
4Identifiable = tiny trait for entities that have an id
5This lets the framework store handle ID assignment and lookups.
6*/
7pub trait Identifiable {
8    fn id(&self) -> u64;
9    fn set_id(&mut self, id: u64);
10}
11
12/*
13InMemoryStore<T> = framework-provided shared in-memory storage.
14
15This hides Arc/RwLock and gives clean CRUD-ish methods for simple apps,
16examples, and CLI scaffolds.
17*/
18#[derive(Clone)]
19pub struct InMemoryStore<T> {
20    items: Arc<RwLock<Vec<T>>>,
21}
22
23impl<T> Default for InMemoryStore<T>
24where
25    T: Identifiable + Clone,
26{
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl<T> InMemoryStore<T>
33where
34    T: Identifiable + Clone,
35{
36    pub fn new() -> Self {
37        Self {
38            items: Arc::new(RwLock::new(Vec::new())),
39        }
40    }
41
42    pub fn with_seed(seed: Vec<T>) -> Self {
43        Self {
44            items: Arc::new(RwLock::new(seed)),
45        }
46    }
47
48    pub fn find_all(&self) -> Vec<T> {
49        self.items
50            .read()
51            .map(|items| items.clone())
52            .unwrap_or_default()
53    }
54
55    pub fn find_by_id(&self, id: u64) -> Option<T> {
56        self.items
57            .read()
58            .ok()
59            .and_then(|items| items.iter().find(|item| item.id() == id).cloned())
60    }
61
62    pub fn count(&self) -> usize {
63        self.items.read().map(|items| items.len()).unwrap_or(0)
64    }
65
66    /*
67    create():
68    - auto-generates next id
69    - stores item
70    - returns stored item
71    */
72    pub fn create(&self, mut item: T) -> T {
73        let mut items = self.items.write().expect("store write lock poisoned");
74
75        let next_id = items.iter().map(|item| item.id()).max().unwrap_or(0) + 1;
76        item.set_id(next_id);
77
78        items.push(item.clone());
79        item
80    }
81
82    /*
83    update_by_id():
84    - mutates item in place via closure
85    - returns updated item
86    */
87    pub fn update_by_id<F>(&self, id: u64, mut updater: F) -> Option<T>
88    where
89        F: FnMut(&mut T),
90    {
91        let mut items = self.items.write().ok()?;
92        let item = items.iter_mut().find(|item| item.id() == id)?;
93
94        updater(item);
95        Some(item.clone())
96    }
97
98    pub fn replace_by_id(&self, id: u64, mut replacement: T) -> Option<T> {
99        let mut items = self.items.write().ok()?;
100        let existing = items.iter_mut().find(|item| item.id() == id)?;
101        replacement.set_id(id);
102        *existing = replacement;
103        Some(existing.clone())
104    }
105
106    pub fn delete_by_id(&self, id: u64) -> Option<T> {
107        let mut items = self.items.write().ok()?;
108        let index = items.iter().position(|item| item.id() == id)?;
109        Some(items.remove(index))
110    }
111}