Skip to main content

ic_storage/btree/
cursor.rs

1use super::page::{MAX_HEIGHT, Node, Record};
2use super::{BTreeMap, Comparator, Error, Memory};
3use std::{cmp::Ordering, iter::FusedIterator, ops::Bound};
4
5/// One scanned key with an unread value descriptor.
6///
7/// Holding an entry borrows the tree, preventing mutation through that handle.
8/// Inspecting the key never reads the value payload.
9pub struct Entry<'a, M, C = super::Lexicographic> {
10    tree: &'a BTreeMap<M, C>,
11    key: Vec<u8>,
12    record: Record,
13}
14impl<M: Memory, C: Comparator> Entry<'_, M, C> {
15    /// Borrow the encoded key.
16    #[must_use]
17    pub fn key(&self) -> &[u8] {
18        &self.key
19    }
20    /// Encoded value size, without loading its payload.
21    #[must_use]
22    pub const fn value_len(&self) -> u64 {
23        self.record.value_len
24    }
25    /// Load and validate this entry's value bytes.
26    /// # Errors
27    /// Returns an error on observed payload corruption.
28    pub fn value(&self) -> Result<Vec<u8>, Error> {
29        self.tree.value(self.record)
30    }
31    /// Consume the entry and load its value.
32    /// # Errors
33    /// Returns an error on observed payload corruption.
34    pub fn into_pair(self) -> Result<(Vec<u8>, Vec<u8>), Error> {
35        let value = self.value()?;
36        Ok((self.key, value))
37    }
38}
39struct Frame {
40    node: Node,
41    position: usize,
42}
43struct Cursor {
44    frames: Vec<Frame>,
45    reverse: bool,
46    started: bool,
47    pending_child: Option<u64>,
48}
49impl Cursor {
50    const fn new(reverse: bool) -> Self {
51        Self {
52            frames: Vec::new(),
53            reverse,
54            started: false,
55            pending_child: None,
56        }
57    }
58    fn seek<M: Memory, C: Comparator>(
59        &mut self,
60        tree: &BTreeMap<M, C>,
61        bound: &Bound<Vec<u8>>,
62    ) -> Result<(), Error> {
63        self.started = true;
64        let mut id = tree.header.root;
65        for _ in 0..MAX_HEIGHT {
66            let node = tree.node(id)?;
67            let (at, found, inclusive) = match bound {
68                Bound::Unbounded => (
69                    if self.reverse { node.entries.len() } else { 0 },
70                    false,
71                    false,
72                ),
73                Bound::Included(key) | Bound::Excluded(key) => {
74                    let (at, found) = tree.locate(&node, key)?;
75                    (at, found, matches!(bound, Bound::Included(_)))
76                }
77            };
78            let position = at + usize::from(found && (self.reverse == inclusive));
79            let child = if found && inclusive {
80                None
81            } else {
82                node.children.get(position).copied()
83            };
84            self.frames.push(Frame { node, position });
85            if let Some(child) = child {
86                id = child;
87            } else {
88                return Ok(());
89            }
90        }
91        Err(Error::Corrupt)
92    }
93    fn descend<M: Memory, C: Comparator>(
94        &mut self,
95        tree: &BTreeMap<M, C>,
96        mut id: u64,
97    ) -> Result<(), Error> {
98        while self.frames.len() < MAX_HEIGHT {
99            let node = tree.node(id)?;
100            let position = if self.reverse { node.entries.len() } else { 0 };
101            let child = node.children.get(position).copied();
102            self.frames.push(Frame { node, position });
103            if let Some(child) = child {
104                id = child;
105            } else {
106                return Ok(());
107            }
108        }
109        Err(Error::Corrupt)
110    }
111    fn next<M: Memory, C: Comparator>(
112        &mut self,
113        tree: &BTreeMap<M, C>,
114    ) -> Result<Option<Record>, Error> {
115        if let Some(child) = self.pending_child.take() {
116            self.descend(tree, child)?;
117        }
118        while let Some(frame) = self.frames.last_mut() {
119            if (self.reverse && frame.position == 0)
120                || (!self.reverse && frame.position == frame.node.entries.len())
121            {
122                self.frames.pop();
123                continue;
124            }
125            let index = if self.reverse {
126                frame.position - 1
127            } else {
128                frame.position
129            };
130            let record = frame.node.entries[index];
131            frame.position = if self.reverse { index } else { index + 1 };
132            let child = frame.node.children.get(frame.position).copied();
133            self.pending_child = child;
134            return Ok(Some(record));
135        }
136        Ok(None)
137    }
138}
139
140/// Fallible, double-ended traversal with bounded tree-path memory.
141///
142/// Each direction seeks once, then walks the tree in order. The first observed
143/// error ends iteration. Values are loaded only by [`Entry::value`].
144pub struct Range<'a, M, C = super::Lexicographic> {
145    tree: &'a BTreeMap<M, C>,
146    lower: Bound<Vec<u8>>,
147    upper: Bound<Vec<u8>>,
148    front: Cursor,
149    back: Cursor,
150    done: bool,
151}
152impl<'a, M: Memory, C: Comparator> Range<'a, M, C> {
153    pub(super) fn all(tree: &'a BTreeMap<M, C>) -> Self {
154        Self {
155            tree,
156            lower: Bound::Unbounded,
157            upper: Bound::Unbounded,
158            front: Cursor::new(false),
159            back: Cursor::new(true),
160            done: false,
161        }
162    }
163    pub(super) fn new(
164        tree: &'a BTreeMap<M, C>,
165        lower: Bound<&[u8]>,
166        upper: Bound<&[u8]>,
167    ) -> Result<Self, Error> {
168        for bound in [&lower, &upper] {
169            if let Bound::Included(key) | Bound::Excluded(key) = bound {
170                tree.check_key(key)?;
171            }
172        }
173        if let (
174            Bound::Included(left) | Bound::Excluded(left),
175            Bound::Included(right) | Bound::Excluded(right),
176        ) = (lower, upper)
177        {
178            if tree.order.compare(left, right)? == Ordering::Greater {
179                return Err(Error::InvalidRange);
180            }
181        }
182        Ok(Self {
183            lower: lower.map(<[u8]>::to_vec),
184            upper: upper.map(<[u8]>::to_vec),
185            ..Self::all(tree)
186        })
187    }
188    fn advance(&mut self, reverse: bool) -> Result<Option<Entry<'a, M, C>>, Error> {
189        let (cursor, bound) = if reverse {
190            (&mut self.back, &self.upper)
191        } else {
192            (&mut self.front, &self.lower)
193        };
194        if !cursor.started {
195            cursor.seek(self.tree, bound)?;
196        }
197        let Some(record) = cursor.next(self.tree)? else {
198            return Ok(None);
199        };
200        let key = self.tree.key(record)?;
201        self.tree.check_key(&key)?;
202        for (bound, forbidden) in [
203            (&self.lower, Ordering::Less),
204            (&self.upper, Ordering::Greater),
205        ] {
206            if let Bound::Included(limit) | Bound::Excluded(limit) = bound {
207                let comparison = self.tree.order.compare(&key, limit)?;
208                if comparison == forbidden
209                    || (comparison == Ordering::Equal && matches!(bound, Bound::Excluded(_)))
210                {
211                    return Ok(None);
212                }
213            }
214        }
215        if reverse {
216            self.upper = Bound::Excluded(key.clone());
217        } else {
218            self.lower = Bound::Excluded(key.clone());
219        }
220        Ok(Some(Entry {
221            tree: self.tree,
222            key,
223            record,
224        }))
225    }
226    fn step(&mut self, reverse: bool) -> Option<Result<Entry<'a, M, C>, Error>> {
227        if self.done {
228            return None;
229        }
230        match self.advance(reverse) {
231            Ok(Some(entry)) => Some(Ok(entry)),
232            Ok(None) => {
233                self.done = true;
234                None
235            }
236            Err(error) => {
237                self.done = true;
238                Some(Err(error))
239            }
240        }
241    }
242}
243impl<'a, M: Memory, C: Comparator> Iterator for Range<'a, M, C> {
244    type Item = Result<Entry<'a, M, C>, Error>;
245    fn next(&mut self) -> Option<Self::Item> {
246        self.step(false)
247    }
248}
249impl<M: Memory, C: Comparator> DoubleEndedIterator for Range<'_, M, C> {
250    fn next_back(&mut self) -> Option<Self::Item> {
251        self.step(true)
252    }
253}
254impl<M: Memory, C: Comparator> FusedIterator for Range<'_, M, C> {}