sled_extensions/db.rs
1use chrono::{DateTime, Utc};
2use serde::{de::DeserializeOwned, ser::Serialize};
3use sled::IVec;
4use std::collections::HashSet;
5
6use crate::{encoding::Encoding, error::Result, expiring, structured};
7
8/// Extensions for the sled Db type that provides different ways of opening trees for storing
9/// structured data.
10///
11/// Example:
12/// ```rust
13/// use sled_extensions::{Config, DbExt};
14///
15/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
16/// let db = Config::default().temporary(true).open()?;
17/// let tree = db.open_json_tree::<()>("json-tree")?;
18/// # Ok(())
19/// # }
20/// ```
21pub trait DbExt {
22 /// Open an expiring tree
23 ///
24 /// Expiring trees are trees that keep track of insert and update times in order to help cache
25 /// implementations. While this library on it's own doesn't provide a fully-featured cache,
26 /// implementing a cache on top of an expiring tree is simple.
27 ///
28 /// This tree can have numerous types, for example,
29 /// ```rust
30 /// use sled_extensions::{Config, DbExt, bincode, cbor, json};
31 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
32 /// # let db = Config::default().temporary(true).open()?;
33 /// let tree: bincode::expiring::Tree<()> = db.open_expiring_tree("bincode-tree").build()?;
34 /// let tree: cbor::expiring::Tree<()> = db.open_expiring_tree("cbor-tree").build()?;
35 /// let tree: json::expiring::Tree<()> = db.open_expiring_tree("json-tree").build()?;
36 /// # Ok(())
37 /// # }
38 /// ```
39 ///
40 /// While it is possible to use only this method to open many kinds of expiring trees, it may
41 /// be easier to use a more specific tree opening method.
42 fn open_expiring_tree<V, E, F>(&self, name: &str) -> expiring::TreeBuilder<V, E, F>
43 where
44 E: Encoding<HashSet<IVec>> + Encoding<DateTime<Utc>> + 'static,
45 F: Encoding<V> + 'static;
46
47 /// Open a structured tree
48 ///
49 /// Structured trees are a thin wrapper on top of basic sled trees that provides encoding and
50 /// decoding for the data stored in the tree.
51 ///
52 /// This tree can have numerous types, for example,
53 /// ```rust
54 /// use sled_extensions::{Config, DbExt, bincode, cbor, json};
55 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
56 /// # let db = Config::default().temporary(true).open()?;
57 /// let tree: bincode::Tree<()> = db.open_structured_tree("bincode-tree")?;
58 /// let tree: cbor::Tree<()> = db.open_structured_tree("cbor-tree")?;
59 /// let tree: json::Tree<()> = db.open_structured_tree("json-tree")?;
60 /// # Ok(())
61 /// # }
62 /// ```
63 ///
64 /// While it is possible to use only this method to open many kinds of structured trees, it may
65 /// be easier to use a more specific tree opening method.
66 fn open_structured_tree<V, E>(&self, name: &str) -> Result<structured::Tree<V, E>>
67 where
68 E: Encoding<V> + 'static;
69
70 /// Open an expiring tree using an encoding for both metadata storage and value storage
71 fn open_expiring_structured_tree<V, E>(
72 &self,
73 name: &str,
74 ) -> structured::expiring::TreeBuilder<V, E>
75 where
76 E: Encoding<V> + Encoding<HashSet<IVec>> + Encoding<DateTime<Utc>> + 'static,
77 V: DeserializeOwned + Serialize + 'static,
78 {
79 self.open_expiring_tree(name)
80 }
81
82 /// Open an expiring tree using an encoding for metadata storage
83 fn open_expiring_plain_tree<E>(&self, name: &str) -> expiring::plain::TreeBuilder<E>
84 where
85 E: Encoding<HashSet<IVec>> + Encoding<DateTime<Utc>> + 'static,
86 {
87 self.open_expiring_tree(name)
88 }
89
90 #[cfg(feature = "bincode")]
91 /// Open a tree that stores it's values as bincode
92 fn open_bincode_tree<V>(&self, name: &str) -> Result<crate::bincode::Tree<V>>
93 where
94 V: DeserializeOwned + Serialize + 'static,
95 {
96 self.open_structured_tree(name)
97 }
98
99 #[cfg(feature = "bincode")]
100 /// Open an expiring tree that stores it's values as bincode
101 fn open_expiring_bincode_tree<V>(&self, name: &str) -> crate::bincode::expiring::TreeBuilder<V>
102 where
103 V: DeserializeOwned + Serialize + 'static,
104 {
105 self.open_expiring_tree(name)
106 }
107
108 #[cfg(feature = "bincode")]
109 /// Open an expiring tree that stores it's metadata as bincode
110 fn open_expiring_plain_bincode_tree(
111 &self,
112 name: &str,
113 ) -> expiring::plain::TreeBuilder<crate::bincode::BincodeEncoding> {
114 self.open_expiring_tree(name)
115 }
116
117 #[cfg(feature = "cbor")]
118 /// Open a tree that stores it's values as cbor
119 fn open_cbor_tree<V>(&self, name: &str) -> Result<crate::cbor::Tree<V>>
120 where
121 V: DeserializeOwned + Serialize + 'static,
122 {
123 self.open_structured_tree(name)
124 }
125
126 #[cfg(feature = "cbor")]
127 /// Open an expiring tree that stores it's values as cbor
128 fn open_expiring_cbor_tree<V>(&self, name: &str) -> crate::cbor::expiring::TreeBuilder<V>
129 where
130 V: DeserializeOwned + Serialize + 'static,
131 {
132 self.open_expiring_tree(name)
133 }
134
135 #[cfg(feature = "cbor")]
136 /// Open an expiring tree that stores it's metadata as cbor
137 fn open_expiring_plain_cbor_tree(
138 &self,
139 name: &str,
140 ) -> expiring::plain::TreeBuilder<crate::cbor::CborEncoding> {
141 self.open_expiring_tree(name)
142 }
143
144 #[cfg(feature = "json")]
145 /// Open a tree that stores it's values as json
146 fn open_json_tree<V>(&self, name: &str) -> Result<crate::json::Tree<V>>
147 where
148 V: DeserializeOwned + Serialize + 'static,
149 {
150 self.open_structured_tree(name)
151 }
152
153 #[cfg(feature = "json")]
154 /// Open an expiring tree that stores it's values as json
155 fn open_expiring_json_tree<V>(&self, name: &str) -> crate::json::expiring::TreeBuilder<V>
156 where
157 V: DeserializeOwned + Serialize + 'static,
158 {
159 self.open_expiring_tree(name)
160 }
161
162 #[cfg(feature = "json")]
163 /// Open an expiring tree that stores it's metadata as json
164 fn open_expiring_plain_json_tree(
165 &self,
166 name: &str,
167 ) -> expiring::plain::TreeBuilder<crate::json::JsonEncoding> {
168 self.open_expiring_tree(name)
169 }
170}
171
172impl DbExt for sled::Db {
173 fn open_expiring_tree<V, E, F>(&self, name: &str) -> expiring::TreeBuilder<V, E, F>
174 where
175 E: Encoding<HashSet<IVec>> + Encoding<DateTime<Utc>> + 'static,
176 F: Encoding<V> + 'static,
177 {
178 expiring::TreeBuilder::new(self, name)
179 }
180
181 fn open_structured_tree<V, E>(&self, name: &str) -> Result<structured::Tree<V, E>>
182 where
183 E: Encoding<V> + 'static,
184 {
185 structured::Tree::new(self, name)
186 }
187}