Skip to main content

hematite/btree/
typed.rs

1//! Typed B-tree facade built on top of the raw byte-tree API.
2//!
3//! This is the convenience layer for callers that already have a stable key/value codec. It wires
4//! a [`KeyValueCodec`] into the raw byte-tree API so typed code can work with domain objects while
5//! still relying on the generic tree implementation underneath.
6
7use std::marker::PhantomData;
8use std::sync::{Arc, Mutex};
9
10use crate::btree::bytes::{ByteTree, ByteTreeCursor, ByteTreeStore};
11use crate::btree::{KeyValueCodec, TreeSpaceStats};
12use crate::error::Result;
13use crate::storage::{PageId, Pager};
14
15#[derive(Clone)]
16pub struct TypedTreeStore<C> {
17    bytes: ByteTreeStore,
18    marker: PhantomData<C>,
19}
20
21impl<C> TypedTreeStore<C> {
22    pub fn new(bytes: ByteTreeStore) -> Self {
23        Self {
24            bytes,
25            marker: PhantomData,
26        }
27    }
28
29    pub fn from_storage(storage: Pager) -> Self {
30        Self::new(ByteTreeStore::new(storage))
31    }
32
33    pub fn from_shared_storage(storage: Arc<Mutex<Pager>>) -> Self {
34        Self::new(ByteTreeStore::from_shared_storage(storage))
35    }
36
37    pub fn byte_tree_store(&self) -> &ByteTreeStore {
38        &self.bytes
39    }
40}
41
42impl<C: KeyValueCodec> TypedTreeStore<C> {
43    pub fn create_tree(&self) -> Result<PageId> {
44        self.bytes.create_tree()
45    }
46
47    pub fn open_tree(&self, root_page_id: PageId) -> Result<TypedTree<C>> {
48        Ok(TypedTree {
49            bytes: self.bytes.open_tree(root_page_id)?,
50            marker: PhantomData,
51        })
52    }
53
54    pub fn delete_tree(&self, root_page_id: PageId) -> Result<()> {
55        self.bytes.delete_tree(root_page_id)
56    }
57
58    pub fn validate_tree(&self, root_page_id: PageId) -> Result<bool> {
59        self.bytes.validate_tree(root_page_id)
60    }
61
62    pub fn reset_tree(&self, root_page_id: PageId) -> Result<()> {
63        self.bytes.reset_tree(root_page_id)
64    }
65
66    pub fn collect_page_ids(&self, root_page_id: PageId) -> Result<Vec<PageId>> {
67        self.bytes.collect_page_ids(root_page_id)
68    }
69
70    pub fn collect_space_stats(&self, root_page_id: PageId) -> Result<TreeSpaceStats> {
71        self.bytes.collect_space_stats(root_page_id)
72    }
73}
74
75pub struct TypedTree<C> {
76    bytes: ByteTree,
77    marker: PhantomData<C>,
78}
79
80impl<C: KeyValueCodec> TypedTree<C> {
81    pub fn root_page_id(&self) -> PageId {
82        self.bytes.root_page_id()
83    }
84
85    pub fn get(&mut self, key: &C::Key) -> Result<Option<C::Value>> {
86        let encoded_key = C::encode_key(key)?;
87        self.bytes
88            .get(&encoded_key)?
89            .map(|value| C::decode_value(&value))
90            .transpose()
91    }
92
93    pub fn insert(&mut self, key: &C::Key, value: &C::Value) -> Result<()> {
94        let encoded_key = C::encode_key(key)?;
95        let encoded_value = C::encode_value(value)?;
96        self.bytes.insert(&encoded_key, &encoded_value)
97    }
98
99    pub fn delete(&mut self, key: &C::Key) -> Result<Option<C::Value>> {
100        let encoded_key = C::encode_key(key)?;
101        self.bytes
102            .delete(&encoded_key)?
103            .map(|value| C::decode_value(&value))
104            .transpose()
105    }
106
107    pub fn entries(&self) -> Result<Vec<(C::Key, C::Value)>> {
108        self.bytes
109            .entries()?
110            .into_iter()
111            .map(|(key, value)| Ok((C::decode_key(&key)?, C::decode_value(&value)?)))
112            .collect()
113    }
114
115    pub fn cursor(&self) -> Result<TypedTreeCursor<C>> {
116        Ok(TypedTreeCursor {
117            bytes: self.bytes.cursor()?,
118            marker: PhantomData,
119        })
120    }
121}
122
123pub struct TypedTreeCursor<C> {
124    bytes: ByteTreeCursor,
125    marker: PhantomData<C>,
126}
127
128impl<C: KeyValueCodec> TypedTreeCursor<C> {
129    pub fn is_valid(&self) -> bool {
130        self.bytes.is_valid()
131    }
132
133    pub fn first(&mut self) -> Result<()> {
134        self.bytes.first()
135    }
136
137    pub fn next(&mut self) -> Result<()> {
138        self.bytes.next()
139    }
140
141    pub fn seek(&mut self, key: &C::Key) -> Result<()> {
142        let encoded_key = C::encode_key(key)?;
143        self.bytes.seek(&encoded_key)
144    }
145
146    pub fn current(&self) -> Result<Option<(C::Key, C::Value)>> {
147        self.bytes
148            .current()?
149            .map(|(key, value)| Ok((C::decode_key(&key)?, C::decode_value(&value)?)))
150            .transpose()
151    }
152
153    pub fn collect_all(&mut self) -> Result<Vec<(C::Key, C::Value)>> {
154        self.bytes
155            .collect_all()?
156            .into_iter()
157            .map(|(key, value)| Ok((C::decode_key(&key)?, C::decode_value(&value)?)))
158            .collect()
159    }
160}