1use super::*;
2use crate::{CowPage, LoadPage};
3use core::mem::MaybeUninit;
4
5#[derive(Debug)]
6pub(super) struct PageCursor<K: ?Sized, V: ?Sized, P: BTreePage<K, V>> {
7 pub page: CowPage,
8 pub cursor: P::Cursor,
9}
10
11pub(crate) const N_CURSORS: usize = 33;
20
21#[derive(Debug)]
22pub struct Cursor<K: ?Sized, V: ?Sized, P: BTreePage<K, V>> {
24 stack: [core::mem::MaybeUninit<PageCursor<K, V, P>>; N_CURSORS],
26 first_rc_len: usize,
32 len: usize,
34}
35
36impl<K: ?Sized + Storable, V: ?Sized + Storable, P: BTreePage<K, V>> Cursor<K, V, P> {
37 pub fn new<T: LoadPage>(txn: &T, db: &Db_<K, V, P>) -> Result<Self, T::Error> {
39 let mut stack = [
41 core::mem::MaybeUninit::uninit(),
42 core::mem::MaybeUninit::uninit(),
43 core::mem::MaybeUninit::uninit(),
44 core::mem::MaybeUninit::uninit(),
45 core::mem::MaybeUninit::uninit(),
46 core::mem::MaybeUninit::uninit(),
47 core::mem::MaybeUninit::uninit(),
48 core::mem::MaybeUninit::uninit(),
49 core::mem::MaybeUninit::uninit(),
50 core::mem::MaybeUninit::uninit(),
51 core::mem::MaybeUninit::uninit(),
52 core::mem::MaybeUninit::uninit(),
53 core::mem::MaybeUninit::uninit(),
54 core::mem::MaybeUninit::uninit(),
55 core::mem::MaybeUninit::uninit(),
56 core::mem::MaybeUninit::uninit(),
57 core::mem::MaybeUninit::uninit(),
58 core::mem::MaybeUninit::uninit(),
59 core::mem::MaybeUninit::uninit(),
60 core::mem::MaybeUninit::uninit(),
61 core::mem::MaybeUninit::uninit(),
62 core::mem::MaybeUninit::uninit(),
63 core::mem::MaybeUninit::uninit(),
64 core::mem::MaybeUninit::uninit(),
65 core::mem::MaybeUninit::uninit(),
66 core::mem::MaybeUninit::uninit(),
67 core::mem::MaybeUninit::uninit(),
68 core::mem::MaybeUninit::uninit(),
69 core::mem::MaybeUninit::uninit(),
70 core::mem::MaybeUninit::uninit(),
71 core::mem::MaybeUninit::uninit(),
72 core::mem::MaybeUninit::uninit(),
73 core::mem::MaybeUninit::uninit(),
74 ];
75 let page = unsafe { txn.load_page(db.db.into())? };
76 if page.offset == 0 {
77 return Ok(Cursor {
78 stack,
79 first_rc_len: N_CURSORS,
80 len: 0,
81 });
82 }
83 stack[0] = MaybeUninit::new(PageCursor {
84 cursor: P::cursor_before(&page),
85 page,
86 });
87 Ok(Cursor {
88 stack,
89 first_rc_len: N_CURSORS,
90 len: 1,
91 })
92 }
93
94 pub(super) fn push(&mut self, p: PageCursor<K, V, P>) {
95 self.stack[self.len] = MaybeUninit::new(p);
96 self.len += 1;
97 }
98
99 pub(super) fn cur(&self) -> &PageCursor<K, V, P> {
100 assert!(self.len > 0);
101 unsafe { &*self.stack[self.len - 1].as_ptr() }
102 }
103
104 pub(super) fn len(&self) -> usize {
105 self.len
106 }
107
108 pub(super) fn first_rc_len(&self) -> usize {
109 self.first_rc_len
110 }
111
112 pub(super) fn pop(&mut self) -> Option<PageCursor<K, V, P>> {
113 if self.len > 0 {
114 self.len -= 1;
115 let result = core::mem::replace(&mut self.stack[self.len], MaybeUninit::uninit());
116 Some(unsafe { result.assume_init() })
117 } else {
118 None
119 }
120 }
121
122 pub(super) fn current_mut(&mut self) -> &mut PageCursor<K, V, P> {
123 assert!(self.len > 0);
124 unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() }
125 }
126
127 pub(super) fn set_first_leaf<T: LoadPage>(
130 &mut self,
131 txn: &T,
132 mut left_page: u64,
133 ) -> Result<(), T::Error> {
134 while left_page > 0 {
135 if self.first_rc_len >= N_CURSORS && txn.rc(left_page)? >= 2 {
136 self.first_rc_len = self.len + 1
137 }
138 let page = unsafe { txn.load_page(left_page)? };
139 if page.offset == 0 {
140 break;
141 }
142 let curs = P::cursor_first(&page);
143 left_page = P::left_child(page.as_page(), &curs);
144 self.push(PageCursor { page, cursor: curs });
145 }
146 Ok(())
147 }
148
149 pub fn reset<'a, T: LoadPage>(&mut self) {
151 self.len = 1;
152 let init = unsafe { &mut *self.stack[0].as_mut_ptr() };
153 init.cursor = P::cursor_before(&init.page);
154 }
155
156 pub fn set<'a, T: LoadPage>(
164 &mut self,
165 txn: &'a T,
166 k: &K,
167 v: Option<&V>,
168 ) -> Result<Option<(&'a K, &'a V)>, T::Error> {
169 self.len = 1;
175 self.first_rc_len = N_CURSORS;
176 let init = unsafe { &mut *self.stack[0].as_mut_ptr() };
177 init.cursor = P::cursor_before(&init.page);
178
179 let mut last_matching_page = N_CURSORS;
180 let mut last_match = None;
181 while self.len < N_CURSORS {
182 let current = unsafe { &mut *self.stack.get_unchecked_mut(self.len - 1).as_mut_ptr() };
183 if self.first_rc_len >= N_CURSORS && txn.rc(current.page.offset)? >= 2 {
184 self.first_rc_len = self.len
185 }
186 let ref mut cursor = current.cursor;
187 if let Ok((kk, vv, _)) = P::set_cursor(txn, current.page.as_page(), cursor, k, v) {
188 if v.is_some() {
189 return Ok(Some((kk, vv)));
190 }
191 last_match = Some((kk, vv));
192 last_matching_page = self.len
193 }
194 let next_page = P::left_child(current.page.as_page(), cursor);
195 if next_page > 0 {
196 let page = unsafe { txn.load_page(next_page)? };
197 if page.offset == 0 {
198 break;
199 }
200 self.push(PageCursor {
201 cursor: P::cursor_before(&page),
202 page,
203 });
204 } else {
205 break;
206 }
207 }
208 if last_matching_page < N_CURSORS {
209 self.len = last_matching_page;
210 Ok(last_match)
211 } else {
212 Ok(None)
213 }
214 }
215
216 pub fn set_last<'a, T: LoadPage>(&mut self, txn: &'a T) -> Result<(), T::Error> {
219 self.len = 1;
220 self.first_rc_len = N_CURSORS;
221 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
222 current.cursor = P::cursor_after(¤t.page);
223 loop {
224 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
225 if self.first_rc_len >= N_CURSORS && txn.rc(current.page.offset)? >= 2 {
226 self.first_rc_len = self.len
227 }
228 let l = P::left_child(current.page.as_page(), ¤t.cursor);
229 if l > 0 {
230 let page = unsafe { txn.load_page(l)? };
231 if page.offset == 0 {
232 break;
233 }
234 self.push(PageCursor {
235 cursor: P::cursor_after(&page),
236 page,
237 })
238 } else {
239 break;
240 }
241 }
242 Ok(())
243 }
244
245 pub fn current<'a, T: LoadPage>(
247 &mut self,
248 txn: &'a T,
249 ) -> Result<Option<(&'a K, &'a V)>, T::Error> {
250 loop {
251 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
252 if P::is_init(¤t.cursor) {
253 return Ok(None);
255 } else if let Some((k, v, _)) = P::current(txn, current.page.as_page(), ¤t.cursor)
256 {
257 unsafe {
258 return Ok(Some((core::mem::transmute(k), core::mem::transmute(v))));
259 }
260 } else if self.len > 1 {
261 self.len -= 1
262 } else {
263 return Ok(None);
265 }
266 }
267 }
268
269 pub fn next<'a, T: LoadPage>(
272 &mut self,
273 txn: &'a T,
274 ) -> Result<Option<(&'a K, &'a V)>, T::Error> {
275 loop {
276 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
277 if P::is_empty(¤t.cursor) {
278 if self.len > 1 {
279 if self.first_rc_len == self.len {
280 self.first_rc_len = N_CURSORS
281 }
282 self.len -= 1
283 } else {
284 return Ok(None);
285 }
286 } else {
287 let (cur_entry, r) = if let Some((k, v, r)) =
288 P::current(txn, current.page.as_page(), ¤t.cursor)
289 {
290 (Some((k, v)), r)
291 } else {
292 (
293 None,
294 P::right_child(current.page.as_page(), ¤t.cursor),
295 )
296 };
297 P::move_next(&mut current.cursor);
298 if r != 0 {
299 let page = unsafe { txn.load_page(r)? };
300 if page.offset == 0 {
301 return Ok(None);
302 }
303 self.push(PageCursor {
304 cursor: P::cursor_before(&page),
305 page,
306 });
307 if self.first_rc_len >= N_CURSORS && txn.rc(r)? >= 2 {
308 self.first_rc_len = self.len
309 }
310 }
311 if let Some((k, v)) = cur_entry {
312 unsafe {
313 return Ok(Some((core::mem::transmute(k), core::mem::transmute(v))));
314 }
315 }
316 }
317 }
318 }
319
320 pub fn prev<'a, T: LoadPage>(
324 &mut self,
325 txn: &'a T,
326 ) -> Result<Option<(&'a K, &'a V)>, T::Error> {
327 loop {
328 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
329
330 if P::is_init(¤t.cursor) {
331 if self.len > 1 {
332 if self.first_rc_len == self.len {
333 self.first_rc_len = N_CURSORS
334 }
335 self.len -= 1;
336 let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };
337 P::move_prev(&mut current.cursor);
338 } else {
339 return Ok(None);
340 }
341 } else {
342 let cur_entry = P::current(txn, current.page.as_page(), ¤t.cursor);
343 let left = P::left_child(current.page.as_page(), ¤t.cursor);
344 if left != 0 {
345 let page = unsafe { txn.load_page(left)? };
346 if page.offset == 0 {
347 return Ok(None);
348 }
349 self.push(PageCursor {
350 cursor: P::cursor_after(&page),
351 page,
352 });
353 if self.first_rc_len >= N_CURSORS && txn.rc(left)? >= 2 {
354 self.first_rc_len = self.len
355 }
356 } else {
357 P::move_prev(&mut current.cursor);
359 }
360 if let Some((k, v, _)) = cur_entry {
361 unsafe {
362 return Ok(Some((core::mem::transmute(k), core::mem::transmute(v))));
363 }
364 }
365 }
366 }
367 }
368}
369
370pub struct Iter<'a, T: LoadPage, K: Storable + ?Sized, V: Storable + ?Sized, P: BTreePage<K, V>> {
371 txn: &'a T,
372 cursor: Cursor<K, V, P>,
373}
374
375pub fn iter<'a, T, K, V, P>(
376 txn: &'a T,
377 db: &super::Db_<K, V, P>,
378 origin: Option<(&K, Option<&V>)>,
379) -> Result<Iter<'a, T, K, V, P>, T::Error>
380where
381 T: LoadPage,
382 K: Storable + ?Sized,
383 V: Storable + ?Sized,
384 P: BTreePage<K, V>,
385{
386 let mut cursor = Cursor::new(txn, db)?;
387 if let Some((k, v)) = origin {
388 cursor.set(txn, k, v)?;
389 }
390 Ok(Iter { cursor, txn })
391}
392
393impl<
394 'a,
395 T: LoadPage,
396 K: Storable + ?Sized + 'a,
397 V: Storable + ?Sized + 'a,
398 P: BTreePage<K, V> + 'a,
399 > Iterator for Iter<'a, T, K, V, P>
400{
401 type Item = Result<(&'a K, &'a V), T::Error>;
402 fn next(&mut self) -> Option<Self::Item> {
403 self.cursor.next(self.txn).transpose()
404 }
405}
406
407pub struct RevIter<'a, T: LoadPage, K: Storable + ?Sized, V: Storable + ?Sized, P: BTreePage<K, V>>
408{
409 txn: &'a T,
410 cursor: Cursor<K, V, P>,
411}
412
413pub fn rev_iter<'a, T, K, V, P>(
414 txn: &'a T,
415 db: &super::Db_<K, V, P>,
416 origin: Option<(&K, Option<&V>)>,
417) -> Result<RevIter<'a, T, K, V, P>, T::Error>
418where
419 T: LoadPage,
420 K: Storable + ?Sized,
421 V: Storable + ?Sized,
422 P: BTreePage<K, V>,
423{
424 let mut cursor = Cursor::new(txn, db)?;
425 if let Some((k, v)) = origin {
426 cursor.set(txn, k, v)?;
427 } else {
428 cursor.set_last(txn)?;
429 }
430 Ok(RevIter { cursor, txn })
431}
432
433impl<
434 'a,
435 T: LoadPage,
436 K: Storable + ?Sized + 'a,
437 V: Storable + ?Sized + 'a,
438 P: BTreePage<K, V> + 'a,
439 > Iterator for RevIter<'a, T, K, V, P>
440{
441 type Item = Result<(&'a K, &'a V), T::Error>;
442 fn next(&mut self) -> Option<Self::Item> {
443 self.cursor.prev(self.txn).transpose()
444 }
445}