heed/iterator/
iter.rs

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