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#[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 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 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}