light_magic/
table.rs

1use serde::{Deserialize, Serialize};
2use serde_with::{serde_as, DisplayFromStr};
3use std::collections::BTreeMap;
4use std::fmt::{Debug, Display};
5use std::str::FromStr;
6use std::{
7    clone::Clone,
8    collections::btree_map::{Values, ValuesMut},
9};
10
11/// Represents a database table utilizing a `BTreeMap` for underlying data storage.
12/// Needs the `PrimaryKey` trait to be implemented for the value type. Offers
13/// enhanced methods for manipulating records, including `add`, `edit`, `delete`, `get`, and `search`.
14/// ```
15/// use light_magic::{
16///     serde::{Deserialize, Serialize},
17///     table::{PrimaryKey, Table},
18/// };
19///
20/// #[derive(Default, Debug, Clone, Serialize, Deserialize)]
21/// struct User {
22///     id: usize,
23///     name: String,
24///     age: usize,
25/// }
26///
27/// impl PrimaryKey for User {
28///     type PrimaryKeyType = usize;
29///
30///     fn primary_key(&self) -> &Self::PrimaryKeyType {
31///         &self.id
32///     }
33/// }
34/// ```
35#[serde_as]
36#[derive(Default, Debug, Serialize, Deserialize, Clone)]
37pub struct Table<V>
38where
39    V: PrimaryKey + Serialize + for<'a> Deserialize<'a>,
40    V::PrimaryKeyType: Ord + FromStr + Display + Debug + Clone,
41    <<V as PrimaryKey>::PrimaryKeyType as FromStr>::Err: std::fmt::Display,
42{
43    #[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
44    #[serde(flatten)]
45    inner: BTreeMap<<V as PrimaryKey>::PrimaryKeyType, V>,
46}
47
48impl<V> Table<V>
49where
50    V: PrimaryKey + Serialize + for<'a> Deserialize<'a>,
51    V::PrimaryKeyType: Ord + FromStr + Display + Debug + Clone,
52    <<V as PrimaryKey>::PrimaryKeyType as FromStr>::Err: std::fmt::Display,
53{
54    /// Adds an entry to the table, returns the `value` or `None` if the addition failed
55    pub fn add(&mut self, value: V) -> Option<V>
56    where
57        V: Clone,
58        V::PrimaryKeyType: Clone,
59    {
60        let key = value.primary_key();
61        if !self.inner.contains_key(key) {
62            self.inner.insert(key.clone(), value.clone());
63            return Some(value);
64        }
65        None
66    }
67
68    /// Gets an entry from the table, returns the `value` or `None` if it couldn't find the data
69    pub fn get(&self, key: &V::PrimaryKeyType) -> Option<&V> {
70        self.inner.get(key)
71    }
72
73    /// Gets an mutable entry from the table, returns the `value` or `None` if it couldn't find the data
74    pub fn get_mut(&mut self, key: &V::PrimaryKeyType) -> Option<&mut V> {
75        self.inner.get_mut(key)
76    }
77
78    /// Edits an entry in the table, returns the `new_value` or `None` if the editing failed
79    pub fn edit(&mut self, key: &V::PrimaryKeyType, new_value: V) -> Option<V>
80    where
81        V: Clone,
82        V::PrimaryKeyType: Clone,
83    {
84        let new_key = new_value.primary_key();
85        if (key == new_key || !self.inner.contains_key(new_key)) && self.inner.remove(key).is_some()
86        {
87            self.inner.insert(new_key.clone(), new_value.clone());
88            return Some(new_value);
89        }
90        None
91    }
92
93    /// Deletes an entry from the table, returns the `value` or `None` if the deletion failed
94    pub fn delete(&mut self, key: &V::PrimaryKeyType) -> Option<V> {
95        self.inner.remove(key)
96    }
97
98    /// Searches the table by a predicate function
99    pub fn search<F>(&self, predicate: F) -> Vec<&V>
100    where
101        F: Fn(&V) -> bool,
102    {
103        self.inner.values().filter(|&val| predicate(val)).collect()
104    }
105
106    /// Searches the table by a predicate function and a custom ordering with a comparator function
107    pub fn search_ordered<F, O>(&self, predicate: F, comparator: O) -> Vec<&V>
108    where
109        F: Fn(&V) -> bool,
110        O: Fn(&&V, &&V) -> std::cmp::Ordering,
111    {
112        let mut result = self.search(predicate);
113        result.sort_by(comparator);
114        result
115    }
116
117    /// Gets an iterator over the values of the map, in order by key.
118    pub fn values(&self) -> Values<'_, V::PrimaryKeyType, V> {
119        self.inner.values()
120    }
121
122    /// Gets a mutable iterator over the values of the map, in order by key.
123    pub fn values_mut(&mut self) -> ValuesMut<'_, V::PrimaryKeyType, V> {
124        self.inner.values_mut()
125    }
126}
127
128/// Trait for getting the value of the primary key
129pub trait PrimaryKey {
130    type PrimaryKeyType;
131    fn primary_key(&self) -> &Self::PrimaryKeyType;
132}
133
134mod test {
135    use serde::{Deserialize, Serialize};
136
137    use super::PrimaryKey;
138
139    #[derive(Default, Debug, Clone, Serialize, Deserialize)]
140    struct User {
141        id: usize,
142        name: String,
143        age: usize,
144    }
145
146    impl PrimaryKey for User {
147        type PrimaryKeyType = usize;
148
149        fn primary_key(&self) -> &Self::PrimaryKeyType {
150            &self.id
151        }
152    }
153
154    #[test]
155    fn serialize() {
156        use super::Table;
157
158        let mut table = Table::default();
159
160        table.add(User::default());
161
162        serde_json::to_string(&table).unwrap();
163        serde_json::from_str::<Table<User>>(&"{\"0\":{\"id\":0,\"name\":\"\",\"age\":0}}").unwrap();
164    }
165}