hive_mind/
lib.rs

1use std::fmt::Debug;
2
3pub mod self_boxed;
4mod test;
5
6pub use self_boxed::{hive_mind::HiveMind, HiveNamed, SelfHiveBoxed};
7pub trait HiveBoxable: serde::de::DeserializeOwned + serde::Serialize + Debug {}
8
9impl<T: serde::de::DeserializeOwned + serde::Serialize + Debug> HiveBoxable for T {}
10
11#[derive(Debug, Clone)]
12pub struct HiveBox<T: HiveBoxable> {
13    pub sled: sled::Db,
14    pub path: Option<std::sync::Arc<std::path::PathBuf>>,
15    _phantom: std::marker::PhantomData<T>,
16}
17impl<I: HiveBoxable> PartialEq for HiveBox<I> {
18    fn eq(&self, other: &Self) -> bool {
19        self.path == other.path
20    }
21}
22
23//error for get from db
24#[derive(Debug, thiserror::Error)]
25pub enum HiveError {
26    #[error("sled error: {0}")]
27    Sled(#[from] sled::Error),
28    #[error("pot error: {0}")]
29    PotError(#[from] pot::Error),
30    #[error("no value found")]
31    None,
32}
33
34impl<T: HiveBoxable> HiveBox<T> {
35    pub fn new(path: impl AsRef<std::path::Path>) -> Result<Self, sled::Error> {
36        let path = path.as_ref();
37        Ok(Self {
38            sled: sled::open(path.clone())?,
39            path: Some(std::sync::Arc::new(path.to_path_buf())),
40            _phantom: std::marker::PhantomData,
41        })
42    }
43
44    pub fn memory() -> Result<Self, sled::Error> {
45        Ok(Self {
46            sled: sled::Config::new().temporary(true).open()?,
47            path: None,
48            _phantom: std::marker::PhantomData,
49        })
50    }
51
52    pub fn insert(&self, key: &str, value: T) -> Result<(), HiveError> {
53        let bytes = pot::to_vec(&value)?;
54        self.sled.insert(key, bytes)?;
55        Ok(())
56    }
57    
58    pub fn insert_bytes(&self, key: impl AsRef<[u8]>, bytes: impl Into<sled::IVec>) -> Result<(), HiveError> {
59        self.sled.insert(key, bytes)?;
60        Ok(())
61    }
62
63    pub fn get(&self, key: &str) -> Result<T, HiveError> {
64        let bytes = self.sled.get(key)?.ok_or(HiveError::None)?;
65        let value = pot::from_slice::<T>(&bytes)?;
66        Ok(value)
67    }
68
69    pub fn iter(&self) -> impl Iterator<Item = T> {
70        self.sled
71            .iter()
72            .map(|result| result.ok())
73            .flatten()
74            .map(|(_, bytes)| pot::from_slice::<T>(&bytes).ok())
75            .flatten()
76            .into_iter()
77    }
78
79    pub fn vec(&self) -> Vec<T> {
80        self.iter().collect()
81    }
82
83    pub fn remove(&self, key: &str) -> Result<(), sled::Error> {
84        self.sled.remove(key)?;
85        Ok(())
86    }
87}
88
89impl<T: std::hash::Hash + HiveBoxable> HiveBox<T> {
90    pub fn add(&self, value: T) -> Result<(), HiveError> {
91        let bytes = pot::to_vec(&value)?;
92        let mut hasher = std::collections::hash_map::DefaultHasher::new();
93        value.hash(&mut hasher);
94        let hash = std::hash::Hasher::finish(&hasher);
95        self.sled.insert(hash.to_le_bytes(), bytes)?;
96        Ok(())
97    }
98
99    pub fn exact(&self, value: &T) -> Result<T, HiveError> {
100        let mut hasher = std::collections::hash_map::DefaultHasher::new();
101        value.hash(&mut hasher);
102        let hash = std::hash::Hasher::finish(&hasher);
103        let bytes = self.sled.get(hash.to_le_bytes())?.ok_or(HiveError::None)?;
104        let value = pot::from_slice::<T>(&bytes)?;
105        Ok(value)
106    }
107
108    pub fn remove_dublicate(&self, value: &T) -> Result<(), HiveError> {
109        let mut hasher = std::collections::hash_map::DefaultHasher::new();
110        value.hash(&mut hasher);
111        let hash = std::hash::Hasher::finish(&hasher);
112        self.sled.remove(hash.to_le_bytes())?;
113        Ok(())
114    }
115}
116#[cfg(test)]
117mod test_hive_mind {
118    use crate::test::test_utils::*;
119
120    use super::*;
121    use std::sync::Arc;
122
123    #[test]
124    fn test_db_with_file() {
125        let dir = test_db_file_path();
126        //remove dir
127        match std::fs::remove_dir_all(dir) {
128            Ok(_) => {}
129            Err(e) => {
130                if e.kind() != std::io::ErrorKind::NotFound {
131                    panic!("error removing dir: {}", e);
132                }
133            }
134        }
135        let db = test_db_file();
136
137        let hello = Hello::default();
138        db.insert("hello", hello.clone()).unwrap();
139        let hello2 = Hello::new(Arc::from("world"), String::from("sus"), 1);
140        db.insert("hello2", hello2.clone()).unwrap();
141        let mut iter = db.iter();
142        assert_eq!(iter.next().unwrap(), hello);
143        assert_eq!(iter.next().unwrap(), hello2);
144    }
145
146    #[test]
147    fn test_db_restore() {
148        let dir = test_db_file_path();
149        //remove dir
150        match std::fs::remove_dir_all(dir) {
151            Ok(_) => {}
152            Err(e) => {
153                if e.kind() != std::io::ErrorKind::NotFound {
154                    panic!("error removing dir: {}", e);
155                }
156            }
157        }
158        {
159            let db = test_db_file();
160            db.insert("hello", Hello::default()).unwrap();
161        }
162        {
163            let db = test_db_file();
164            let hello = db.get("hello").unwrap();
165            assert_eq!(hello, Hello::default());
166        }
167    }
168
169    #[test]
170    fn test_insert() {
171        let db = test_db_memory();
172        let hello = Hello::default();
173        db.insert("hello", hello.clone()).unwrap();
174        let hello2 = db.get("hello").unwrap();
175        assert_eq!(hello, hello2);
176    }
177
178    #[test]
179    fn test_iter() {
180        let db = test_db_memory();
181        let hello = Hello::default();
182        db.insert("hello", hello.clone()).unwrap();
183        let hello2 = Hello::new(Arc::from("world"), String::from("sus"), 1);
184        db.insert("hello2", hello2.clone()).unwrap();
185        let mut iter = db.iter();
186        assert_eq!(iter.next().unwrap(), hello);
187        assert_eq!(iter.next().unwrap(), hello2);
188    }
189
190    #[test]
191    fn test_vec() {
192        let db = test_db_memory();
193        let hello = Hello::default();
194        db.insert("hello", hello.clone()).unwrap();
195        let hello2 = Hello::new(Arc::from("world"), String::from("sus"), 1);
196        db.insert("hello2", hello2.clone()).unwrap();
197        let vec = db.vec();
198        assert_eq!(vec[0], hello);
199        assert_eq!(vec[1], hello2);
200    }
201
202    #[test]
203    fn test_remove() {
204        let db = test_db_memory();
205        let hello = Hello::default();
206        db.insert("hello", hello.clone()).unwrap();
207        db.remove("hello").unwrap();
208        assert!(db.get("hello").is_err());
209    }
210
211    #[test]
212    fn test_add() {
213        let db = test_db_memory();
214        let hello = Hello::default();
215        db.add(hello.clone()).unwrap();
216        let hello2 = Hello::new(Arc::from("world"), String::from("sus"), 1);
217        db.add(hello2.clone()).unwrap();
218        let mut iter = db.iter();
219        assert_eq!(iter.next().unwrap(), hello);
220        assert_eq!(iter.next().unwrap(), hello2);
221    }
222
223    #[test]
224    fn test_exact() {
225        let db = test_db_memory();
226        let hello = Hello::default();
227        db.add(hello.clone()).unwrap();
228        let hello2 = Hello::new(Arc::from("world"), String::from("sus"), 1);
229        db.add(hello2.clone()).unwrap();
230        let hello3 = Hello::new(Arc::from("world"), String::from("sus"), 1);
231        let hello4 = db.exact(&hello3).unwrap();
232        assert_eq!(hello4, hello2);
233    }
234}