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