leveldb/database/iterator.rs
1//! LevelDB iterators
2//!
3//! Iteration is one of the most important parts of LevelDB. This module provides
4//! Iterators to iterate over key, values and pairs of both.
5//!
6//! Use the `Iterable` trait methods to create iterator instances. For convenience,
7//! various Iterator type aliases are provided.
8//!
9//! Furthermore, policies can be used to control iteration behavior:
10//!
11//! ```ignore
12//! // Basic iterator with default policy
13//! let iter: KeyIterator<'_> = database.iter(ReadOptions::new());
14//!
15//! // Iterator with custom policy
16//! let policy = BoundedKeyPolicy::new(Some(start_key), Some(end_key));
17//! let bounded_iter: EntryIterator<'_, _> = database.iter_with_policy(ReadOptions::new(), policy);
18//! ```
19use super::Database;
20use super::error::Error;
21use super::options::{ReadOptions, c_readoptions};
22use super::slice::Slice;
23use crate::binding::{
24 leveldb_create_iterator, leveldb_iter_destroy, leveldb_iter_get_error, leveldb_iter_key,
25 leveldb_iter_next, leveldb_iter_prev, leveldb_iter_seek, leveldb_iter_seek_to_first,
26 leveldb_iter_seek_to_last, leveldb_iter_valid, leveldb_iter_value, leveldb_iterator_t,
27 leveldb_readoptions_destroy,
28};
29use libc::{c_char, size_t};
30use std::iter;
31use std::marker::PhantomData;
32
33#[allow(missing_docs)]
34struct RawIterator {
35 ptr: *mut leveldb_iterator_t,
36}
37
38#[allow(missing_docs)]
39impl Drop for RawIterator {
40 fn drop(&mut self) {
41 unsafe { leveldb_iter_destroy(self.ptr) }
42 }
43}
44
45/// Marker types of iterators return key only
46pub struct KeyType;
47/// Marker types of iterators return value only
48pub struct ValueType;
49/// Marker types of iterators return key & value pair
50pub struct EntryType;
51
52/// Marker types for iterating direction: front to back through block data
53pub struct Forward;
54/// Marker types for iterating direction: back to front through block data
55pub struct Backward;
56
57/// Trait for providing context for policy to make decisions
58pub trait Context<'a> {
59 /// Get the current key as a slice that borrows from the iterator
60 ///
61 /// # Safety
62 ///
63 /// ## Iterator Validity Requirement
64 /// Use `valid()` to check iterator state before calling this method.
65 ///
66 /// ## Lifetime Safety
67 /// The returned slice borrows data directly from the LevelDB iterator without copying.
68 /// The data is only valid until the iterator is advanced to the next position or destroyed.
69 ///
70 /// The caller must ensure that the returned slice does not outlive the iterator
71 /// or any operation that would advance the iterator (such as calling `next()`, `seek()`, etc.).
72 /// To keep the data longer, the slice should be cloned.
73 ///
74 /// ## Performance
75 /// This method provides zero-copy access to LevelDB data for maximum performance.
76 /// Get the current key as a slice
77 unsafe fn key(&self) -> Option<Slice<'a>>;
78
79 /// Get the current value as a slice that borrows from the iterator
80 ///
81 /// # Safety
82 ///
83 /// ## Iterator Validity Requirement
84 /// Use `valid()` to check iterator state before calling this method.
85 ///
86 /// ## Lifetime Safety
87 /// The returned slice borrows data directly from the LevelDB iterator without copying.
88 /// The data is only valid until the iterator is advanced to the next position or destroyed.
89 ///
90 /// The caller must ensure that the returned slice does not outlive the iterator
91 /// or any operation that would advance the iterator (such as calling `next()`, `seek()`, etc.).
92 /// To keep the data longer, the slice should be cloned.
93 ///
94 /// ## Performance
95 /// This method provides zero-copy access to LevelDB data for maximum performance.
96 unsafe fn value(&self) -> Option<Slice<'a>>;
97
98 /// Get the current key-value pair as slices that borrow from the iterator
99 ///
100 /// # Safety
101 ///
102 /// ## Iterator Validity Requirement
103 /// Use `valid()` to check iterator state before calling this method.
104 ///
105 /// ## Lifetime Safety
106 /// The returned slices borrow data directly from the LevelDB iterator without copying.
107 /// The data is only valid until the iterator is advanced to the next position or destroyed.
108 ///
109 /// The caller must ensure that the returned slices do not outlive the iterator
110 /// or any operation that would advance the iterator (such as calling `next()`, `seek()`, etc.).
111 /// To keep the data longer, the slice should be cloned.
112 ///
113 /// ## Performance
114 /// This method provides zero-copy access to LevelDB data for maximum performance.
115 unsafe fn entry(&self) -> Option<(Slice<'a>, Slice<'a>)>;
116}
117
118/// Trait for LevelDB iterator operations
119pub trait LevelDBIterator<'a>: Context<'a> {
120 /// Check if iterator is valid
121 fn valid(&self) -> bool;
122
123 /// Seek to specific key
124 fn seek(&self, key: &Slice);
125
126 /// Seek to the first key
127 fn seek_to_first(&self);
128
129 /// Seek to the last key
130 fn seek_to_last(&self);
131
132 /// Get the error message if the iterator is invalid
133 fn get_error(&self) -> Option<Error>;
134}
135
136/// Policy for controlling iterator behavior
137///
138/// This trait defines how iterators should behave during iteration,
139/// including when to stop and whether to seek to the beginning at start.
140pub trait Policy {
141 /// Determines if iteration should continue based on current context
142 fn should_continue(&self, context: &dyn Context) -> bool;
143
144 /// Determines if iterator should seek to beginning at start, default is true
145 fn should_seek_begin(&self) -> bool {
146 true
147 }
148}
149
150/// Default iteration policy with no bounds (iterates over all data)
151pub struct DefaultPolicy;
152
153impl DefaultPolicy {
154 pub fn new() -> Self {
155 Self
156 }
157}
158
159impl Default for DefaultPolicy {
160 fn default() -> Self {
161 Self::new()
162 }
163}
164
165impl Policy for DefaultPolicy {
166 fn should_continue(&self, _context: &dyn Context) -> bool {
167 true
168 }
169}
170
171/// Policy for bounded key iteration with from/to bounds.
172///
173/// This policy restricts iteration to a specific key range.
174///
175/// **Important**: When using `BoundedKeyPolicy`, the method `seek()` must be called explicitly
176/// before starting iteration. This policy does not automatically seek to the beginning position.
177pub struct BoundedKeyPolicy<'a> {
178 from: Option<Slice<'a>>,
179 to: Option<Slice<'a>>,
180}
181
182impl<'a> BoundedKeyPolicy<'a> {
183 pub fn new(from: Option<Slice<'a>>, to: Option<Slice<'a>>) -> Self {
184 Self { from, to }
185 }
186}
187
188impl<'a> Policy for BoundedKeyPolicy<'a> {
189 fn should_continue(&self, context: &dyn Context) -> bool {
190 if let Some(key) = unsafe { context.key() } {
191 if let Some(from) = &self.from
192 && key < *from
193 {
194 return false;
195 }
196 if let Some(to) = &self.to
197 && key >= *to
198 {
199 return false;
200 }
201 }
202 true
203 }
204
205 fn should_seek_begin(&self) -> bool {
206 false
207 }
208}
209
210/// A fully unified iterator over the LevelDB keyspace.
211///
212/// The iteration direction is determined by the generic parameters `D`.
213/// The return type is determined by the generic parameters `T`.
214/// The iteration policy is determined by parameter `P`.
215/// This provides static dispatch for direction-specific, type-specific, and policy-specific operations.
216pub struct Iterator<'a, T = KeyType, D = Forward, P = DefaultPolicy> {
217 iter: RawIterator,
218 started: bool,
219 stopped: bool,
220 policy: P,
221 // Iterator accesses the Database through a leveldb_iter_t pointer
222 // but needs to hold the reference for lifetime tracking
223 #[allow(dead_code)]
224 database: PhantomData<&'a Database>,
225 _return_type: PhantomData<T>,
226 _direction: PhantomData<D>,
227}
228
229// Private methods for this crate only
230impl<'a, T, D, P> Iterator<'a, T, D, P> {
231 /// Core factory method to create iterator with specified direction and policy
232 fn new(
233 database: &'a Database,
234 options: ReadOptions<'a>,
235 policy: P,
236 _direction: PhantomData<D>,
237 _return_type: PhantomData<T>,
238 ) -> Self {
239 unsafe {
240 let c_readoptions = c_readoptions(&options);
241 let ptr = leveldb_create_iterator(database.database.ptr, c_readoptions);
242 leveldb_readoptions_destroy(c_readoptions);
243
244 Iterator {
245 iter: RawIterator { ptr },
246 started: false,
247 stopped: false,
248 policy,
249 database: PhantomData,
250 _return_type: PhantomData,
251 _direction: PhantomData,
252 }
253 }
254 }
255
256 /// Get the raw iterator pointer
257 #[inline]
258 fn raw_iterator(&self) -> *mut leveldb_iterator_t {
259 self.iter.ptr
260 }
261
262 #[inline]
263 fn move_forward(&self) {
264 unsafe { leveldb_iter_next(self.raw_iterator()) }
265 }
266
267 #[inline]
268 fn move_backward(&self) {
269 unsafe { leveldb_iter_prev(self.raw_iterator()) }
270 }
271}
272
273impl<'a, T, D, P> Context<'a> for Iterator<'a, T, D, P> {
274 #[inline]
275 unsafe fn key(&self) -> Option<Slice<'a>> {
276 unsafe {
277 let length: size_t = 0;
278 let value = leveldb_iter_key(self.raw_iterator(), &length) as *const u8;
279 if value.is_null() || length == 0 {
280 None
281 } else {
282 let data = std::slice::from_raw_parts(value, length);
283 Some(Slice::from(data))
284 }
285 }
286 }
287
288 #[inline]
289 unsafe fn value(&self) -> Option<Slice<'a>> {
290 unsafe {
291 let length: size_t = 0;
292 let value = leveldb_iter_value(self.raw_iterator(), &length) as *const u8;
293 if value.is_null() || length == 0 {
294 None
295 } else {
296 let data = std::slice::from_raw_parts(value, length);
297 Some(Slice::from(data))
298 }
299 }
300 }
301
302 #[inline]
303 unsafe fn entry(&self) -> Option<(Slice<'a>, Slice<'a>)> {
304 unsafe {
305 match (self.key(), self.value()) {
306 (Some(key), Some(value)) => Some((key, value)),
307 _ => None,
308 }
309 }
310 }
311}
312
313/// Macro to implement Iterator trait for different
314/// - return types
315/// - directions
316/// - policies
317macro_rules! impl_iterator {
318 ($T:ty, $Item:ty, $ItemFn:ident, $D:ty, $MoveFn:ident, $SeekInitFn:ident, $SeekLastFn:ident) => {
319 impl<'a, P: Policy> iter::Iterator for Iterator<'a, $T, $D, P> {
320 type Item = $Item;
321
322 #[inline]
323 fn next(&mut self) -> Option<Self::Item> {
324 if self.advance() {
325 unsafe { self.$ItemFn() }
326 } else {
327 None
328 }
329 }
330 }
331
332 impl<'a, P: Policy> Iterator<'a, $T, $D, P> {
333 /// Return the last element of the iterator
334 ///
335 /// The returned slice borrows data directly from the LevelDB iterator without copying.
336 /// The data is only valid until the iterator is advanced to the next position or destroyed.
337 ///
338 /// # Safety
339 /// The caller must ensure that the returned slice does not outlive the iterator
340 /// or any operation that would advance the iterator (such as calling `next()`).
341 /// To keep the data longer, the slice should be cloned.
342 ///
343 /// # Performance
344 /// This method provides zero-copy access to LevelDB data for maximum performance
345 #[inline]
346 pub fn last(&mut self) -> Result<Option<$Item>, Error> {
347 self.$SeekLastFn();
348 if self.valid() {
349 Ok(unsafe { self.$ItemFn() })
350 } else {
351 match self.get_error() {
352 Some(e) => Err(e),
353 None => Ok(None),
354 }
355 }
356 }
357
358 #[inline]
359 fn advance(&mut self) -> bool {
360 if self.stopped {
361 return false;
362 }
363 if !self.started {
364 if self.policy.should_seek_begin() {
365 self.$SeekInitFn();
366 }
367 self.started = true;
368 } else {
369 // Subsequent calls: move to next position
370 self.$MoveFn();
371 }
372 // Check if current position is valid and should continue
373 self.stopped = !self.valid() || !self.policy.should_continue(self);
374 !self.stopped
375 }
376 }
377 };
378}
379
380impl<'a, T, D, P: Policy> LevelDBIterator<'a> for Iterator<'a, T, D, P> {
381 #[inline]
382 fn valid(&self) -> bool {
383 unsafe { leveldb_iter_valid(self.raw_iterator()) != 0 }
384 }
385
386 #[inline]
387 fn seek(&self, key: &Slice) {
388 unsafe {
389 let key = key.as_bytes();
390 leveldb_iter_seek(
391 self.raw_iterator(),
392 key.as_ptr() as *mut c_char,
393 key.len() as size_t,
394 );
395 }
396 }
397
398 #[inline]
399 fn seek_to_first(&self) {
400 unsafe { leveldb_iter_seek_to_first(self.raw_iterator()) }
401 }
402
403 #[inline]
404 fn seek_to_last(&self) {
405 unsafe { leveldb_iter_seek_to_last(self.raw_iterator()) }
406 }
407
408 #[inline]
409 fn get_error(&self) -> Option<Error> {
410 unsafe {
411 let mut errptr: *mut c_char = std::ptr::null_mut();
412 leveldb_iter_get_error(self.raw_iterator(), &mut errptr);
413
414 if errptr.is_null() {
415 None
416 } else {
417 Some(Error::new_from_char(errptr))
418 }
419 }
420 }
421}
422
423// Apply macro to generate Iterator implementations
424// For different types: key, value & entry
425macro_rules! impl_iterators_for_direction {
426 ($MoveFn:ident, $SeekInitFn:ident, $SeekLastFn:ident, $Dir:ty) => {
427 impl_iterator!(
428 KeyType,
429 Slice<'a>,
430 key,
431 $Dir,
432 $MoveFn,
433 $SeekInitFn,
434 $SeekLastFn
435 );
436 impl_iterator!(
437 ValueType,
438 Slice<'a>,
439 value,
440 $Dir,
441 $MoveFn,
442 $SeekInitFn,
443 $SeekLastFn
444 );
445 impl_iterator!(
446 EntryType,
447 (Slice<'a>, Slice<'a>),
448 entry,
449 $Dir,
450 $MoveFn,
451 $SeekInitFn,
452 $SeekLastFn
453 );
454 };
455}
456// For 2 different directions
457impl_iterators_for_direction!(move_forward, seek_to_first, seek_to_last, Forward);
458impl_iterators_for_direction!(move_backward, seek_to_last, seek_to_first, Backward);
459
460pub type KeyIterator<'a, P = DefaultPolicy> = Iterator<'a, KeyType, Forward, P>;
461pub type ValueIterator<'a, P = DefaultPolicy> = Iterator<'a, ValueType, Forward, P>;
462pub type EntryIterator<'a, P = DefaultPolicy> = Iterator<'a, EntryType, Forward, P>;
463pub type KeyIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, KeyType, Backward, P>;
464pub type ValueIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, ValueType, Backward, P>;
465pub type EntryIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, EntryType, Backward, P>;
466
467/// A trait to provide various iterators of LevelDB instance.
468///
469/// This trait provides a unified interface for creating different types of iterators
470/// over LevelDB data. The API is designed to be flexible while maintaining type safety
471/// and performance.
472///
473/// # Iterator Types
474///
475/// There are three main iterator types, each defined by `T` type parameter:
476///
477/// - **EntryIterator** (`EntryType`): Iterates over key-value pairs `(K, V)`
478/// - **KeyIterator** (`KeyType`): Iterates over keys only `K`
479/// - **ValueIterator** (`ValueType`): Iterates over values only `V`
480///
481/// # Direction
482///
483/// The direction is controlled by `D` type parameter:
484///
485/// - **Forward** (`Forward`): Iterates from smallest to largest key
486/// - **Backward** (`Backward`): Iterates from largest to smallest key
487///
488/// # Policies
489///
490/// Policies control iteration behavior and bounds. For example:
491///
492/// - **DefaultPolicy**: No bounds, iterates over all data
493/// - **BoundedKeyPolicy**: Iterates within specified key bounds
494///
495/// # Usage Examples
496///
497/// ## Basic Entry Iteration
498///
499/// ```ignore
500/// // Forward iteration over all key-value pairs
501/// let iter: EntryIterator<'_> = database.iter(ReadOptions::new());
502///
503/// // Backward iteration over all key-value pairs
504/// let iter: EntryIteratorRev<'_> = database.iter(ReadOptions::new());
505/// ```
506///
507/// ## Key-Only Iteration
508///
509/// ```ignore
510/// // Forward iteration over keys only
511/// let iter: KeyIterator<'_> = database.iter(ReadOptions::new());
512///
513/// // Backward iteration over keys only
514/// let iter: KeyIteratorRev<'_> = database.iter(ReadOptions::new());
515/// ```
516///
517/// ## Value-Only Iteration
518///
519/// ```ignore
520/// // Forward iteration over values only
521/// let iter: ValueIterator<'_> = database.iter(ReadOptions::new());
522///
523/// // Backward iteration over values only
524/// let iter: ValueIteratorRev<'_> = database.iter(ReadOptions::new());
525/// ```
526pub trait Iterable<'a> {
527 /// Create an iterator with specified type, direction, and policy
528 /// Specify return type for correctness of inference
529 ///
530 /// This is the most flexible method that allows complete control over iterator behavior,
531 /// with custom policies.
532 ///
533 /// # Parameters
534 ///
535 /// - `options`: Read options for the iterator
536 /// - `policy`: Iteration policy (bounds, filtering, etc.)
537 ///
538 /// # Returns
539 ///
540 /// An iterator with the specified type, direction, and policy.
541 ///
542 /// # Example
543 ///
544 /// ```ignore
545 /// let begin = Slice::from(&b"key1"[..]);
546 /// let end = Slice::from(&b"key9"[..]);
547 /// let policy = BoundedKeyPolicy::new(Some(begin), Some(end));
548 ///
549 /// // Bounded entry iteration
550 /// let iter: KeyIterator<'_, _> = database.iter_with_policy(ReadOptions::new(), policy);
551 ///
552 /// // Remember to seek to the start position for bounded iteration
553 /// iter.seek(&begin);
554 /// ```
555 fn iter_with_policy<T, D, P: Policy>(
556 &'a self,
557 options: ReadOptions<'a>,
558 policy: P,
559 ) -> Iterator<'a, T, D, P>;
560
561 /// Create an iterator with specified type and direction, using DefaultPolicy
562 ///
563 /// This is a convenience method that uses the `DefaultPolicy`.
564 ///
565 /// Note: The default iterator type is `KeyIterator` for key-only iteration.
566 /// Use explicit type annotation for other iterator types.
567 ///
568 /// # Parameters
569 ///
570 /// - `options`: Read options for the iterator
571 ///
572 /// # Returns
573 ///
574 /// An iterator with the specified type and direction, using DefaultPolicy.
575 ///
576 /// # Example
577 ///
578 /// ```ignore
579 /// let policy = BoundedKeyPolicy::new(
580 /// Some(Slice::from(&b"start"[..])),
581 /// Some(Slice::from(&b"end"[..]))
582 /// );
583 /// let iter: EntryIterator<'_, _> = database.iter_with_policy(ReadOptions::new(), policy);
584 /// ```
585 fn iter<T, D>(&'a self, options: ReadOptions<'a>) -> Iterator<'a, T, D, DefaultPolicy> {
586 self.iter_with_policy(options, DefaultPolicy)
587 }
588}
589
590impl<'a> Iterable<'a> for Database {
591 fn iter_with_policy<T, D, P: Policy>(
592 &'a self,
593 options: ReadOptions<'a>,
594 policy: P,
595 ) -> Iterator<'a, T, D, P> {
596 Iterator::new(self, options, policy, PhantomData, PhantomData)
597 }
598}