1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
use std::collections::BTreeMap;
use std::fmt::Display;
use std::str::FromStr;
use std::{clone::Clone, collections::btree_map::Values};

/// Represents a database table utilizing a `BTreeMap` for underlying data storage.
/// Offers enhanced methods for manipulating records, including `add`, `edit`, `delete`, `get`, and `search`.
#[serde_as]
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Table<K, V>
where
    K: Ord + FromStr + Display,
    <K as FromStr>::Err: Display,
    V: Serialize + for<'a> Deserialize<'a>,
{
    #[serde_as(as = "BTreeMap<DisplayFromStr, _>")]
    #[serde(flatten)]
    inner: BTreeMap<K, V>,
}

impl<K, V> Table<K, V>
where
    K: Clone + Ord + FromStr + Display,
    K::Err: Display,
    V: Clone + Matches + FirstField<FieldType = K> + Serialize + for<'a> Deserialize<'a>,
{
    /// Adds an entry to the table, returns the `value` or `None` if the addition failed
    pub fn add(&mut self, value: V) -> Option<V> {
        let key = value.first_field().clone();
        if !self.inner.contains_key(&key) {
            self.inner.insert(key.clone(), value.clone());
            return Some(value);
        }
        None
    }

    /// Gets an entry from the table, returns the `value` or `None` if it couldn't find the data
    pub fn get(&self, key: &K) -> Option<V> {
        self.inner.get(key).cloned()
    }

    /// Edits an entry in the table, returns the `new_value` or `None` if the editing failed
    pub fn edit(&mut self, key: &K, new_value: V) -> Option<V> {
        let new_key = new_value.first_field().clone();
        if (key == &new_key || !self.inner.contains_key(&new_key))
            && self.inner.remove(key).is_some()
        {
            self.inner.insert(new_key, new_value.clone());
            return Some(new_value);
        }
        None
    }

    /// Deletes an entry from the table, returns the `value` or `None` if the deletion failed
    pub fn delete(&mut self, key: &K) -> Option<V> {
        self.inner.remove(key)
    }

    /// Searches the table by a `&str`, works in parallel
    pub fn search(&self, search: &str) -> Vec<V> {
        self.inner
            .values()
            .filter(|val| val.matches(search))
            .cloned()
            .collect()
    }

    pub fn values(&self) -> Values<'_, K, V> {
        self.inner.values()
    }
}

/// Match trait, filled in `db` macro
pub trait Matches {
    fn matches(&self, search: &str) -> bool;
}

/// Trait for getting the value of the first field, filled in `db` macro
pub trait FirstField {
    type FieldType: Clone;
    fn first_field(&self) -> &Self::FieldType;
}

mod test {
    use serde::{Deserialize, Serialize};

    use super::{FirstField, Matches};

    #[derive(Default, Debug, Clone, Serialize, Deserialize)]
    struct User {
        id: usize,
        name: String,
        age: usize,
    }

    impl Matches for User {
        fn matches(&self, _: &str) -> bool {
            false
        }
    }

    impl FirstField for User {
        type FieldType = usize;

        fn first_field(&self) -> &Self::FieldType {
            &self.id
        }
    }

    #[test]
    fn serialize() {
        use super::Table;

        let mut table = Table::default();

        table.add(User::default());

        serde_json::to_string(&table).unwrap();
        serde_json::from_str::<Table<usize, User>>(&"{\"0\":{\"id\":0,\"name\":\"\",\"age\":0}}")
            .unwrap();
    }
}