1use crate::tree::{LeafNode, LeafNodeId};
2use crate::BPlusTree;
3use crate::Key;
4use crate::NodeStore;
5
6#[derive(Debug, Clone, Copy)]
8pub struct Cursor<K: Key> {
9 k: K,
11 leaf_id_hint: LeafNodeId,
14 offset_hint: usize,
17}
18
19impl<'k, K: Key + 'k> Cursor<K> {
20 #[inline(always)]
22 pub(crate) fn new(k: K, leaf_id: LeafNodeId, offset: usize) -> Self {
23 Self {
24 k,
25 leaf_id_hint: leaf_id,
26 offset_hint: offset,
27 }
28 }
29
30 #[inline(always)]
32 pub fn key(&self) -> &K {
33 &self.k
34 }
35
36 pub fn first<'b, S: NodeStore<K = K>>(tree: &'b BPlusTree<S>) -> Option<(Self, &'b S::V)>
38 where
39 'k: 'b,
40 {
41 let leaf_id = tree.first_leaf()?;
42 let leaf = tree.node_store.get_leaf(leaf_id);
43
44 let kv = leaf.data_at(0);
45
46 Some((
47 Self {
48 k: kv.0.clone(),
49 leaf_id_hint: leaf_id,
50 offset_hint: 0,
51 },
52 &kv.1,
53 ))
54 }
55
56 pub fn last<'b, S: NodeStore<K = K>>(tree: &'b BPlusTree<S>) -> Option<(Self, &'b S::V)>
59 where
60 'k: 'b,
61 {
62 let leaf_id = tree.last_leaf()?;
63 let leaf = tree.node_store.get_leaf(leaf_id);
64 let kv = leaf.data_at(leaf.len() - 1);
65
66 Some((
67 Self {
68 k: kv.0.clone(),
69 leaf_id_hint: leaf_id,
70 offset_hint: leaf.len() - 1,
71 },
72 &kv.1,
73 ))
74 }
75
76 pub fn prev<'a, 'b, S: NodeStore<K = K>>(&'a self, tree: &'b BPlusTree<S>) -> Option<Self> {
79 self.prev_with_value(tree).map(|x| x.0)
80 }
81
82 pub fn prev_with_value<'a, 'b, S: NodeStore<K = K>>(
85 &'a self,
86 tree: &'b BPlusTree<S>,
87 ) -> Option<(Self, &'b S::V)>
88 where
89 'k: 'b,
90 {
91 let (leaf_id, leaf) = self.locate_leaf(tree)?;
92
93 let (offset, leaf) = match leaf.try_data_at(self.offset_hint) {
94 Some(kv) if kv.0.eq(&self.k) => {
95 if self.offset_hint > 0 {
96 (self.offset_hint - 1, leaf)
97 } else if let Some(prev_id) = leaf.prev() {
98 let prev = tree.node_store.get_leaf(prev_id);
99 (prev.len() - 1, prev)
100 } else {
101 return None;
102 }
103 }
104 _ => {
105 let offset = match leaf.locate_slot(&self.k) {
106 Ok(offset) => offset,
107 Err(offset) => offset,
108 };
109
110 if offset > 0 {
111 (offset - 1, leaf)
112 } else if let Some(prev_id) = leaf.prev() {
113 let prev = tree.node_store.get_leaf(prev_id);
114 (prev.len() - 1, prev)
115 } else {
116 return None;
117 }
118 }
119 };
120
121 let kv = leaf.data_at(offset);
122 Some((
123 Self {
124 k: kv.0.clone(),
125 leaf_id_hint: leaf_id,
126 offset_hint: offset,
127 },
128 &kv.1,
129 ))
130 }
131
132 pub fn next<'a, 'b, S: NodeStore<K = K>>(&'a self, tree: &'b BPlusTree<S>) -> Option<Self> {
135 self.next_with_value(tree).map(|x| x.0)
136 }
137
138 pub fn next_with_value<'a, 'b, S: NodeStore<K = K>>(
140 &'a self,
141 tree: &'b BPlusTree<S>,
142 ) -> Option<(Self, &'b S::V)>
143 where
144 'k: 'b,
145 {
146 let (leaf_id, leaf) = self.locate_leaf(tree)?;
147
148 let next_offset = match leaf.try_data_at(self.offset_hint) {
149 Some(kv) if kv.0.eq(&self.k) => self.offset_hint + 1,
150 _ => {
151 let (offset, value) = leaf.locate_slot_with_value(&self.k);
152 match value {
153 Some(_) => offset + 1,
154 None => offset,
155 }
156 }
157 };
158
159 if next_offset < leaf.len() {
160 let kv = leaf.data_at(next_offset);
161 Some((
162 Self {
163 k: kv.0.clone(),
164 leaf_id_hint: leaf_id,
165 offset_hint: next_offset,
166 },
167 &kv.1,
168 ))
169 } else {
170 let leaf_id = leaf.next()?;
171 let leaf = tree.node_store.get_leaf(leaf_id);
172 let kv = leaf.data_at(0);
173
174 Some((
175 Self {
176 k: kv.0.clone(),
177 leaf_id_hint: leaf_id,
178 offset_hint: 0,
179 },
180 &kv.1,
181 ))
182 }
183 }
184
185 pub fn exists<'a, 'b, S: NodeStore<K = K>>(&'a self, tree: &'b BPlusTree<S>) -> bool {
187 self.value(tree).is_some()
188 }
189
190 pub fn value<'a, 'b, S: NodeStore<K = K>>(&'a self, tree: &'b BPlusTree<S>) -> Option<&'b S::V>
192 where
193 'k: 'b,
194 {
195 let (_, leaf) = self.locate_leaf(tree)?;
196
197 match leaf.try_data_at(self.offset_hint) {
198 Some(kv) if kv.0.eq(&self.k) => Some(&kv.1),
199 _ => {
200 let (_, value) = leaf.locate_slot_with_value(&self.k);
202 value
203 }
204 }
205 }
206
207 #[inline]
208 fn locate_leaf<'a, 'b, S: NodeStore<K = K>>(
209 &'a self,
210 tree: &'b BPlusTree<S>,
211 ) -> Option<(LeafNodeId, &'b LeafNode<S::K, S::V>)> {
212 let leaf_id = self.leaf_id_hint;
213 if let Some(leaf) = tree.node_store.try_get_leaf(leaf_id) {
214 if leaf.in_range(&self.k) {
215 return Some((leaf_id, leaf));
216 }
217 }
218
219 let leaf_id = tree.locate_leaf(&self.k)?;
221
222 Some((leaf_id, tree.node_store.get_leaf(leaf_id)))
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229 use crate::{tree::tests, *};
230 use rand::seq::SliceRandom;
231 use std::collections::BTreeSet;
232
233 #[test]
234 fn test_cursor_next() {
235 let (mut tree, mut keys) = tests::create_test_tree::<2000>();
236 let mut expected_count = keys.len();
237
238 keys.shuffle(&mut rand::thread_rng());
239
240 tree.node_store.debug();
241
242 let mut keys = keys.into_iter();
243
244 let (mut cursor_0, v_0) = Cursor::first(&tree).unwrap();
245
246 let (cursor_1, _) = Cursor::first(&tree).unwrap();
247
248 assert_eq!(cursor_0.k, 0);
249
250 let mut value = vec![v_0.clone()];
251 let mut keys_deleted = BTreeSet::new();
252 while let Some((c, v)) = cursor_0.next_with_value(&tree) {
253 println!("\n-------------------");
254 println!("cursor {:?}", c);
255 tree.node_store.debug();
256 assert!(!keys_deleted.contains(&c.k));
257
258 assert_eq!(c.value(&tree).unwrap(), v);
259 value.push(v.clone());
260
261 cursor_0 = c;
262
263 if keys_deleted.contains(&cursor_1.k) {
265 assert!(cursor_1.value(&tree).is_none());
266 } else {
267 assert!(cursor_1.value(&tree).is_some());
268 }
269
270 let k = keys.next().unwrap();
272 keys_deleted.insert(k);
273 tree.remove(&k);
274 if cursor_0.k < k {
275 expected_count -= 1;
276 }
277 }
278
279 assert_eq!(value.len(), expected_count);
280 assert_eq!(cursor_1.k, 0);
282 }
283
284 #[test]
285 fn test_cursor_prev() {
286 let (mut tree, mut keys) = tests::create_test_tree::<500>();
287 let mut expected_count = keys.len();
288
289 keys.shuffle(&mut rand::thread_rng());
290 let mut keys = keys.into_iter();
293
294 let mut values: Vec<i64> = vec![];
295 let (mut cursor, _v) = Cursor::last(&tree).unwrap();
296 values.push(cursor.k);
297
298 while let Some((c, _v)) = cursor.prev_with_value(&tree) {
299 values.push(c.k);
300 cursor = c;
301 let key = keys.next().unwrap();
302
303 tree.remove(&key);
304 if key < cursor.k {
305 expected_count -= 1;
306 }
307 }
308
309 assert_eq!(values.len(), expected_count);
310 }
311}