1use std::sync::{Arc, RwLock};
2
3pub trait Identifiable {
8 fn id(&self) -> u64;
9 fn set_id(&mut self, id: u64);
10}
11
12#[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 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 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}