libmdbx_remote/
cursor.rs

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
16/// A cursor for navigating the items within a database.
17pub 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    /// Returns a raw pointer to the underlying MDBX cursor.
57    ///
58    /// The caller **must** ensure that the pointer is not used after the
59    /// lifetime of the cursor.
60    pub const fn cursor(&self) -> *mut ffi::MDBX_cursor {
61        self.cursor
62    }
63
64    /// Returns an iterator over the raw key value slices.
65    #[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    /// Returns an iterator over database items.
71    #[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    /// Retrieves a key/data pair from the cursor. Depending on the cursor op,
81    /// the current key may be returned.
82    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                    // MDBX wrote in new key
107                    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    /// Position at first key/data item.
149    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    /// [`DatabaseFlags::DUP_SORT`]-only: Position at first data item of current key.
158    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    /// [`DatabaseFlags::DUP_SORT`]-only: Position at key/data pair.
166    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    /// [`DatabaseFlags::DUP_SORT`]-only: Position at given key and at first data greater than or
174    /// equal to specified data.
175    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    /// Return key/data at current cursor position.
183    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    /// DupFixed-only: Return up to a page of duplicate data items from current cursor position.
192    /// Move cursor to prepare for [`Self::next_multiple()`].
193    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    /// Position at last key/data item.
201    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    /// DupSort-only: Position at last data item of current key.
210    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    /// Position at next data item
218    #[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    /// [`DatabaseFlags::DUP_SORT`]-only: Position at next data item of current key.
228    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    /// [`DatabaseFlags::DUP_FIXED`]-only: Return up to a page of duplicate data items from next
237    /// cursor position. Move cursor to prepare for `MDBX_NEXT_MULTIPLE`.
238    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    /// Position at first data item of next key.
247    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    /// Position at previous data item.
256    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    /// [`DatabaseFlags::DUP_SORT`]-only: Position at previous data item of current key.
265    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    /// Position at last data item of previous key.
274    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    /// Position at specified key.
283    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    /// Position at specified key, return both key and data.
291    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    /// Position at first key greater than or equal to specified key.
300    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    /// [`DatabaseFlags::DUP_FIXED`]-only: Position at previous page and return up to a page of
309    /// duplicate data items.
310    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    /// Position at first key-value pair greater than or equal to specified, return both key and
319    /// data, and the return code depends on a exact match.
320    ///
321    /// For non DupSort-ed collections this works the same as [`Self::set_range()`], but returns
322    /// [false] if key found exactly and [true] if greater key was found.
323    ///
324    /// For DupSort-ed a data value is taken into account for duplicates, i.e. for a pairs/tuples of
325    /// a key and an each data value of duplicates. Returns [false] if key-value pair found
326    /// exactly and [true] if the next pair was returned.
327    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    /// Returns an iterator over database items.
338    ///
339    /// The iterator will begin with item next after the cursor, and continue until the end of the
340    /// database. For new cursors, the iterator will begin with the first item in the database.
341    ///
342    /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), the
343    /// duplicate data items of each key will be returned before moving on to
344    /// the next key.
345    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    /// Iterate over database items starting from the beginning of the database.
354    ///
355    /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), the
356    /// duplicate data items of each key will be returned before moving on to
357    /// the next key.
358    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    /// Iterate over database items starting from the given key.
367    ///
368    /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), the
369    /// duplicate data items of each key will be returned before moving on to
370    /// the next key.
371    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    /// Iterate over duplicate database items. The iterator will begin with the
384    /// item next after the cursor, and continue until the end of the database.
385    /// Each item will be returned as an iterator of its duplicates.
386    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    /// Iterate over duplicate database items starting from the beginning of the
403    /// database. Each item will be returned as an iterator of its duplicates.
404    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    /// Iterate over duplicate items in the database starting from the given
421    /// key. Each item will be returned as an iterator of its duplicates.
422    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    /// Iterate over the duplicates of the item in the database with the given key.
447    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    /// Puts a key/data pair into the database. The cursor will be positioned at
484    /// the new data item, or on failure usually near it.
485    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    /// Deletes the current key/data pair.
504    ///
505    /// ### Flags
506    ///
507    /// [`WriteFlags::NO_DUP_DATA`] may be used to delete all data items for the
508    /// current key, if the database was opened with [`DatabaseFlags::DUP_SORT`].
509    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        // To be able to close a cursor of a timed out transaction, we need to renew it first.
545        // Hence the usage of `txn_execute_renew_on_timeout` here.
546        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/// An iterator over the key/value pairs in an MDBX database.
569#[derive(Debug)]
570pub enum IntoIter<'cur, K, Key, Value>
571where
572    K: TransactionKind,
573    Key: TableObject,
574    Value: TableObject,
575{
576    /// An iterator that returns an error on every call to [`Iter::next()`].
577    /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
578    /// on retrieval of a cursor.  Using this variant instead of returning
579    /// an error makes `Cursor.iter()`* methods infallible, so consumers only
580    /// need to check the result of `Iter.next()`.
581    Err(Option<Error>),
582
583    /// An iterator that returns an Item on calls to [`Iter::next()`].
584    /// The Item is a [Result], so this variant
585    /// might still return an error, if retrieval of the key/value pair
586    /// fails for some reason.
587    Ok {
588        /// The MDBX cursor with which to iterate.
589        cursor: Cursor<K>,
590
591        /// The first operation to perform when the consumer calls [`Iter::next()`].
592        op: ffi::MDBX_cursor_op,
593
594        /// The next and subsequent operations to perform.
595        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    /// Creates a new iterator backed by the given cursor.
608    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                            // MDBX_ENODATA can occur when the cursor was previously sought to a
659                            // non-existent value, e.g. iter_from with a
660                            // key greater than all values in the database.
661                            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/// An iterator over the key/value pairs in an MDBX database.
677#[derive(Debug)]
678pub enum Iter<'cur, K, Key, Value>
679where
680    K: TransactionKind,
681    Key: TableObject,
682    Value: TableObject,
683{
684    /// An iterator that returns an error on every call to [`Iter::next()`].
685    /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
686    /// on retrieval of a cursor.  Using this variant instead of returning
687    /// an error makes `Cursor.iter()`* methods infallible, so consumers only
688    /// need to check the result of `Iter.next()`.
689    Err(Option<Error>),
690
691    /// An iterator that returns an Item on calls to [`Iter::next()`].
692    /// The Item is a [Result], so this variant
693    /// might still return an error, if retrieval of the key/value pair
694    /// fails for some reason.
695    Ok {
696        /// The MDBX cursor with which to iterate.
697        cursor: &'cur mut Cursor<K>,
698
699        /// The first operation to perform when the consumer calls [`Iter::next()`].
700        op: ffi::MDBX_cursor_op,
701
702        /// The next and subsequent operations to perform.
703        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    /// Creates a new iterator backed by the given cursor.
716    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                            // MDBX_NODATA can occur when the cursor was previously sought to a
770                            // non-existent value, e.g. iter_from with a
771                            // key greater than all values in the database.
772                            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
787/// An iterator over the keys and duplicate values in an MDBX database.
788///
789/// The yielded items of the iterator are themselves iterators over the duplicate values for a
790/// specific key.
791pub enum IterDup<'cur, K, Key, Value>
792where
793    K: TransactionKind,
794    Key: TableObject,
795    Value: TableObject,
796{
797    /// An iterator that returns an error on every call to `Iter.next()`.
798    /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
799    /// on retrieval of a cursor.  Using this variant instead of returning
800    /// an error makes `Cursor.iter()`* methods infallible, so consumers only
801    /// need to check the result of `Iter.next()`.
802    Err(Option<Error>),
803
804    /// An iterator that returns an Item on calls to `Iter.next()`.
805    /// The Item is a Result<(&'txn [u8], &'txn [u8])>, so this variant
806    /// might still return an error, if retrieval of the key/value pair
807    /// fails for some reason.
808    Ok {
809        /// The MDBX cursor with which to iterate.
810        cursor: &'cur mut Cursor<K>,
811
812        /// The first operation to perform when the consumer calls `Iter.next()`.
813        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    /// Creates a new iterator backed by the given cursor.
826    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
890/// An iterator over the keys and duplicate values in an MDBX database.
891///
892/// The yielded items of the iterator are themselves iterators over the duplicate values for a
893/// specific key.
894///
895/// Note:
896/// This difference has totally diference variance in 'cur compared to IterDup. Since we no longer
897/// hold a reference, the 'cur is contravariant here and thus IntoIterDup<'cur> shall live shorter
898/// than 'cur. Reference: https://doc.rust-lang.org/reference/subtyping.html#variance
899/// Sidenote: IterDup<'cur> shall have invariance in 'cur
900pub enum IntoIterDup<'cur, K, Key, Value>
901where
902    K: TransactionKind,
903    Key: TableObject,
904    Value: TableObject,
905{
906    /// An iterator that returns an error on every call to `Iter.next()`.
907    /// Cursor.iter*() creates an Iter of this type when MDBX returns an error
908    /// on retrieval of a cursor.  Using this variant instead of returning
909    /// an error makes `Cursor.iter()`* methods infallible, so consumers only
910    /// need to check the result of `Iter.next()`.
911    Err(Option<Error>),
912
913    /// An iterator that returns an Item on calls to `Iter.next()`.
914    /// The Item is a Result<(&'txn [u8], &'txn [u8])>, so this variant
915    /// might still return an error, if retrieval of the key/value pair
916    /// fails for some reason.
917    Ok {
918        /// The MDBX cursor with which to iterate.
919        cursor: Cursor<K>,
920
921        /// The first operation to perform when the consumer calls `Iter.next()`.
922        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    /// Creates a new iterator backed by the given cursor.
935    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}