Skip to main content

heed/iterator/
range.rs

1use std::borrow::Cow;
2use std::marker;
3use std::ops::Bound;
4
5use types::LazyDecode;
6
7use crate::cursor::MoveOperation;
8use crate::iteration_method::{IterationMethod, MoveBetweenKeys, MoveThroughDuplicateValues};
9use crate::*;
10
11fn move_on_range_end<'txn>(
12    cursor: &mut RoCursor<'txn>,
13    end_bound: &Bound<Vec<u8>>,
14) -> Result<Option<(&'txn [u8], &'txn [u8])>> {
15    match end_bound {
16        Bound::Included(end) => match cursor.move_on_key_greater_than_or_equal_to(end) {
17            Ok(Some((key, data))) if key == &end[..] => Ok(Some((key, data))),
18            Ok(_) => cursor.move_on_prev(MoveOperation::NoDup),
19            Err(e) => Err(e),
20        },
21        Bound::Excluded(end) => cursor
22            .move_on_key_greater_than_or_equal_to(end)
23            .and_then(|_| cursor.move_on_prev(MoveOperation::NoDup)),
24        Bound::Unbounded => cursor.move_on_last(MoveOperation::NoDup),
25    }
26}
27
28fn move_on_range_start<'txn>(
29    cursor: &mut RoCursor<'txn>,
30    start_bound: &mut Bound<Vec<u8>>,
31) -> Result<Option<(&'txn [u8], &'txn [u8])>> {
32    match start_bound {
33        Bound::Included(start) => cursor.move_on_key_greater_than_or_equal_to(start),
34        Bound::Excluded(start) => match cursor.move_on_key_greater_than_or_equal_to(start)? {
35            Some((key, _)) if key == start => cursor.move_on_next(MoveOperation::NoDup),
36            result => Ok(result),
37        },
38        Bound::Unbounded => cursor.move_on_first(MoveOperation::NoDup),
39    }
40}
41
42/// A read-only range iterator structure.
43pub struct RoRange<'txn, KC, DC, IM = MoveThroughDuplicateValues> {
44    cursor: RoCursor<'txn>,
45    move_on_start: bool,
46    start_bound: Bound<Vec<u8>>,
47    end_bound: Bound<Vec<u8>>,
48    _phantom: marker::PhantomData<(KC, DC, IM)>,
49}
50
51impl<'txn, KC, DC, IM> RoRange<'txn, KC, DC, IM> {
52    pub(crate) fn new(
53        cursor: RoCursor<'txn>,
54        start_bound: Bound<Vec<u8>>,
55        end_bound: Bound<Vec<u8>>,
56    ) -> RoRange<'txn, KC, DC, IM> {
57        RoRange {
58            cursor,
59            move_on_start: true,
60            start_bound,
61            end_bound,
62            _phantom: marker::PhantomData,
63        }
64    }
65
66    /// Move on the first value of keys, ignoring duplicate values.
67    ///
68    /// For more info, see [`RoIter::move_between_keys`].
69    pub fn move_between_keys(self) -> RoRange<'txn, KC, DC, MoveBetweenKeys> {
70        RoRange {
71            cursor: self.cursor,
72            move_on_start: self.move_on_start,
73            start_bound: self.start_bound,
74            end_bound: self.end_bound,
75            _phantom: marker::PhantomData,
76        }
77    }
78
79    /// Move through key/values entries and output duplicate values.
80    ///
81    /// For more info, see [`RoIter::move_through_duplicate_values`].
82    pub fn move_through_duplicate_values(
83        self,
84    ) -> RoRange<'txn, KC, DC, MoveThroughDuplicateValues> {
85        RoRange {
86            cursor: self.cursor,
87            move_on_start: self.move_on_start,
88            start_bound: self.start_bound,
89            end_bound: self.end_bound,
90            _phantom: marker::PhantomData,
91        }
92    }
93
94    /// Change the codec types of this iterator, specifying the codecs.
95    pub fn remap_types<KC2, DC2>(self) -> RoRange<'txn, KC2, DC2, IM> {
96        RoRange {
97            cursor: self.cursor,
98            move_on_start: self.move_on_start,
99            start_bound: self.start_bound,
100            end_bound: self.end_bound,
101            _phantom: marker::PhantomData,
102        }
103    }
104
105    /// Change the key codec type of this iterator, specifying the new codec.
106    pub fn remap_key_type<KC2>(self) -> RoRange<'txn, KC2, DC, IM> {
107        self.remap_types::<KC2, DC>()
108    }
109
110    /// Change the data codec type of this iterator, specifying the new codec.
111    pub fn remap_data_type<DC2>(self) -> RoRange<'txn, KC, DC2, IM> {
112        self.remap_types::<KC, DC2>()
113    }
114
115    /// Wrap the data bytes into a lazy decoder.
116    pub fn lazily_decode_data(self) -> RoRange<'txn, KC, LazyDecode<DC>, IM> {
117        self.remap_types::<KC, LazyDecode<DC>>()
118    }
119}
120
121impl<'txn, KC, DC, IM> Iterator for RoRange<'txn, KC, DC, IM>
122where
123    KC: BytesDecode<'txn>,
124    DC: BytesDecode<'txn>,
125    IM: IterationMethod,
126{
127    type Item = Result<(KC::DItem, DC::DItem)>;
128
129    fn next(&mut self) -> Option<Self::Item> {
130        let result = if self.move_on_start {
131            self.move_on_start = false;
132            move_on_range_start(&mut self.cursor, &mut self.start_bound)
133        } else {
134            self.cursor.move_on_next(IM::MOVE_OPERATION)
135        };
136
137        match result {
138            Ok(Some((key, data))) => {
139                let must_be_returned = match &self.end_bound {
140                    Bound::Included(end) => key <= end,
141                    Bound::Excluded(end) => key < end,
142                    Bound::Unbounded => true,
143                };
144
145                if must_be_returned {
146                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
147                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
148                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
149                    }
150                } else {
151                    None
152                }
153            }
154            Ok(None) => None,
155            Err(e) => Some(Err(e)),
156        }
157    }
158
159    fn last(mut self) -> Option<Self::Item> {
160        let result = if self.move_on_start {
161            move_on_range_end(&mut self.cursor, &self.end_bound)
162        } else {
163            match (
164                self.cursor.current(),
165                move_on_range_end(&mut self.cursor, &self.end_bound),
166            ) {
167                (Ok(Some((ckey, _))), Ok(Some((key, data)))) if ckey != key => {
168                    Ok(Some((key, data)))
169                }
170                (Ok(_), Ok(_)) => Ok(None),
171                (Err(e), _) | (_, Err(e)) => Err(e),
172            }
173        };
174
175        match result {
176            Ok(Some((key, data))) => {
177                let must_be_returned = match &self.start_bound {
178                    Bound::Included(start) => key >= start,
179                    Bound::Excluded(start) => key > start,
180                    Bound::Unbounded => true,
181                };
182
183                if must_be_returned {
184                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
185                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
186                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
187                    }
188                } else {
189                    None
190                }
191            }
192            Ok(None) => None,
193            Err(e) => Some(Err(e)),
194        }
195    }
196}
197
198impl<KC, DC, IM> fmt::Debug for RoRange<'_, KC, DC, IM> {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        f.debug_struct("RoRange").finish()
201    }
202}
203
204#[cfg(feature = "read-txn-no-tls")]
205unsafe impl<KC, DC, IM> Send for RoRange<'_, KC, DC, IM> {}
206
207/// A read-write range iterator structure.
208pub struct RwRange<'txn, KC, DC, IM = MoveThroughDuplicateValues> {
209    cursor: RwCursor<'txn>,
210    move_on_start: bool,
211    start_bound: Bound<Vec<u8>>,
212    end_bound: Bound<Vec<u8>>,
213    _phantom: marker::PhantomData<(KC, DC, IM)>,
214}
215
216impl<'txn, KC, DC, IM> RwRange<'txn, KC, DC, IM> {
217    pub(crate) fn new(
218        cursor: RwCursor<'txn>,
219        start_bound: Bound<Vec<u8>>,
220        end_bound: Bound<Vec<u8>>,
221    ) -> RwRange<'txn, KC, DC, IM> {
222        RwRange {
223            cursor,
224            move_on_start: true,
225            start_bound,
226            end_bound,
227            _phantom: marker::PhantomData,
228        }
229    }
230
231    /// Delete the entry the cursor is currently pointing to.
232    ///
233    /// Returns `true` if the entry was successfully deleted.
234    ///
235    /// # Safety
236    ///
237    /// It is _[undefined behavior]_ to keep a reference of a value from this database
238    /// while modifying it.
239    ///
240    /// > [Values returned from the database are valid only until a subsequent update operation,
241    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
242    ///
243    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
244    pub unsafe fn del_current(&mut self) -> Result<bool> {
245        self.cursor.del_current()
246    }
247
248    /// Write a new value to the current entry.
249    ///
250    /// The given key **must** be equal to the one this cursor is pointing otherwise the database
251    /// can be put into an inconsistent state.
252    ///
253    /// Returns `true` if the entry was successfully written.
254    ///
255    /// > This is intended to be used when the new data is the same size as the old.
256    /// > Otherwise it will simply perform a delete of the old record followed by an insert.
257    ///
258    /// # Safety
259    ///
260    /// It is _[undefined behavior]_ to keep a reference of a value from this database while
261    /// modifying it, so you can't use the key/value that comes from the cursor to feed
262    /// this function.
263    ///
264    /// In other words: Transform the key and value that you borrow from this database into an owned
265    /// version of them (e.g. `&str` into `String`).
266    ///
267    /// > [Values returned from the database are valid only until a subsequent update operation,
268    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
269    ///
270    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
271    pub unsafe fn put_current<'a>(
272        &mut self,
273        key: &'a KC::EItem,
274        data: &'a DC::EItem,
275    ) -> Result<bool>
276    where
277        KC: BytesEncode<'a>,
278        DC: BytesEncode<'a>,
279    {
280        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
281        let data_bytes: Cow<[u8]> = DC::bytes_encode(data).map_err(Error::Encoding)?;
282        self.cursor.put_current(&key_bytes, &data_bytes)
283    }
284
285    /// Write a new value to the current entry. The entry is written with the specified flags.
286    ///
287    /// The given key **must** be equal to the one this cursor is pointing otherwise the database
288    /// can be put into an inconsistent state.
289    ///
290    /// Returns `true` if the entry was successfully written.
291    ///
292    /// > This is intended to be used when the new data is the same size as the old.
293    /// > Otherwise it will simply perform a delete of the old record followed by an insert.
294    ///
295    /// # Safety
296    ///
297    /// Please read the safety notes of the [`RwRange::put_current`] method.
298    pub unsafe fn put_current_reserved_with_flags<'a, F>(
299        &mut self,
300        flags: PutFlags,
301        key: &'a KC::EItem,
302        data_size: usize,
303        write_func: F,
304    ) -> Result<bool>
305    where
306        KC: BytesEncode<'a>,
307        F: FnOnce(&mut ReservedSpace) -> io::Result<()>,
308    {
309        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
310        self.cursor
311            .put_current_reserved_with_flags(flags, &key_bytes, data_size, write_func)
312    }
313
314    /// Insert a key-value pair in this database. The entry is written with the specified flags and data codec.
315    ///
316    /// For more info, see [`RwIter::put_current_with_options`].
317    ///
318    /// # Safety
319    ///
320    /// It is _[undefined behavior]_ to keep a reference of a value from this database while
321    /// modifying it, so you can't use the key/value that comes from the cursor to feed
322    /// this function.
323    ///
324    /// In other words: Transform the key and value that you borrow from this database into an owned
325    /// version of them (e.g. `&str` into `String`).
326    ///
327    /// > [Values returned from the database are valid only until a subsequent update operation,
328    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
329    ///
330    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
331    pub unsafe fn put_current_with_options<'a, NDC>(
332        &mut self,
333        flags: PutFlags,
334        key: &'a KC::EItem,
335        data: &'a NDC::EItem,
336    ) -> Result<()>
337    where
338        KC: BytesEncode<'a>,
339        NDC: BytesEncode<'a>,
340    {
341        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
342        let data_bytes: Cow<[u8]> = NDC::bytes_encode(data).map_err(Error::Encoding)?;
343        self.cursor
344            .put_current_with_flags(flags, &key_bytes, &data_bytes)
345    }
346
347    /// Move on the first value of keys, ignoring duplicate values.
348    ///
349    /// For more info, see [`RoIter::move_between_keys`].
350    pub fn move_between_keys(self) -> RwRange<'txn, KC, DC, MoveBetweenKeys> {
351        RwRange {
352            cursor: self.cursor,
353            move_on_start: self.move_on_start,
354            start_bound: self.start_bound,
355            end_bound: self.end_bound,
356            _phantom: marker::PhantomData,
357        }
358    }
359
360    /// Move through key/values entries and output duplicate values.
361    ///
362    /// For more info, see [`RoIter::move_through_duplicate_values`].
363    pub fn move_through_duplicate_values(
364        self,
365    ) -> RwRange<'txn, KC, DC, MoveThroughDuplicateValues> {
366        RwRange {
367            cursor: self.cursor,
368            move_on_start: self.move_on_start,
369            start_bound: self.start_bound,
370            end_bound: self.end_bound,
371            _phantom: marker::PhantomData,
372        }
373    }
374
375    /// Change the codec types of this iterator, specifying the codecs.
376    pub fn remap_types<KC2, DC2>(self) -> RwRange<'txn, KC2, DC2, IM> {
377        RwRange {
378            cursor: self.cursor,
379            move_on_start: self.move_on_start,
380            start_bound: self.start_bound,
381            end_bound: self.end_bound,
382            _phantom: marker::PhantomData,
383        }
384    }
385
386    /// Change the key codec type of this iterator, specifying the new codec.
387    pub fn remap_key_type<KC2>(self) -> RwRange<'txn, KC2, DC, IM> {
388        self.remap_types::<KC2, DC>()
389    }
390
391    /// Change the data codec type of this iterator, specifying the new codec.
392    pub fn remap_data_type<DC2>(self) -> RwRange<'txn, KC, DC2, IM> {
393        self.remap_types::<KC, DC2>()
394    }
395
396    /// Wrap the data bytes into a lazy decoder.
397    pub fn lazily_decode_data(self) -> RwRange<'txn, KC, LazyDecode<DC>, IM> {
398        self.remap_types::<KC, LazyDecode<DC>>()
399    }
400}
401
402impl<'txn, KC, DC, IM> Iterator for RwRange<'txn, KC, DC, IM>
403where
404    KC: BytesDecode<'txn>,
405    DC: BytesDecode<'txn>,
406    IM: IterationMethod,
407{
408    type Item = Result<(KC::DItem, DC::DItem)>;
409
410    fn next(&mut self) -> Option<Self::Item> {
411        let result = if self.move_on_start {
412            self.move_on_start = false;
413            move_on_range_start(&mut self.cursor, &mut self.start_bound)
414        } else {
415            self.cursor.move_on_next(IM::MOVE_OPERATION)
416        };
417
418        match result {
419            Ok(Some((key, data))) => {
420                let must_be_returned = match self.end_bound {
421                    Bound::Included(ref end) => key <= end,
422                    Bound::Excluded(ref end) => key < end,
423                    Bound::Unbounded => true,
424                };
425
426                if must_be_returned {
427                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
428                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
429                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
430                    }
431                } else {
432                    None
433                }
434            }
435            Ok(None) => None,
436            Err(e) => Some(Err(e)),
437        }
438    }
439
440    fn last(mut self) -> Option<Self::Item> {
441        let result = if self.move_on_start {
442            move_on_range_end(&mut self.cursor, &self.end_bound)
443        } else {
444            match (
445                self.cursor.current(),
446                move_on_range_end(&mut self.cursor, &self.end_bound),
447            ) {
448                (Ok(Some((ckey, _))), Ok(Some((key, data)))) if ckey != key => {
449                    Ok(Some((key, data)))
450                }
451                (Ok(_), Ok(_)) => Ok(None),
452                (Err(e), _) | (_, Err(e)) => Err(e),
453            }
454        };
455
456        match result {
457            Ok(Some((key, data))) => {
458                let must_be_returned = match &self.start_bound {
459                    Bound::Included(start) => key >= start,
460                    Bound::Excluded(start) => key > start,
461                    Bound::Unbounded => true,
462                };
463
464                if must_be_returned {
465                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
466                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
467                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
468                    }
469                } else {
470                    None
471                }
472            }
473            Ok(None) => None,
474            Err(e) => Some(Err(e)),
475        }
476    }
477}
478
479impl<KC, DC, IM> fmt::Debug for RwRange<'_, KC, DC, IM> {
480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481        f.debug_struct("RwRange").finish()
482    }
483}
484
485/// A reverse read-only range iterator structure.
486pub struct RoRevRange<'txn, KC, DC, IM = MoveThroughDuplicateValues> {
487    cursor: RoCursor<'txn>,
488    move_on_end: bool,
489    start_bound: Bound<Vec<u8>>,
490    end_bound: Bound<Vec<u8>>,
491    _phantom: marker::PhantomData<(KC, DC, IM)>,
492}
493
494impl<'txn, KC, DC, IM> RoRevRange<'txn, KC, DC, IM> {
495    pub(crate) fn new(
496        cursor: RoCursor<'txn>,
497        start_bound: Bound<Vec<u8>>,
498        end_bound: Bound<Vec<u8>>,
499    ) -> RoRevRange<'txn, KC, DC, IM> {
500        RoRevRange {
501            cursor,
502            move_on_end: true,
503            start_bound,
504            end_bound,
505            _phantom: marker::PhantomData,
506        }
507    }
508
509    /// Move on the first value of keys, ignoring duplicate values.
510    ///
511    /// For more info, see [`RoIter::move_between_keys`].
512    pub fn move_between_keys(self) -> RoRevRange<'txn, KC, DC, MoveBetweenKeys> {
513        RoRevRange {
514            cursor: self.cursor,
515            move_on_end: self.move_on_end,
516            start_bound: self.start_bound,
517            end_bound: self.end_bound,
518            _phantom: marker::PhantomData,
519        }
520    }
521
522    /// Move through key/values entries and output duplicate values.
523    ///
524    /// For more info, see [`RoIter::move_through_duplicate_values`].
525    pub fn move_through_duplicate_values(
526        self,
527    ) -> RoRevRange<'txn, KC, DC, MoveThroughDuplicateValues> {
528        RoRevRange {
529            cursor: self.cursor,
530            move_on_end: self.move_on_end,
531            start_bound: self.start_bound,
532            end_bound: self.end_bound,
533            _phantom: marker::PhantomData,
534        }
535    }
536
537    /// Change the codec types of this iterator, specifying the codecs.
538    pub fn remap_types<KC2, DC2>(self) -> RoRevRange<'txn, KC2, DC2, IM> {
539        RoRevRange {
540            cursor: self.cursor,
541            move_on_end: self.move_on_end,
542            start_bound: self.start_bound,
543            end_bound: self.end_bound,
544            _phantom: marker::PhantomData,
545        }
546    }
547
548    /// Change the key codec type of this iterator, specifying the new codec.
549    pub fn remap_key_type<KC2>(self) -> RoRevRange<'txn, KC2, DC, IM> {
550        self.remap_types::<KC2, DC>()
551    }
552
553    /// Change the data codec type of this iterator, specifying the new codec.
554    pub fn remap_data_type<DC2>(self) -> RoRevRange<'txn, KC, DC2, IM> {
555        self.remap_types::<KC, DC2>()
556    }
557
558    /// Wrap the data bytes into a lazy decoder.
559    pub fn lazily_decode_data(self) -> RoRevRange<'txn, KC, LazyDecode<DC>, IM> {
560        self.remap_types::<KC, LazyDecode<DC>>()
561    }
562}
563
564impl<'txn, KC, DC, IM> Iterator for RoRevRange<'txn, KC, DC, IM>
565where
566    KC: BytesDecode<'txn>,
567    DC: BytesDecode<'txn>,
568    IM: IterationMethod,
569{
570    type Item = Result<(KC::DItem, DC::DItem)>;
571
572    fn next(&mut self) -> Option<Self::Item> {
573        let result = if self.move_on_end {
574            self.move_on_end = false;
575            move_on_range_end(&mut self.cursor, &self.end_bound)
576        } else {
577            self.cursor.move_on_prev(IM::MOVE_OPERATION)
578        };
579
580        match result {
581            Ok(Some((key, data))) => {
582                let must_be_returned = match &self.start_bound {
583                    Bound::Included(start) => key >= start,
584                    Bound::Excluded(start) => key > start,
585                    Bound::Unbounded => true,
586                };
587
588                if must_be_returned {
589                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
590                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
591                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
592                    }
593                } else {
594                    None
595                }
596            }
597            Ok(None) => None,
598            Err(e) => Some(Err(e)),
599        }
600    }
601
602    fn last(mut self) -> Option<Self::Item> {
603        let result = if self.move_on_end {
604            move_on_range_start(&mut self.cursor, &mut self.start_bound)
605        } else {
606            let current = self.cursor.current();
607            let start = move_on_range_start(&mut self.cursor, &mut self.start_bound);
608            match (current, start) {
609                (Ok(Some((ckey, _))), Ok(Some((key, data)))) if ckey != key => {
610                    Ok(Some((key, data)))
611                }
612                (Ok(_), Ok(_)) => Ok(None),
613                (Err(e), _) | (_, Err(e)) => Err(e),
614            }
615        };
616
617        match result {
618            Ok(Some((key, data))) => {
619                let must_be_returned = match &self.end_bound {
620                    Bound::Included(end) => key <= end,
621                    Bound::Excluded(end) => key < end,
622                    Bound::Unbounded => true,
623                };
624
625                if must_be_returned {
626                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
627                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
628                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
629                    }
630                } else {
631                    None
632                }
633            }
634            Ok(None) => None,
635            Err(e) => Some(Err(e)),
636        }
637    }
638}
639
640impl<KC, DC, IM> fmt::Debug for RoRevRange<'_, KC, DC, IM> {
641    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642        f.debug_struct("RoRevRange").finish()
643    }
644}
645
646#[cfg(feature = "read-txn-no-tls")]
647unsafe impl<KC, DC, IM> Send for RoRevRange<'_, KC, DC, IM> {}
648
649/// A reverse read-write range iterator structure.
650pub struct RwRevRange<'txn, KC, DC, IM = MoveThroughDuplicateValues> {
651    cursor: RwCursor<'txn>,
652    move_on_end: bool,
653    start_bound: Bound<Vec<u8>>,
654    end_bound: Bound<Vec<u8>>,
655    _phantom: marker::PhantomData<(KC, DC, IM)>,
656}
657
658impl<'txn, KC, DC, IM> RwRevRange<'txn, KC, DC, IM> {
659    pub(crate) fn new(
660        cursor: RwCursor<'txn>,
661        start_bound: Bound<Vec<u8>>,
662        end_bound: Bound<Vec<u8>>,
663    ) -> RwRevRange<'txn, KC, DC, IM> {
664        RwRevRange {
665            cursor,
666            move_on_end: true,
667            start_bound,
668            end_bound,
669            _phantom: marker::PhantomData,
670        }
671    }
672
673    /// Delete the entry the cursor is currently pointing to.
674    ///
675    /// Returns `true` if the entry was successfully deleted.
676    ///
677    /// # Safety
678    ///
679    /// It is _[undefined behavior]_ to keep a reference of a value from this database
680    /// while modifying it.
681    ///
682    /// > [Values returned from the database are valid only until a subsequent update operation,
683    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
684    ///
685    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
686    pub unsafe fn del_current(&mut self) -> Result<bool> {
687        self.cursor.del_current()
688    }
689
690    /// Write a new value to the current entry.
691    ///
692    /// The given key **must** be equal to the one this cursor is pointing otherwise the database
693    /// can be put into an inconsistent state.
694    ///
695    /// Returns `true` if the entry was successfully written.
696    ///
697    /// > This is intended to be used when the new data is the same size as the old.
698    /// > Otherwise it will simply perform a delete of the old record followed by an insert.
699    ///
700    /// # Safety
701    ///
702    /// It is _[undefined behavior]_ to keep a reference of a value from this database while
703    /// modifying it, so you can't use the key/value that comes from the cursor to feed
704    /// this function.
705    ///
706    /// In other words: Transform the key and value that you borrow from this database into an owned
707    /// version of them (e.g. `&str` into `String`).
708    ///
709    /// > [Values returned from the database are valid only until a subsequent update operation,
710    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
711    ///
712    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
713    pub unsafe fn put_current<'a>(
714        &mut self,
715        key: &'a KC::EItem,
716        data: &'a DC::EItem,
717    ) -> Result<bool>
718    where
719        KC: BytesEncode<'a>,
720        DC: BytesEncode<'a>,
721    {
722        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
723        let data_bytes: Cow<[u8]> = DC::bytes_encode(data).map_err(Error::Encoding)?;
724        self.cursor.put_current(&key_bytes, &data_bytes)
725    }
726
727    /// Write a new value to the current entry. The entry is written with the specified flags.
728    ///
729    /// The given key **must** be equal to the one this cursor is pointing otherwise the database
730    /// can be put into an inconsistent state.
731    ///
732    /// Returns `true` if the entry was successfully written.
733    ///
734    /// > This is intended to be used when the new data is the same size as the old.
735    /// > Otherwise it will simply perform a delete of the old record followed by an insert.
736    ///
737    /// # Safety
738    ///
739    /// Please read the safety notes of the [`RwRevRange::put_current`] method.
740    pub unsafe fn put_current_reserved_with_flags<'a, F>(
741        &mut self,
742        flags: PutFlags,
743        key: &'a KC::EItem,
744        data_size: usize,
745        write_func: F,
746    ) -> Result<bool>
747    where
748        KC: BytesEncode<'a>,
749        F: FnOnce(&mut ReservedSpace) -> io::Result<()>,
750    {
751        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
752        self.cursor
753            .put_current_reserved_with_flags(flags, &key_bytes, data_size, write_func)
754    }
755
756    /// Insert a key-value pair in this database. The entry is written with the specified flags and data codec.
757    ///
758    /// For more info, see [`RwIter::put_current_with_options`].
759    ///
760    /// # Safety
761    ///
762    /// It is _[undefined behavior]_ to keep a reference of a value from this database while
763    /// modifying it, so you can't use the key/value that comes from the cursor to feed
764    /// this function.
765    ///
766    /// In other words: Transform the key and value that you borrow from this database into an owned
767    /// version of them (e.g. `&str` into `String`).
768    ///
769    /// > [Values returned from the database are valid only until a subsequent update operation,
770    /// > or the end of the transaction.](http://www.lmdb.tech/doc/group__mdb.html#structMDB__val)
771    ///
772    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
773    pub unsafe fn put_current_with_options<'a, NDC>(
774        &mut self,
775        flags: PutFlags,
776        key: &'a KC::EItem,
777        data: &'a NDC::EItem,
778    ) -> Result<()>
779    where
780        KC: BytesEncode<'a>,
781        NDC: BytesEncode<'a>,
782    {
783        let key_bytes: Cow<[u8]> = KC::bytes_encode(key).map_err(Error::Encoding)?;
784        let data_bytes: Cow<[u8]> = NDC::bytes_encode(data).map_err(Error::Encoding)?;
785        self.cursor
786            .put_current_with_flags(flags, &key_bytes, &data_bytes)
787    }
788
789    /// Move on the first value of keys, ignoring duplicate values.
790    ///
791    /// For more info, see [`RoIter::move_between_keys`].
792    pub fn move_between_keys(self) -> RwRevRange<'txn, KC, DC, MoveBetweenKeys> {
793        RwRevRange {
794            cursor: self.cursor,
795            move_on_end: self.move_on_end,
796            start_bound: self.start_bound,
797            end_bound: self.end_bound,
798            _phantom: marker::PhantomData,
799        }
800    }
801
802    /// Move through key/values entries and output duplicate values.
803    ///
804    /// For more info, see [`RoIter::move_through_duplicate_values`].
805    pub fn move_through_duplicate_values(
806        self,
807    ) -> RwRevRange<'txn, KC, DC, MoveThroughDuplicateValues> {
808        RwRevRange {
809            cursor: self.cursor,
810            move_on_end: self.move_on_end,
811            start_bound: self.start_bound,
812            end_bound: self.end_bound,
813            _phantom: marker::PhantomData,
814        }
815    }
816
817    /// Change the codec types of this iterator, specifying the codecs.
818    pub fn remap_types<KC2, DC2>(self) -> RwRevRange<'txn, KC2, DC2, IM> {
819        RwRevRange {
820            cursor: self.cursor,
821            move_on_end: self.move_on_end,
822            start_bound: self.start_bound,
823            end_bound: self.end_bound,
824            _phantom: marker::PhantomData,
825        }
826    }
827
828    /// Change the key codec type of this iterator, specifying the new codec.
829    pub fn remap_key_type<KC2>(self) -> RwRevRange<'txn, KC2, DC, IM> {
830        self.remap_types::<KC2, DC>()
831    }
832
833    /// Change the data codec type of this iterator, specifying the new codec.
834    pub fn remap_data_type<DC2>(self) -> RwRevRange<'txn, KC, DC2, IM> {
835        self.remap_types::<KC, DC2>()
836    }
837
838    /// Wrap the data bytes into a lazy decoder.
839    pub fn lazily_decode_data(self) -> RwRevRange<'txn, KC, LazyDecode<DC>, IM> {
840        self.remap_types::<KC, LazyDecode<DC>>()
841    }
842}
843
844impl<'txn, KC, DC, IM> Iterator for RwRevRange<'txn, KC, DC, IM>
845where
846    KC: BytesDecode<'txn>,
847    DC: BytesDecode<'txn>,
848    IM: IterationMethod,
849{
850    type Item = Result<(KC::DItem, DC::DItem)>;
851
852    fn next(&mut self) -> Option<Self::Item> {
853        let result = if self.move_on_end {
854            self.move_on_end = false;
855            move_on_range_end(&mut self.cursor, &self.end_bound)
856        } else {
857            self.cursor.move_on_prev(IM::MOVE_OPERATION)
858        };
859
860        match result {
861            Ok(Some((key, data))) => {
862                let must_be_returned = match &self.start_bound {
863                    Bound::Included(start) => key >= start,
864                    Bound::Excluded(start) => key > start,
865                    Bound::Unbounded => true,
866                };
867
868                if must_be_returned {
869                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
870                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
871                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
872                    }
873                } else {
874                    None
875                }
876            }
877            Ok(None) => None,
878            Err(e) => Some(Err(e)),
879        }
880    }
881
882    fn last(mut self) -> Option<Self::Item> {
883        let result = if self.move_on_end {
884            move_on_range_start(&mut self.cursor, &mut self.start_bound)
885        } else {
886            let current = self.cursor.current();
887            let start = move_on_range_start(&mut self.cursor, &mut self.start_bound);
888            match (current, start) {
889                (Ok(Some((ckey, _))), Ok(Some((key, data)))) if ckey != key => {
890                    Ok(Some((key, data)))
891                }
892                (Ok(_), Ok(_)) => Ok(None),
893                (Err(e), _) | (_, Err(e)) => Err(e),
894            }
895        };
896
897        match result {
898            Ok(Some((key, data))) => {
899                let must_be_returned = match &self.end_bound {
900                    Bound::Included(end) => key <= end,
901                    Bound::Excluded(end) => key < end,
902                    Bound::Unbounded => true,
903                };
904
905                if must_be_returned {
906                    match (KC::bytes_decode(key), DC::bytes_decode(data)) {
907                        (Ok(key), Ok(data)) => Some(Ok((key, data))),
908                        (Err(e), _) | (_, Err(e)) => Some(Err(Error::Decoding(e))),
909                    }
910                } else {
911                    None
912                }
913            }
914            Ok(None) => None,
915            Err(e) => Some(Err(e)),
916        }
917    }
918}
919
920impl<KC, DC, IM> fmt::Debug for RwRevRange<'_, KC, DC, IM> {
921    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
922        f.debug_struct("RwRevRange").finish()
923    }
924}