Skip to main content

heed/iterator/
prefix.rs

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