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