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