1use super::page::{MAX_HEIGHT, Node, Record};
2use super::{BTreeMap, Comparator, Error, Memory};
3use std::{cmp::Ordering, iter::FusedIterator, ops::Bound};
4
5pub 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 #[must_use]
17 pub fn key(&self) -> &[u8] {
18 &self.key
19 }
20 #[must_use]
22 pub const fn value_len(&self) -> u64 {
23 self.record.value_len
24 }
25 pub fn value(&self) -> Result<Vec<u8>, Error> {
29 self.tree.value(self.record)
30 }
31 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
140pub 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> {}