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