1use borsh::{BorshDeserialize, BorshSerialize};
4pub mod config;
5pub mod types;
6use anyhow::{anyhow, Result};
7use config::DbOpts;
8use sled::{IVec, Tree};
9use std::sync::Arc;
10
11use self::types::{DbKey, DbTrees};
12
13#[derive(Clone)]
16pub struct Database {
17 db: sled::Db,
18}
19
20#[derive(Clone)]
23pub struct DbTree {
24 pub tree: Tree,
25}
26
27#[derive(Default, Clone)]
30pub struct DbBatch {
31 batch: sled::Batch,
32 count: u64,
33}
34
35impl Database {
36 pub fn new(cfg: &DbOpts) -> Result<Arc<Self>> {
38 let sled_config: sled::Config = cfg.into();
39 let db = sled_config.open()?;
40 drop(sled_config);
41 Ok(Arc::new(Database { db }))
42 }
43 pub fn open_tree(self: &Arc<Self>, tree: DbTrees) -> Result<Arc<DbTree>> {
45 DbTree::open(&self.db, tree)
46 }
47 pub fn list_values(self: &Arc<Self>, tree: DbTrees) -> Result<Vec<(IVec, IVec)>> {
49 let tree = self.open_tree(tree)?;
50 Ok(tree
51 .iter()
52 .filter_map(|entry| {
53 if let Ok((key, value)) = entry {
54 Some((key, value))
55 } else {
56 None
57 }
58 })
59 .collect())
60 }
61 pub fn flush(self: &Arc<Self>) -> Result<usize> {
63 Ok(self.db.flush()?)
64 }
65 pub fn inner(self: &Arc<Self>) -> sled::Db {
67 self.db.clone()
68 }
69 pub fn destroy(self: &Arc<Self>) {
71 const SLED_DEFAULT_TREE: &[u8] = b"__sled__default";
72 self.db
73 .tree_names()
74 .iter()
75 .filter(|tree_name| tree_name.as_ref().ne(SLED_DEFAULT_TREE))
76 .for_each(|tree_name| {
77 if let Err(err) = self.db.drop_tree(tree_name) {
78 log::error!("failed to drop tree {:?}: {:#?}", tree_name.as_ref(), err);
79 }
80 });
81 }
82 pub fn get<K: AsRef<[u8]>>(&self, key: K) -> sled::Result<Option<sled::IVec>> {
83 self.db.get(key)
84 }
85 pub fn deserialize<K: AsRef<[u8]>, T>(&self, key: K) -> Result<T>
86 where
87 T: BorshDeserialize,
88 {
89 let value = self.get(key)?;
90 if let Some(value) = value {
91 Ok(borsh::de::BorshDeserialize::try_from_slice(&value)?)
92 } else {
93 Err(anyhow!("value for key is None"))
94 }
95 }
96 pub fn apply_batch(&self, batch: &mut DbBatch) -> sled::Result<()> {
97 self.db.apply_batch(batch.take_inner())
98 }
99 pub fn insert<T>(&mut self, value: &T) -> Result<()>
101 where
102 T: BorshSerialize + DbKey,
103 {
104 self.db.insert(
105 value.key()?,
106 match borsh::to_vec(value) {
107 Ok(data) => data,
108 Err(err) => return Err(anyhow!("failed to insert entry into batch {:#?}", err)),
109 },
110 )?;
111 Ok(())
112 }
113}
114
115impl DbTree {
116 pub fn open(db: &sled::Db, tree: DbTrees) -> Result<Arc<Self>> {
117 let tree = db.open_tree(tree.str())?;
118 Ok(Arc::new(Self { tree }))
119 }
120 pub fn len(&self) -> usize {
121 self.tree.len()
122 }
123 pub fn is_empty(&self) -> bool {
124 self.tree.is_empty()
125 }
126 pub fn iter(&self) -> sled::Iter {
127 self.tree.iter()
128 }
129 pub fn contains_key<K: AsRef<[u8]>>(&self, key: K) -> sled::Result<bool> {
130 self.tree.contains_key(key)
131 }
132 pub fn flush(&self) -> sled::Result<usize> {
133 self.tree.flush()
134 }
135 pub fn apply_batch(&self, batch: &mut DbBatch) -> sled::Result<()> {
136 self.tree.apply_batch(batch.take_inner())
137 }
138 pub fn insert<T>(&self, value: &T) -> Result<Option<sled::IVec>>
139 where
140 T: BorshSerialize + DbKey,
141 {
142 Ok(self.tree.insert(
143 value.key()?,
144 match borsh::to_vec(value) {
145 Ok(data) => data,
146 Err(err) => return Err(anyhow!("failed to insert entry {:#?}", err)),
147 },
148 )?)
149 }
150 pub fn get<K: AsRef<[u8]>>(&self, key: K) -> sled::Result<Option<sled::IVec>> {
151 self.tree.get(key)
152 }
153 pub fn deserialize<K: AsRef<[u8]>, T>(&self, key: K) -> Result<T>
154 where
155 T: BorshDeserialize,
156 {
157 let value = self.get(key)?;
158 if let Some(value) = value {
159 Ok(borsh::de::BorshDeserialize::try_from_slice(&value)?)
160 } else {
161 Err(anyhow!("value for key is None"))
162 }
163 }
164}
165
166impl DbBatch {
167 pub fn new() -> DbBatch {
168 DbBatch {
169 batch: Default::default(),
170 count: 0,
171 }
172 }
173 pub fn insert<T>(&mut self, value: &T) -> Result<()>
174 where
175 T: BorshSerialize + DbKey,
176 {
177 self.batch.insert(
178 value.key()?,
179 match borsh::to_vec(value) {
180 Ok(data) => data,
181 Err(err) => return Err(anyhow!("failed to insert entry into batch {:#?}", err)),
182 },
183 );
184 self.count += 1;
185 Ok(())
186 }
187 pub fn take_inner(&mut self) -> sled::Batch {
191 std::mem::take(&mut self.batch)
192 }
193 pub fn inner(&self) -> &sled::Batch {
194 &self.batch
195 }
196 pub fn count(&self) -> u64 {
197 self.count
198 }
199}
200
201#[cfg(test)]
202mod test {
203 use super::*;
204 use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
205 use config::DbOpts;
206 use std::fs::remove_dir_all;
207
208 #[derive(BorshSerialize, BorshDeserialize, BorshSchema)]
209 pub struct TestData {
210 pub key: String,
211 pub foo: String,
212 }
213
214 impl DbKey for TestData {
215 fn key(&self) -> anyhow::Result<Vec<u8>> {
216 Ok(self.key.as_bytes().to_vec())
217 }
218 }
219
220 #[test]
222 fn test_db_basic() {
223 let db_opts = DbOpts::default();
224
225 let db = Database::new(&db_opts).unwrap();
226 let insert = || {
227 let mut db_batch = DbBatch::new();
228 db_batch
229 .insert(&TestData {
230 key: "key1".to_string(),
231 foo: "foo1".to_string(),
232 })
233 .unwrap();
234 {
235 let tree = db.open_tree(DbTrees::Custom("foobar")).unwrap();
236 tree.apply_batch(&mut db_batch).unwrap();
237 assert_eq!(tree.len(), 1);
238 }
239
240 db_batch
241 .insert(&TestData {
242 key: "key2".to_string(),
243 foo: "foo2".to_string(),
244 })
245 .unwrap();
246 {
247 let tree = db.open_tree(DbTrees::Custom("foobar")).unwrap();
248 tree.apply_batch(&mut db_batch).unwrap();
249 assert_eq!(tree.len(), 2);
250 }
251
252 db_batch
253 .insert(&TestData {
254 key: "key3".to_string(),
255 foo: "foo3".to_string(),
256 })
257 .unwrap();
258 {
259 let tree = db.open_tree(DbTrees::Custom("foobarbaz")).unwrap();
260 tree.apply_batch(&mut db_batch).unwrap();
261 assert_eq!(tree.len(), 1);
262 }
263 db_batch
264 .insert(&TestData {
265 key: "key4".to_string(),
266 foo: "foo4".to_string(),
267 })
268 .unwrap();
269 {
270 db.apply_batch(&mut db_batch).unwrap();
271 }
272 };
273 let query = || {
274 let foobar_values = db.list_values(DbTrees::Custom("foobar")).unwrap();
275 assert_eq!(foobar_values.len(), 2);
276 let test_data_one: TestData = db
277 .open_tree(DbTrees::Custom("foobar"))
278 .unwrap()
279 .deserialize(foobar_values[0].0.clone())
280 .unwrap();
281 assert_eq!(test_data_one.key, "key1".to_string());
282 assert_eq!(test_data_one.foo, "foo1".to_string());
283 let test_data_two: TestData = db
284 .open_tree(DbTrees::Custom("foobar"))
285 .unwrap()
286 .deserialize(foobar_values[1].0.clone())
287 .unwrap();
288 assert_eq!(test_data_two.key, "key2".to_string());
289 assert_eq!(test_data_two.foo, "foo2".to_string());
290 let foobarbaz_values = db.list_values(DbTrees::Custom("foobarbaz")).unwrap();
291 assert_eq!(foobarbaz_values.len(), 1);
292 let test_data_three: TestData = db
293 .open_tree(DbTrees::Custom("foobarbaz"))
294 .unwrap()
295 .deserialize(foobarbaz_values[0].0.clone())
296 .unwrap();
297 assert_eq!(test_data_three.key, "key3".to_string());
298 assert_eq!(test_data_three.foo, "foo3".to_string());
299 let default_tree_values = db.list_values(DbTrees::Default).unwrap();
300 assert_eq!(default_tree_values.len(), 1);
301 };
302 insert();
303 query();
304 db.destroy();
305 remove_dir_all("test_infos.db").unwrap();
306 }
307}