Skip to main content

anathema_store/tree/
view.rs

1use std::ops::ControlFlow;
2
3use super::{AsNodePath, InsertTransaction, Nodes, RemovedValues, TreeValues, ValueId};
4
5#[derive(Debug)]
6pub struct TreeView<'tree, T> {
7    pub offset: &'tree [u16],
8    pub values: &'tree mut TreeValues<T>,
9    pub layout: &'tree mut Nodes,
10    pub removed_values: &'tree mut RemovedValues,
11}
12
13impl<'tree, T> TreeView<'tree, T> {
14    pub fn new(
15        offset: &'tree [u16],
16        layout: &'tree mut Nodes,
17        values: &'tree mut TreeValues<T>,
18        removed_values: &'tree mut RemovedValues,
19    ) -> Self {
20        Self {
21            offset,
22            values,
23            layout,
24            removed_values,
25        }
26    }
27
28    pub fn view(&mut self) -> TreeView<'_, T> {
29        TreeView::new(self.offset, self.layout, self.values, self.removed_values)
30    }
31
32    /// Get a mutable reference by value id
33    pub fn get_mut(&mut self, value_id: ValueId) -> Option<&mut T> {
34        self.values.get_mut(value_id).map(|(_, value)| value)
35    }
36
37    /// Get a reference by value id
38    pub fn get(&self, value_id: ValueId) -> Option<&T> {
39        self.values.get(value_id).map(|(_, value)| value)
40    }
41
42    pub fn contains(&self, key: ValueId) -> bool {
43        self.values.get(key).is_some()
44    }
45
46    /// The number of children (not counting childrens children)
47    pub fn layout_len(&self) -> usize {
48        self.layout.len()
49    }
50
51    pub fn for_each<F, U>(&mut self, mut f: F) -> Option<U>
52    where
53        F: FnMut(&[u16], &mut T, TreeView<'_, T>) -> ControlFlow<U>,
54    {
55        for index in 0..self.layout.len() {
56            let node = &mut self.layout.inner[index];
57            match self.values.with_mut(node.value, |(offset, value), values| {
58                let tree_view = TreeView::new(offset, &mut node.children, values, self.removed_values);
59                f(offset, value, tree_view)
60            }) {
61                ControlFlow::Continue(_) => continue,
62                ControlFlow::Break(value) => return Some(value),
63            }
64        }
65
66        None
67    }
68
69    // The path reference for a value in the tree.
70    // Unlike a `ValueId` which will never change for a given value,
71    // the `NodePath` can change if the node is moved to another location within the tree.
72    //
73    // # Panics
74    //
75    // Panics if the value id is no long present in the tree.
76    fn path_ref(&self, id: impl Into<ValueId>) -> &[u16] {
77        let id = id.into();
78        let (path, _) = self
79            .values
80            .get(id)
81            .expect("an id should always be associated with a path");
82        path
83    }
84
85    /// The path to a value in the tree.
86    /// Unlike a `ValueId` which will never change for a given value,
87    /// the `NodePath` can change if the node is moved to another location within the tree.
88    ///
89    /// # Panics
90    ///
91    /// Panics if the value id is no long present in the tree.
92    pub fn path(&self, id: impl Into<ValueId>) -> Box<[u16]> {
93        self.path_ref(id).into()
94    }
95
96    // Find the value id by the path
97    fn id(&self, path: &[u16]) -> Option<ValueId> {
98        self.layout.with(path, |nodes| nodes.value())
99    }
100
101    /// Get a reference to the value and the value id
102    /// This has an additional cost since the value id has to
103    /// be found first.
104    pub fn get_node_and_value(&self, path: &[u16]) -> Option<(ValueId, &T)> {
105        let id = self.id(path)?;
106        self.values.get(id).map(|(_, val)| (id, val))
107    }
108
109    /// Being an insert transaction.
110    /// The transaction has to be committed before the value is written to
111    /// the tree.
112    /// ```
113    /// # use anathema_store::tree::*;
114    /// let mut tree = Tree::empty();
115    /// let mut tree = tree.view();
116    /// let transaction = tree.insert(&[]);
117    /// let value_id = transaction.commit_child(1usize).unwrap();
118    /// let one = tree.get_mut(value_id).unwrap();
119    /// assert_eq!(*one, 1);
120    /// ```
121    pub fn insert<'a>(&'a mut self, parent: &'a [u16]) -> InsertTransaction<'a, 'tree, T> {
122        InsertTransaction::new(self, parent)
123    }
124
125    /// Remove all the nodes in this view
126    pub fn truncate_children<F>(&mut self, f: &mut F)
127    where
128        F: FnMut(T),
129    {
130        self.layout.clear(self.values, self.removed_values, f);
131    }
132
133    /// Remove a `Node` and value from the tree.
134    /// This will also remove all the children and associated values.
135    pub fn relative_remove<F>(&mut self, path: &[u16], f: &mut F)
136    where
137        F: FnMut(T),
138    {
139        if self.layout.is_empty() {
140            return;
141        }
142
143        // This will not return the value that was removed, as it will also
144        // remove all the children under that node.
145        let (path, index) = path.split_parent().expect("a value will always exist within the tree");
146
147        let node = self.layout.with_mut(path, |nodes| {
148            let node = nodes.remove(index);
149
150            nodes.inner[index..].iter_mut().for_each(|node| {
151                // Update the subsequent siblings by bumping their index by one
152                let (path, _) = self.values.get_mut(node.value).expect("every node has a value");
153                path[path.len() - 1] -= 1;
154
155                // Clone the path to drop the borrow of the tree
156                let path = path.clone();
157                // Update the root of all the children of the preceding siblings
158                node.reparent(&path, self.values);
159            });
160
161            node
162        });
163
164        if let Some(mut node) = node {
165            let value_key = node.value();
166            _ = self
167                .values
168                .remove(value_key)
169                .expect("a node is always associated with a value");
170            self.removed_values.insert(value_key);
171            node.children.clear(self.values, self.removed_values, f);
172        }
173    }
174
175    /// Perform a given operation (`F`) on a mutable reference to a value in the tree
176    /// while still having mutable access to the rest of the tree.
177    ///
178    /// # Panics
179    ///
180    /// This will panic if the value is already checked out
181    pub fn with_value_mut<F, V>(&mut self, value_id: ValueId, f: F) -> Option<V>
182    where
183        F: FnOnce(&[u16], &mut T, TreeView<'_, T>) -> V,
184    {
185        let mut ticket = self.values.checkout(value_id);
186        let (path, value) = &mut *ticket;
187        let node = self.layout.get_by_path_mut(&path[self.offset.len()..])?;
188        let view = TreeView {
189            offset: path,
190            values: self.values,
191            layout: node.children_mut(),
192            removed_values: self.removed_values,
193        };
194        let value = f(path, value, view);
195        self.values.restore(ticket);
196        Some(value)
197    }
198
199    pub fn nodes_and_values(&self) -> (&[super::Node], &TreeValues<T>) {
200        (self.layout, self.values)
201    }
202
203    #[cfg(test)]
204    fn get_ref_by_path(&self, path: &[u16]) -> Option<&T> {
205        let relative = &path[self.offset.len()..];
206        let id = self.id(relative)?;
207        self.values.get(id).map(|(_, val)| val)
208    }
209}
210
211#[cfg(test)]
212mod test {
213    use super::*;
214    use crate::tree::{Tree, root_node};
215
216    #[test]
217    fn insert_and_commit() {
218        // let mut tree = Tree::<u32>::empty();
219        // let mut tree = tree.view();
220        // let transaction = tree.insert(root_node());
221        // let node_id = transaction.node_id();
222        // let value = 123;
223
224        // transaction.commit_child(value);
225
226        // assert_eq!(*tree.get_ref_by_id(node_id).unwrap(), 123);
227    }
228
229    #[test]
230    fn insert_without_commit() {
231        // let mut tree = Tree::<()>::empty();
232        // let mut tree = tree.view();
233        // let transaction = tree.insert(root_node());
234        // let node_id = transaction.node_id();
235        // assert!(tree.get_ref_by_id(node_id).is_none());
236    }
237
238    #[test]
239    fn get_by_path() {
240        let mut tree = Tree::empty();
241        let mut tree = tree.view();
242        let node_id = tree.insert(root_node()).commit_child(1).unwrap();
243        let path = tree.path(node_id);
244        tree.insert(&path).commit_child(2);
245
246        let one = tree.get_ref_by_path(&[0]).unwrap();
247        let two = tree.get_ref_by_path(&[0, 0]).unwrap();
248
249        assert_eq!(*one, 1);
250        assert_eq!(*two, 2);
251    }
252
253    #[test]
254    fn with_node_id_reading_checkedout_value() {
255        let mut tree = Tree::empty();
256        let mut tree = tree.view();
257        let key = tree.insert(root_node()).commit_child(0).unwrap();
258        tree.insert(root_node()).commit_child(1);
259        tree.with_value_mut(key, |_path, _value, mut tree| {
260            // The value is already checked out
261            assert!(tree.get_mut(key).is_none());
262        });
263    }
264
265    #[test]
266    fn remove_children() {
267        let mut tree = Tree::<u32>::empty();
268        let mut tree = tree.view();
269        tree.insert(root_node()).commit_child(1);
270        let path = &[0, 0];
271        tree.insert(path).commit_at(2);
272
273        assert!(tree.get_ref_by_path(path).is_some());
274        tree.relative_remove(path, &mut |_| {});
275        assert!(tree.get_ref_by_path(path).is_none());
276    }
277
278    // This is where we start:
279    // Insert At has to be a possibility.
280    // Scenario:
281    // * Insert at 0
282    // * Insert at len
283    // * Insert in the middle
284    #[test]
285    fn insert_at_path() {
286        let mut tree = Tree::empty();
287        let mut tree = tree.view();
288        // Setup: add two entries
289
290        // First entry
291        let key = tree.insert(root_node()).commit_child(0).unwrap();
292        let _sibling_path = tree.path_ref(key);
293
294        // Second entry (with two children)
295        let key_1 = tree.insert(root_node()).commit_child(1).unwrap();
296        let parent: Box<_> = tree.path_ref(key_1).into();
297
298        // Insert two values under the second entry
299        let key_1_0 = tree.insert(&parent).commit_child(5).unwrap();
300        let key_1_1 = tree.insert(&parent).commit_child(6).unwrap();
301
302        // Assert 1.
303        // First assertion that the paths are all rooted in [1]
304        assert_eq!(tree.path_ref(key_1), &[1]);
305        assert_eq!(tree.path_ref(key_1_0), &[1, 0]);
306        assert_eq!(tree.path_ref(key_1_1), &[1, 1]);
307
308        // Insert a node as the new first node ([0]), which should update
309        // the path for all the other entries in the tree
310        let insert_at = &[0];
311        tree.insert(insert_at).commit_at(123).unwrap();
312
313        // Assert 2
314        // Second assertion that the paths are all rooted in [2]
315        assert_eq!(tree.path_ref(key_1), &[2]);
316        assert_eq!(tree.path_ref(key_1_0), &[2, 0]);
317        assert_eq!(tree.path_ref(key_1_1), &[2, 1]);
318
319        // Insert a node as the new last node ([0]), which should update
320        // the path for all the other entries in the tree
321        let insert_at = [3];
322        let key_3 = tree.insert(&insert_at).commit_at(999).unwrap();
323
324        // Assert 3
325        assert_eq!(tree.path_ref(key_3), &[3]);
326    }
327
328    #[test]
329    fn modify_tree() {
330        let mut tree = Tree::<usize>::empty();
331        tree.view().insert(root_node()).commit_child(123);
332        let path = &[0, 0];
333        tree.view().insert(path).commit_at(1);
334
335        let mut tree = tree.view();
336        tree.for_each(|_path, outer_value, mut children| {
337            children.for_each(|_path, inner_value, mut children| {
338                let parent = &[0, 0];
339                children.insert(parent).commit_child(999);
340                let path = &[0, 0, 0];
341                let value = children.get_ref_by_path(path).unwrap();
342                assert_eq!(*value, 999);
343                assert_eq!(*outer_value, 123);
344                assert_eq!(*inner_value, 1);
345                ControlFlow::Continue::<(), _>(())
346            });
347            ControlFlow::Break(())
348        });
349    }
350}