slice_rbtree/tree.rs
1//! A slice-based Red-Black tree
2//!
3//! Let's assume you want to create a tree holding up to 100 pairs of `u8 <-> f64`:
4//! ```
5//! use slice_rbtree::tree::{tree_size, RBTree, TreeParams};
6//! use std::mem::size_of;
7//!
8//! // RBTree requires input slice to have a proper size
9//! let size = tree_size(
10//! TreeParams {
11//! k_size: size_of::<u8>(),
12//! v_size: size_of::<f64>(),
13//! },
14//! 100,
15//! );
16//!
17//! let mut buffer = vec![0; size];
18//!
19//! let mut tree: RBTree<u8, f64, 1, 8> = RBTree::init_slice(&mut buffer).unwrap();
20//!
21//! // Insert some values
22//! tree.insert(15, 1.245).unwrap();
23//! tree.insert(17, 5.5).unwrap();
24//! tree.insert(19, 6.5).unwrap();
25//!
26//! // This type does not implement `Drop` trait - all the data is immediately serialized in the
27//! // slice, so this is actually a no-op
28//! drop(tree);
29//!
30//! let mut new_tree: RBTree<u8, f64, 1, 8> = unsafe { RBTree::from_slice(&mut buffer).unwrap() };
31//! assert_eq!(new_tree.get(&15), Some(1.245));
32//!
33//! // Create iterator of key-value pairs and collect in a `Vec`
34//! let pairs:Vec<_> = new_tree.pairs().collect();
35//! assert_eq!(pairs[0], (15, 1.245));
36//! assert_eq!(pairs[1], (17, 5.5));
37//! assert_eq!(pairs[2], (19, 6.5));
38//!
39//! // There are 3 ways to remove a value from the tree:
40//! // 1. remove() will deserialize the value to be removed
41//! assert_eq!(new_tree.remove(&17), Some(5.5));
42//! // 2. remove_entry() will deserialize both the key and the value
43//! assert_eq!(new_tree.remove_entry(&15), Some((15,1.245)));
44//! // 2. delete() will not deserialize anything, will return `true` if the value was present
45//! assert_eq!(new_tree.delete(&19), true);
46//! ```
47//!
48//! # Internal structure
49//! Internally, [`RBTree`] is just a wrapper around [`RBForest`](super::forest::RBForest) with `max_roots`
50//! equal to `1`. See [`RBForest`](super::forest::RBForest) docs for description of the internals.
51use borsh::{BorshDeserialize, BorshSerialize};
52use core::borrow::Borrow;
53use core::cmp::Ord;
54use core::fmt;
55
56pub use super::forest::iterators::{KeysIterator, PairsIterator, ValuesIterator};
57use super::forest::{forest_size, init_forest, ForestParams, RBForest};
58use super::Error;
59
60/// Parameters required to calculate [`RBTree`] size
61#[derive(Debug, Eq, PartialEq, Copy, Clone)]
62pub struct TreeParams {
63 /// key buffer size
64 pub k_size: usize,
65 /// value buffer size
66 pub v_size: usize,
67}
68/// Returns the required size of the slice
69#[must_use]
70#[inline]
71pub const fn tree_size(params: TreeParams, max_nodes: usize) -> usize {
72 forest_size(
73 ForestParams {
74 k_size: params.k_size,
75 v_size: params.v_size,
76 max_roots: 1,
77 },
78 max_nodes,
79 )
80}
81
82/// Initializes [`RBTree`] in the given slice without returning it
83///
84/// This function can be used than you don't know buffer sizes at compile time.
85#[inline]
86pub fn init_tree(params: TreeParams, slice: &mut [u8]) -> Result<(), Error> {
87 init_forest(
88 ForestParams {
89 k_size: params.k_size,
90 v_size: params.v_size,
91 max_roots: 1,
92 },
93 slice,
94 )
95}
96
97/// A slice-based Red-Black tree
98///
99/// See [module](super::tree) level documentation for more info.
100pub struct RBTree<'a, K, V, const KSIZE: usize, const VSIZE: usize>(
101 RBForest<'a, K, V, KSIZE, VSIZE>,
102)
103where
104 K: Ord + BorshDeserialize + BorshSerialize,
105 V: BorshDeserialize + BorshSerialize;
106
107impl<'a, K, V, const KSIZE: usize, const VSIZE: usize> RBTree<'a, K, V, KSIZE, VSIZE>
108where
109 K: Ord + BorshDeserialize + BorshSerialize,
110 V: BorshDeserialize + BorshSerialize,
111{
112 /// Initializes [`RBTree`] in a given slice
113 pub fn init_slice(slice: &'a mut [u8]) -> Result<Self, Error> {
114 RBForest::<'a, K, V, KSIZE, VSIZE>::init_slice(slice, 1).map(|tree| Self(tree))
115 }
116
117 /// Returns [`RBTree`], contained in the given slice
118 ///
119 /// # Safety
120 /// This function must be called only on slices, previously initialized as [`RBTree`] using
121 /// [`init_tree`] or [`RBTree::init_slice`]
122 pub unsafe fn from_slice(slice: &'a mut [u8]) -> Result<Self, Error> {
123 unsafe { RBForest::<'a, K, V, KSIZE, VSIZE>::from_slice(slice).map(|tree| Self(tree)) }
124 }
125
126 /// Returns the number of occupied nodes
127 ///
128 /// This function runs in `O(n)`, where `n` - is the number of nodes
129 #[must_use]
130 pub fn len(&self) -> usize {
131 self.0.len(0).unwrap()
132 }
133
134 /// Clears the tree
135 ///
136 /// This function runs in `O(n)`, where `n` - is the number of nodes
137 pub fn clear(&mut self) {
138 self.0.clear();
139 }
140
141 /// Returns the number of free nodes
142 ///
143 /// This function runs in `O(n)`, where `n` - is the number of nodes
144 #[must_use]
145 pub fn free_nodes_left(&self) -> usize {
146 self.0.free_nodes_left()
147 }
148
149 /// Returns true if the map contains a value for the specified key
150 ///
151 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
152 #[must_use]
153 pub fn contains_key<Q>(&self, k: &Q) -> bool
154 where
155 K: Borrow<Q> + Ord,
156 Q: Ord + ?Sized,
157 {
158 self.0.contains_key(0, k)
159 }
160
161 /// Returns a key-value pair corresponding to the supplied key
162 ///
163 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
164 #[must_use]
165 pub fn get_entry<Q>(&self, k: &Q) -> Option<(K, V)>
166 where
167 K: Borrow<Q> + Ord,
168 Q: Ord + ?Sized,
169 {
170 self.0.get_entry(0, k)
171 }
172
173 /// Returns the value corresponding to the key
174 ///
175 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
176 #[must_use]
177 pub fn get<Q>(&self, k: &Q) -> Option<V>
178 where
179 K: Borrow<Q> + Ord,
180 Q: Ord + ?Sized,
181 {
182 self.0.get(0, k)
183 }
184
185 /// Inserts a new key-value pair and returns the old value if it was present
186 ///
187 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
188 pub fn insert(&mut self, k: K, v: V) -> Result<Option<V>, Error> {
189 self.0.insert(0, k, v)
190 }
191
192 /// Returns `true` if the tree contains no elements
193 #[must_use]
194 pub fn is_empty(&self) -> bool {
195 self.0.is_empty(0)
196 }
197
198 /// Deletes entry and returns deserialized value
199 ///
200 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
201 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
202 where
203 K: Borrow<Q> + Ord,
204 Q: Ord + ?Sized,
205 {
206 self.0.remove(0, key)
207 }
208
209 /// Deletes entry and returns deserialized key-value pair
210 ///
211 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
212 pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
213 where
214 K: Borrow<Q> + Ord,
215 Q: Ord + ?Sized,
216 {
217 self.0.remove_entry(0, key)
218 }
219
220 /// Deletes entry without deserializing the value
221 ///
222 /// Returns `true` if there was a value with the given key.
223 pub fn delete<Q>(&mut self, key: &Q) -> bool
224 where
225 K: Borrow<Q> + Ord,
226 Q: Ord + ?Sized,
227 {
228 self.0.delete(0, key)
229 }
230
231 /// Returns the first key-value pair in the map
232 ///
233 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
234 #[must_use]
235 pub fn first_entry(&self) -> Option<(K, V)> {
236 self.0.first_entry(0)
237 }
238
239 /// Returns the last key-value pair in the map
240 ///
241 /// This function runs in `O(log(n))`, where `n` - is the number of nodes
242 #[must_use]
243 pub fn last_entry(&self) -> Option<(K, V)> {
244 self.0.last_entry(0)
245 }
246
247 /// Creates an iterator over key-value pairs, in order by key
248 #[must_use]
249 pub fn pairs<'b>(&'b self) -> PairsIterator<'b, 'a, K, V, KSIZE, VSIZE> {
250 self.0.pairs(0).unwrap()
251 }
252
253 /// Creates an iterator over keys, from smallest to biggest
254 #[must_use]
255 pub fn keys<'b>(&'b self) -> KeysIterator<'b, 'a, K, V, KSIZE, VSIZE> {
256 self.0.keys(0).unwrap()
257 }
258
259 /// Creates an iterator over values, in order by key
260 #[must_use]
261 pub fn values<'b>(&'b self) -> ValuesIterator<'b, 'a, K, V, KSIZE, VSIZE> {
262 self.0.values(0).unwrap()
263 }
264}
265
266impl<'a, K, V, const KSIZE: usize, const VSIZE: usize> fmt::Debug for RBTree<'a, K, V, KSIZE, VSIZE>
267where
268 K: Ord + BorshDeserialize + BorshSerialize + fmt::Debug,
269 V: BorshDeserialize + BorshSerialize + fmt::Debug,
270{
271 #[cfg(not(test))]
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
273 f.debug_map().entries(self.pairs()).finish()
274 }
275 #[cfg(test)]
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
277 self.0.fmt(f)
278 }
279}
280
281impl<'a, K, V, const KSIZE: usize, const VSIZE: usize> Extend<(K, V)>
282 for RBTree<'a, K, V, KSIZE, VSIZE>
283where
284 K: Ord + BorshDeserialize + BorshSerialize,
285 V: BorshDeserialize + BorshSerialize,
286{
287 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
288 for elem in iter {
289 self.insert(elem.0, elem.1).unwrap();
290 }
291 }
292}
293
294#[cfg(test)]
295mod tests;
296
297#[cfg(any(test, fuzzing))]
298pub mod internal_checks;