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}