1use crate::{
2 error::{mdbx_result, Error, Result},
3 flags::*,
4 mdbx_try_optional,
5 transaction::{TransactionKind, RW},
6 TableObject, Transaction,
7};
8use ffi::{
9 MDBX_cursor_op, MDBX_FIRST, MDBX_FIRST_DUP, MDBX_GET_BOTH, MDBX_GET_BOTH_RANGE,
10 MDBX_GET_CURRENT, MDBX_GET_MULTIPLE, MDBX_LAST, MDBX_LAST_DUP, MDBX_NEXT, MDBX_NEXT_DUP,
11 MDBX_NEXT_MULTIPLE, MDBX_NEXT_NODUP, MDBX_PREV, MDBX_PREV_DUP, MDBX_PREV_MULTIPLE,
12 MDBX_PREV_NODUP, MDBX_SET, MDBX_SET_KEY, MDBX_SET_LOWERBOUND, MDBX_SET_RANGE,
13};
14use std::{borrow::Cow, ffi::c_void, fmt, marker::PhantomData, mem, ptr};
15
16pub struct Cursor<K>
18where
19 K: TransactionKind,
20{
21 txn: Transaction<K>,
22 cursor: *mut ffi::MDBX_cursor,
23}
24
25impl<K> Cursor<K>
26where
27 K: TransactionKind,
28{
29 pub(crate) fn new(txn: Transaction<K>, dbi: ffi::MDBX_dbi) -> Result<Self> {
30 let mut cursor: *mut ffi::MDBX_cursor = ptr::null_mut();
31 unsafe {
32 txn.txn_execute(|txn_ptr| {
33 mdbx_result(ffi::mdbx_cursor_open(txn_ptr, dbi, &mut cursor))
34 })??;
35 }
36 Ok(Self { txn, cursor })
37 }
38
39 fn new_at_position(other: &Self) -> Result<Self> {
40 unsafe {
41 let cursor = ffi::mdbx_cursor_create(ptr::null_mut());
42
43 let res = ffi::mdbx_cursor_copy(other.cursor(), cursor);
44
45 let s = Self {
46 txn: other.txn.clone(),
47 cursor,
48 };
49
50 mdbx_result(res)?;
51
52 Ok(s)
53 }
54 }
55
56 pub const fn cursor(&self) -> *mut ffi::MDBX_cursor {
61 self.cursor
62 }
63
64 #[allow(clippy::needless_lifetimes)]
66 pub fn iter_slices<'a>(&'a self) -> IntoIter<'a, K, Cow<'a, [u8]>, Cow<'a, [u8]>> {
67 self.into_iter()
68 }
69
70 #[allow(clippy::should_implement_trait)]
72 pub fn into_iter<Key, Value>(&self) -> IntoIter<'_, K, Key, Value>
73 where
74 Key: TableObject,
75 Value: TableObject,
76 {
77 IntoIter::new(self.clone(), MDBX_NEXT, MDBX_NEXT)
78 }
79
80 pub(crate) fn get<Key, Value>(
83 &self,
84 key: Option<&[u8]>,
85 data: Option<&[u8]>,
86 op: MDBX_cursor_op,
87 ) -> Result<(Option<Key>, Value, bool)>
88 where
89 Key: TableObject,
90 Value: TableObject,
91 {
92 unsafe {
93 let mut key_val = slice_to_val(key);
94 let mut data_val = slice_to_val(data);
95 let key_ptr = key_val.iov_base;
96 let data_ptr = data_val.iov_base;
97 self.txn.txn_execute(|txn| {
98 let v = mdbx_result(ffi::mdbx_cursor_get(
99 self.cursor,
100 &mut key_val,
101 &mut data_val,
102 op,
103 ))?;
104 assert_ne!(data_ptr, data_val.iov_base);
105 let key_out = {
106 if key_ptr == key_val.iov_base {
108 None
109 } else {
110 Some(Key::decode_val::<K>(txn, key_val)?)
111 }
112 };
113 let data_out = Value::decode_val::<K>(txn, data_val)?;
114 Ok((key_out, data_out, v))
115 })?
116 }
117 }
118
119 pub(crate) fn get_value<Value>(
120 &mut self,
121 key: Option<&[u8]>,
122 data: Option<&[u8]>,
123 op: MDBX_cursor_op,
124 ) -> Result<Option<Value>>
125 where
126 Value: TableObject,
127 {
128 let (_, v, _) = mdbx_try_optional!(self.get::<(), Value>(key, data, op));
129
130 Ok(Some(v))
131 }
132
133 pub(crate) fn get_full<Key, Value>(
134 &mut self,
135 key: Option<&[u8]>,
136 data: Option<&[u8]>,
137 op: MDBX_cursor_op,
138 ) -> Result<Option<(Key, Value)>>
139 where
140 Key: TableObject,
141 Value: TableObject,
142 {
143 let (k, v, _) = mdbx_try_optional!(self.get(key, data, op));
144
145 Ok(Some((k.unwrap(), v)))
146 }
147
148 pub fn first<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
150 where
151 Key: TableObject,
152 Value: TableObject,
153 {
154 self.get_full(None, None, MDBX_FIRST)
155 }
156
157 pub fn first_dup<Value>(&mut self) -> Result<Option<Value>>
159 where
160 Value: TableObject,
161 {
162 self.get_value(None, None, MDBX_FIRST_DUP)
163 }
164
165 pub fn get_both<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>>
167 where
168 Value: TableObject,
169 {
170 self.get_value(Some(k), Some(v), MDBX_GET_BOTH)
171 }
172
173 pub fn get_both_range<Value>(&mut self, k: &[u8], v: &[u8]) -> Result<Option<Value>>
176 where
177 Value: TableObject,
178 {
179 self.get_value(Some(k), Some(v), MDBX_GET_BOTH_RANGE)
180 }
181
182 pub fn get_current<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
184 where
185 Key: TableObject,
186 Value: TableObject,
187 {
188 self.get_full(None, None, MDBX_GET_CURRENT)
189 }
190
191 pub fn get_multiple<Value>(&mut self) -> Result<Option<Value>>
194 where
195 Value: TableObject,
196 {
197 self.get_value(None, None, MDBX_GET_MULTIPLE)
198 }
199
200 pub fn last<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
202 where
203 Key: TableObject,
204 Value: TableObject,
205 {
206 self.get_full(None, None, MDBX_LAST)
207 }
208
209 pub fn last_dup<Value>(&mut self) -> Result<Option<Value>>
211 where
212 Value: TableObject,
213 {
214 self.get_value(None, None, MDBX_LAST_DUP)
215 }
216
217 #[allow(clippy::should_implement_trait)]
219 pub fn next<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
220 where
221 Key: TableObject,
222 Value: TableObject,
223 {
224 self.get_full(None, None, MDBX_NEXT)
225 }
226
227 pub fn next_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
229 where
230 Key: TableObject,
231 Value: TableObject,
232 {
233 self.get_full(None, None, MDBX_NEXT_DUP)
234 }
235
236 pub fn next_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
239 where
240 Key: TableObject,
241 Value: TableObject,
242 {
243 self.get_full(None, None, MDBX_NEXT_MULTIPLE)
244 }
245
246 pub fn next_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
248 where
249 Key: TableObject,
250 Value: TableObject,
251 {
252 self.get_full(None, None, MDBX_NEXT_NODUP)
253 }
254
255 pub fn prev<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
257 where
258 Key: TableObject,
259 Value: TableObject,
260 {
261 self.get_full(None, None, MDBX_PREV)
262 }
263
264 pub fn prev_dup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
266 where
267 Key: TableObject,
268 Value: TableObject,
269 {
270 self.get_full(None, None, MDBX_PREV_DUP)
271 }
272
273 pub fn prev_nodup<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
275 where
276 Key: TableObject,
277 Value: TableObject,
278 {
279 self.get_full(None, None, MDBX_PREV_NODUP)
280 }
281
282 pub fn set<Value>(&mut self, key: &[u8]) -> Result<Option<Value>>
284 where
285 Value: TableObject,
286 {
287 self.get_value(Some(key), None, MDBX_SET)
288 }
289
290 pub fn set_key<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>>
292 where
293 Key: TableObject,
294 Value: TableObject,
295 {
296 self.get_full(Some(key), None, MDBX_SET_KEY)
297 }
298
299 pub fn set_range<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(Key, Value)>>
301 where
302 Key: TableObject,
303 Value: TableObject,
304 {
305 self.get_full(Some(key), None, MDBX_SET_RANGE)
306 }
307
308 pub fn prev_multiple<Key, Value>(&mut self) -> Result<Option<(Key, Value)>>
311 where
312 Key: TableObject,
313 Value: TableObject,
314 {
315 self.get_full(None, None, MDBX_PREV_MULTIPLE)
316 }
317
318 pub fn set_lowerbound<Key, Value>(&mut self, key: &[u8]) -> Result<Option<(bool, Key, Value)>>
328 where
329 Key: TableObject,
330 Value: TableObject,
331 {
332 let (k, v, found) = mdbx_try_optional!(self.get(Some(key), None, MDBX_SET_LOWERBOUND));
333
334 Ok(Some((found, k.unwrap(), v)))
335 }
336
337 pub fn iter<Key, Value>(&mut self) -> Iter<'_, K, Key, Value>
346 where
347 Key: TableObject,
348 Value: TableObject,
349 {
350 Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT)
351 }
352
353 pub fn iter_start<Key, Value>(&mut self) -> Iter<'_, K, Key, Value>
359 where
360 Key: TableObject,
361 Value: TableObject,
362 {
363 Iter::new(self, ffi::MDBX_FIRST, ffi::MDBX_NEXT)
364 }
365
366 pub fn iter_from<Key, Value>(&mut self, key: &[u8]) -> Iter<'_, K, Key, Value>
372 where
373 Key: TableObject,
374 Value: TableObject,
375 {
376 let res: Result<Option<((), ())>> = self.set_range(key);
377 if let Err(error) = res {
378 return Iter::Err(Some(error));
379 };
380 Iter::new(self, ffi::MDBX_GET_CURRENT, ffi::MDBX_NEXT)
381 }
382
383 pub fn iter_dup<Key, Value>(&mut self) -> IterDup<'_, K, Key, Value>
387 where
388 Key: TableObject,
389 Value: TableObject,
390 {
391 IterDup::new(self, ffi::MDBX_NEXT)
392 }
393
394 pub fn into_iter_dup<Key, Value>(&self) -> IntoIterDup<'_, K, Key, Value>
395 where
396 Key: TableObject,
397 Value: TableObject,
398 {
399 IntoIterDup::new(self.clone(), ffi::MDBX_NEXT)
400 }
401
402 pub fn iter_dup_start<Key, Value>(&mut self) -> IterDup<'_, K, Key, Value>
405 where
406 Key: TableObject,
407 Value: TableObject,
408 {
409 IterDup::new(self, ffi::MDBX_FIRST)
410 }
411
412 pub fn into_iter_dup_start<Key, Value>(&self) -> IntoIterDup<'_, K, Key, Value>
413 where
414 Key: TableObject,
415 Value: TableObject,
416 {
417 IntoIterDup::new(self.clone(), ffi::MDBX_FIRST)
418 }
419
420 pub fn iter_dup_from<Key, Value>(&mut self, key: &[u8]) -> IterDup<'_, K, Key, Value>
423 where
424 Key: TableObject,
425 Value: TableObject,
426 {
427 let res: Result<Option<((), ())>> = self.set_range(key);
428 if let Err(error) = res {
429 return IterDup::Err(Some(error));
430 };
431 IterDup::new(self, ffi::MDBX_GET_CURRENT)
432 }
433
434 pub fn into_iter_dup_from<Key, Value>(&mut self, key: &[u8]) -> IntoIterDup<'_, K, Key, Value>
435 where
436 Key: TableObject,
437 Value: TableObject,
438 {
439 let res: Result<Option<((), ())>> = self.set_range(key);
440 if let Err(error) = res {
441 return IntoIterDup::Err(Some(error));
442 };
443 IntoIterDup::new(self.clone(), ffi::MDBX_GET_CURRENT)
444 }
445
446 pub fn iter_dup_of<Key, Value>(&mut self, key: &[u8]) -> Iter<'_, K, Key, Value>
448 where
449 Key: TableObject,
450 Value: TableObject,
451 {
452 let res: Result<Option<()>> = self.set(key);
453 match res {
454 Ok(Some(_)) => (),
455 Ok(None) => {
456 let _: Result<Option<((), ())>> = self.last();
457 return Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT);
458 }
459 Err(error) => return Iter::Err(Some(error)),
460 };
461 Iter::new(self, ffi::MDBX_GET_CURRENT, ffi::MDBX_NEXT_DUP)
462 }
463
464 pub fn into_iter_dup_of<Key, Value>(&mut self, key: &[u8]) -> IntoIter<'_, K, Key, Value>
465 where
466 Key: TableObject,
467 Value: TableObject,
468 {
469 let res: Result<Option<()>> = self.set(key);
470 match res {
471 Ok(Some(_)) => (),
472 Ok(None) => {
473 let _: Result<Option<((), ())>> = self.last();
474 return IntoIter::new(self.clone(), ffi::MDBX_NEXT, ffi::MDBX_NEXT);
475 }
476 Err(error) => return IntoIter::Err(Some(error)),
477 };
478 IntoIter::new(self.clone(), ffi::MDBX_GET_CURRENT, ffi::MDBX_NEXT_DUP)
479 }
480}
481
482impl Cursor<RW> {
483 pub fn put(&mut self, key: &[u8], data: &[u8], flags: WriteFlags) -> Result<()> {
486 let key_val: ffi::MDBX_val = ffi::MDBX_val {
487 iov_len: key.len(),
488 iov_base: key.as_ptr() as *mut c_void,
489 };
490 let mut data_val: ffi::MDBX_val = ffi::MDBX_val {
491 iov_len: data.len(),
492 iov_base: data.as_ptr() as *mut c_void,
493 };
494 mdbx_result(unsafe {
495 self.txn.txn_execute(|_| {
496 ffi::mdbx_cursor_put(self.cursor, &key_val, &mut data_val, flags.bits())
497 })?
498 })?;
499
500 Ok(())
501 }
502
503 pub fn del(&mut self, flags: WriteFlags) -> Result<()> {
510 mdbx_result(unsafe {
511 self.txn
512 .txn_execute(|_| ffi::mdbx_cursor_del(self.cursor, flags.bits()))?
513 })?;
514
515 Ok(())
516 }
517}
518
519impl<K> Clone for Cursor<K>
520where
521 K: TransactionKind,
522{
523 fn clone(&self) -> Self {
524 self.txn
525 .txn_execute(|_| Self::new_at_position(self).unwrap())
526 .unwrap()
527 }
528}
529
530impl<K> fmt::Debug for Cursor<K>
531where
532 K: TransactionKind,
533{
534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535 f.debug_struct("Cursor").finish_non_exhaustive()
536 }
537}
538
539impl<K> Drop for Cursor<K>
540where
541 K: TransactionKind,
542{
543 fn drop(&mut self) {
544 let _ = self
547 .txn
548 .txn_execute_renew_on_timeout(|_| unsafe { ffi::mdbx_cursor_close(self.cursor) });
549 }
550}
551
552const unsafe fn slice_to_val(slice: Option<&[u8]>) -> ffi::MDBX_val {
553 match slice {
554 Some(slice) => ffi::MDBX_val {
555 iov_len: slice.len(),
556 iov_base: slice.as_ptr() as *mut c_void,
557 },
558 None => ffi::MDBX_val {
559 iov_len: 0,
560 iov_base: ptr::null_mut(),
561 },
562 }
563}
564
565unsafe impl<K> Send for Cursor<K> where K: TransactionKind {}
566unsafe impl<K> Sync for Cursor<K> where K: TransactionKind {}
567
568#[derive(Debug)]
570pub enum IntoIter<'cur, K, Key, Value>
571where
572 K: TransactionKind,
573 Key: TableObject,
574 Value: TableObject,
575{
576 Err(Option<Error>),
582
583 Ok {
588 cursor: Cursor<K>,
590
591 op: ffi::MDBX_cursor_op,
593
594 next_op: ffi::MDBX_cursor_op,
596
597 _marker: PhantomData<(&'cur (), Key, Value)>,
598 },
599}
600
601impl<K, Key, Value> IntoIter<'_, K, Key, Value>
602where
603 K: TransactionKind,
604 Key: TableObject,
605 Value: TableObject,
606{
607 fn new(cursor: Cursor<K>, op: ffi::MDBX_cursor_op, next_op: ffi::MDBX_cursor_op) -> Self {
609 IntoIter::Ok {
610 cursor,
611 op,
612 next_op,
613 _marker: Default::default(),
614 }
615 }
616}
617
618impl<K, Key, Value> Iterator for IntoIter<'_, K, Key, Value>
619where
620 K: TransactionKind,
621 Key: TableObject,
622 Value: TableObject,
623{
624 type Item = Result<(Key, Value)>;
625
626 fn next(&mut self) -> Option<Self::Item> {
627 match self {
628 Self::Ok {
629 cursor,
630 op,
631 next_op,
632 ..
633 } => {
634 let mut key = ffi::MDBX_val {
635 iov_len: 0,
636 iov_base: ptr::null_mut(),
637 };
638 let mut data = ffi::MDBX_val {
639 iov_len: 0,
640 iov_base: ptr::null_mut(),
641 };
642 let op = mem::replace(op, *next_op);
643 unsafe {
644 let result = cursor.txn.txn_execute(|txn| {
645 match ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) {
646 ffi::MDBX_SUCCESS => {
647 let key = match Key::decode_val::<K>(txn, key) {
648 Ok(v) => v,
649 Err(e) => return Some(Err(e)),
650 };
651 let data = match Value::decode_val::<K>(txn, data) {
652 Ok(v) => v,
653 Err(e) => return Some(Err(e)),
654 };
655
656 Some(Ok((key, data)))
657 }
658 ffi::MDBX_NOTFOUND | ffi::MDBX_ENODATA => None,
662 error => Some(Err(Error::from_err_code(error))),
663 }
664 });
665 match result {
666 Ok(result) => result,
667 Err(err) => Some(Err(err)),
668 }
669 }
670 }
671 Self::Err(err) => err.take().map(Err),
672 }
673 }
674}
675
676#[derive(Debug)]
678pub enum Iter<'cur, K, Key, Value>
679where
680 K: TransactionKind,
681 Key: TableObject,
682 Value: TableObject,
683{
684 Err(Option<Error>),
690
691 Ok {
696 cursor: &'cur mut Cursor<K>,
698
699 op: ffi::MDBX_cursor_op,
701
702 next_op: ffi::MDBX_cursor_op,
704
705 _marker: PhantomData<fn(&'cur (), K, Key, Value)>,
706 },
707}
708
709impl<'cur, K, Key, Value> Iter<'cur, K, Key, Value>
710where
711 K: TransactionKind,
712 Key: TableObject,
713 Value: TableObject,
714{
715 fn new(
717 cursor: &'cur mut Cursor<K>,
718 op: ffi::MDBX_cursor_op,
719 next_op: ffi::MDBX_cursor_op,
720 ) -> Self {
721 Iter::Ok {
722 cursor,
723 op,
724 next_op,
725 _marker: Default::default(),
726 }
727 }
728}
729
730impl<K, Key, Value> Iterator for Iter<'_, K, Key, Value>
731where
732 K: TransactionKind,
733 Key: TableObject,
734 Value: TableObject,
735{
736 type Item = Result<(Key, Value)>;
737
738 fn next(&mut self) -> Option<Self::Item> {
739 match self {
740 Iter::Ok {
741 cursor,
742 op,
743 next_op,
744 ..
745 } => {
746 let mut key = ffi::MDBX_val {
747 iov_len: 0,
748 iov_base: ptr::null_mut(),
749 };
750 let mut data = ffi::MDBX_val {
751 iov_len: 0,
752 iov_base: ptr::null_mut(),
753 };
754 let op = mem::replace(op, *next_op);
755 unsafe {
756 let result = cursor.txn.txn_execute(|txn| {
757 match ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) {
758 ffi::MDBX_SUCCESS => {
759 let key = match Key::decode_val::<K>(txn, key) {
760 Ok(v) => v,
761 Err(e) => return Some(Err(e)),
762 };
763 let data = match Value::decode_val::<K>(txn, data) {
764 Ok(v) => v,
765 Err(e) => return Some(Err(e)),
766 };
767 Some(Ok((key, data)))
768 }
769 ffi::MDBX_NOTFOUND | ffi::MDBX_ENODATA => None,
773 error => Some(Err(Error::from_err_code(error))),
774 }
775 });
776 match result {
777 Ok(result) => result,
778 Err(err) => Some(Err(err)),
779 }
780 }
781 }
782 Iter::Err(err) => err.take().map(Err),
783 }
784 }
785}
786
787pub enum IterDup<'cur, K, Key, Value>
792where
793 K: TransactionKind,
794 Key: TableObject,
795 Value: TableObject,
796{
797 Err(Option<Error>),
803
804 Ok {
809 cursor: &'cur mut Cursor<K>,
811
812 op: MDBX_cursor_op,
814
815 _marker: PhantomData<fn(&'cur (Key, Value))>,
816 },
817}
818
819impl<'cur, K, Key, Value> IterDup<'cur, K, Key, Value>
820where
821 K: TransactionKind,
822 Key: TableObject,
823 Value: TableObject,
824{
825 fn new(cursor: &'cur mut Cursor<K>, op: MDBX_cursor_op) -> Self {
827 IterDup::Ok {
828 cursor,
829 op,
830 _marker: Default::default(),
831 }
832 }
833}
834
835impl<K, Key, Value> fmt::Debug for IterDup<'_, K, Key, Value>
836where
837 K: TransactionKind,
838 Key: TableObject,
839 Value: TableObject,
840{
841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
842 f.debug_struct("IterDup").finish()
843 }
844}
845
846impl<'cur, K, Key, Value> Iterator for IterDup<'cur, K, Key, Value>
847where
848 K: TransactionKind,
849 Key: TableObject,
850 Value: TableObject,
851{
852 type Item = IntoIter<'cur, K, Key, Value>;
853
854 fn next(&mut self) -> Option<Self::Item> {
855 match self {
856 IterDup::Ok { cursor, op, .. } => {
857 let mut key = ffi::MDBX_val {
858 iov_len: 0,
859 iov_base: ptr::null_mut(),
860 };
861 let mut data = ffi::MDBX_val {
862 iov_len: 0,
863 iov_base: ptr::null_mut(),
864 };
865 let op = mem::replace(op, ffi::MDBX_NEXT_NODUP);
866
867 let result = cursor.txn.txn_execute(|_| {
868 let err_code =
869 unsafe { ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) };
870
871 (err_code == ffi::MDBX_SUCCESS).then(|| {
872 IntoIter::new(
873 Cursor::new_at_position(&**cursor).unwrap(),
874 ffi::MDBX_GET_CURRENT,
875 ffi::MDBX_NEXT_DUP,
876 )
877 })
878 });
879
880 match result {
881 Ok(result) => result,
882 Err(err) => Some(IntoIter::Err(Some(err))),
883 }
884 }
885 IterDup::Err(err) => err.take().map(|e| IntoIter::Err(Some(e))),
886 }
887 }
888}
889
890pub enum IntoIterDup<'cur, K, Key, Value>
901where
902 K: TransactionKind,
903 Key: TableObject,
904 Value: TableObject,
905{
906 Err(Option<Error>),
912
913 Ok {
918 cursor: Cursor<K>,
920
921 op: MDBX_cursor_op,
923
924 _marker: PhantomData<fn(&'cur (Key, Value))>,
925 },
926}
927
928impl<'cur, K, Key, Value> IntoIterDup<'cur, K, Key, Value>
929where
930 K: TransactionKind,
931 Key: TableObject,
932 Value: TableObject,
933{
934 fn new(cursor: Cursor<K>, op: MDBX_cursor_op) -> Self {
936 IntoIterDup::Ok {
937 cursor: cursor,
938 op,
939 _marker: Default::default(),
940 }
941 }
942}
943
944impl<K, Key, Value> fmt::Debug for IntoIterDup<'_, K, Key, Value>
945where
946 K: TransactionKind,
947 Key: TableObject,
948 Value: TableObject,
949{
950 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
951 f.debug_struct("IterDup").finish()
952 }
953}
954
955impl<'cur, K, Key, Value> Iterator for IntoIterDup<'cur, K, Key, Value>
956where
957 K: TransactionKind,
958 Key: TableObject,
959 Value: TableObject,
960{
961 type Item = IntoIter<'cur, K, Key, Value>;
962
963 fn next(&mut self) -> Option<Self::Item> {
964 match self {
965 IntoIterDup::Ok { cursor, op, .. } => {
966 let mut key = ffi::MDBX_val {
967 iov_len: 0,
968 iov_base: ptr::null_mut(),
969 };
970 let mut data = ffi::MDBX_val {
971 iov_len: 0,
972 iov_base: ptr::null_mut(),
973 };
974 let op = mem::replace(op, ffi::MDBX_NEXT_NODUP);
975
976 let result = cursor.txn.txn_execute(|_| {
977 let err_code =
978 unsafe { ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) };
979
980 (err_code == ffi::MDBX_SUCCESS).then(|| {
981 IntoIter::new(
982 Cursor::new_at_position(&*cursor).unwrap(),
983 ffi::MDBX_GET_CURRENT,
984 ffi::MDBX_NEXT_DUP,
985 )
986 })
987 });
988
989 match result {
990 Ok(result) => result,
991 Err(err) => Some(IntoIter::Err(Some(err))),
992 }
993 }
994 IntoIterDup::Err(err) => err.take().map(|e| IntoIter::Err(Some(e))),
995 }
996 }
997}