use super::Database;
use super::error::Error;
use super::options::{ReadOptions, c_readoptions};
use super::slice::Slice;
use crate::binding::{
leveldb_create_iterator, leveldb_iter_destroy, leveldb_iter_get_error, leveldb_iter_key,
leveldb_iter_next, leveldb_iter_prev, leveldb_iter_seek, leveldb_iter_seek_to_first,
leveldb_iter_seek_to_last, leveldb_iter_valid, leveldb_iter_value, leveldb_iterator_t,
leveldb_readoptions_destroy,
};
use libc::{c_char, size_t};
use std::iter;
use std::marker::PhantomData;
#[allow(missing_docs)]
struct RawIterator {
ptr: *mut leveldb_iterator_t,
}
#[allow(missing_docs)]
impl Drop for RawIterator {
fn drop(&mut self) {
unsafe { leveldb_iter_destroy(self.ptr) }
}
}
pub struct KeyType;
pub struct ValueType;
pub struct EntryType;
pub struct Forward;
pub struct Backward;
pub trait Context<'a> {
unsafe fn key(&self) -> Option<Slice<'a>>;
unsafe fn value(&self) -> Option<Slice<'a>>;
unsafe fn entry(&self) -> Option<(Slice<'a>, Slice<'a>)>;
}
pub trait LevelDBIterator<'a>: Context<'a> {
fn valid(&self) -> bool;
fn seek(&self, key: &Slice);
fn seek_to_first(&self);
fn seek_to_last(&self);
fn get_error(&self) -> Option<Error>;
}
pub trait Policy {
fn should_continue(&self, context: &dyn Context) -> bool;
fn should_seek_begin(&self) -> bool {
true
}
}
pub struct DefaultPolicy;
impl DefaultPolicy {
pub fn new() -> Self {
Self
}
}
impl Default for DefaultPolicy {
fn default() -> Self {
Self::new()
}
}
impl Policy for DefaultPolicy {
fn should_continue(&self, _context: &dyn Context) -> bool {
true
}
}
pub struct BoundedKeyPolicy<'a> {
from: Option<Slice<'a>>,
to: Option<Slice<'a>>,
}
impl<'a> BoundedKeyPolicy<'a> {
pub fn new(from: Option<Slice<'a>>, to: Option<Slice<'a>>) -> Self {
Self { from, to }
}
}
impl<'a> Policy for BoundedKeyPolicy<'a> {
fn should_continue(&self, context: &dyn Context) -> bool {
if let Some(key) = unsafe { context.key() } {
if let Some(from) = &self.from
&& key < *from
{
return false;
}
if let Some(to) = &self.to
&& key >= *to
{
return false;
}
}
true
}
fn should_seek_begin(&self) -> bool {
false
}
}
pub struct Iterator<'a, T = KeyType, D = Forward, P = DefaultPolicy> {
iter: RawIterator,
started: bool,
stopped: bool,
policy: P,
#[allow(dead_code)]
database: PhantomData<&'a Database>,
_return_type: PhantomData<T>,
_direction: PhantomData<D>,
}
impl<'a, T, D, P> Iterator<'a, T, D, P> {
fn new(
database: &'a Database,
options: ReadOptions<'a>,
policy: P,
_direction: PhantomData<D>,
_return_type: PhantomData<T>,
) -> Self {
unsafe {
let c_readoptions = c_readoptions(&options);
let ptr = leveldb_create_iterator(database.database.ptr, c_readoptions);
leveldb_readoptions_destroy(c_readoptions);
Iterator {
iter: RawIterator { ptr },
started: false,
stopped: false,
policy,
database: PhantomData,
_return_type: PhantomData,
_direction: PhantomData,
}
}
}
#[inline]
fn raw_iterator(&self) -> *mut leveldb_iterator_t {
self.iter.ptr
}
#[inline]
fn move_forward(&self) {
unsafe { leveldb_iter_next(self.raw_iterator()) }
}
#[inline]
fn move_backward(&self) {
unsafe { leveldb_iter_prev(self.raw_iterator()) }
}
}
impl<'a, T, D, P> Context<'a> for Iterator<'a, T, D, P> {
#[inline]
unsafe fn key(&self) -> Option<Slice<'a>> {
unsafe {
let length: size_t = 0;
let value = leveldb_iter_key(self.raw_iterator(), &length) as *const u8;
if value.is_null() || length == 0 {
None
} else {
let data = std::slice::from_raw_parts(value, length);
Some(Slice::from(data))
}
}
}
#[inline]
unsafe fn value(&self) -> Option<Slice<'a>> {
unsafe {
let length: size_t = 0;
let value = leveldb_iter_value(self.raw_iterator(), &length) as *const u8;
if value.is_null() || length == 0 {
None
} else {
let data = std::slice::from_raw_parts(value, length);
Some(Slice::from(data))
}
}
}
#[inline]
unsafe fn entry(&self) -> Option<(Slice<'a>, Slice<'a>)> {
unsafe {
match (self.key(), self.value()) {
(Some(key), Some(value)) => Some((key, value)),
_ => None,
}
}
}
}
macro_rules! impl_iterator {
($T:ty, $Item:ty, $ItemFn:ident, $D:ty, $MoveFn:ident, $SeekInitFn:ident, $SeekLastFn:ident) => {
impl<'a, P: Policy> iter::Iterator for Iterator<'a, $T, $D, P> {
type Item = $Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.advance() {
unsafe { self.$ItemFn() }
} else {
None
}
}
}
impl<'a, P: Policy> Iterator<'a, $T, $D, P> {
#[inline]
pub fn last(&mut self) -> Result<Option<$Item>, Error> {
self.$SeekLastFn();
if self.valid() {
Ok(unsafe { self.$ItemFn() })
} else {
match self.get_error() {
Some(e) => Err(e),
None => Ok(None),
}
}
}
#[inline]
fn advance(&mut self) -> bool {
if self.stopped {
return false;
}
if !self.started {
if self.policy.should_seek_begin() {
self.$SeekInitFn();
}
self.started = true;
} else {
self.$MoveFn();
}
self.stopped = !self.valid() || !self.policy.should_continue(self);
!self.stopped
}
}
};
}
impl<'a, T, D, P: Policy> LevelDBIterator<'a> for Iterator<'a, T, D, P> {
#[inline]
fn valid(&self) -> bool {
unsafe { leveldb_iter_valid(self.raw_iterator()) != 0 }
}
#[inline]
fn seek(&self, key: &Slice) {
unsafe {
let key = key.as_bytes();
leveldb_iter_seek(
self.raw_iterator(),
key.as_ptr() as *mut c_char,
key.len() as size_t,
);
}
}
#[inline]
fn seek_to_first(&self) {
unsafe { leveldb_iter_seek_to_first(self.raw_iterator()) }
}
#[inline]
fn seek_to_last(&self) {
unsafe { leveldb_iter_seek_to_last(self.raw_iterator()) }
}
#[inline]
fn get_error(&self) -> Option<Error> {
unsafe {
let mut errptr: *mut c_char = std::ptr::null_mut();
leveldb_iter_get_error(self.raw_iterator(), &mut errptr);
if errptr.is_null() {
None
} else {
Some(Error::new_from_char(errptr))
}
}
}
}
macro_rules! impl_iterators_for_direction {
($MoveFn:ident, $SeekInitFn:ident, $SeekLastFn:ident, $Dir:ty) => {
impl_iterator!(
KeyType,
Slice<'a>,
key,
$Dir,
$MoveFn,
$SeekInitFn,
$SeekLastFn
);
impl_iterator!(
ValueType,
Slice<'a>,
value,
$Dir,
$MoveFn,
$SeekInitFn,
$SeekLastFn
);
impl_iterator!(
EntryType,
(Slice<'a>, Slice<'a>),
entry,
$Dir,
$MoveFn,
$SeekInitFn,
$SeekLastFn
);
};
}
impl_iterators_for_direction!(move_forward, seek_to_first, seek_to_last, Forward);
impl_iterators_for_direction!(move_backward, seek_to_last, seek_to_first, Backward);
pub type KeyIterator<'a, P = DefaultPolicy> = Iterator<'a, KeyType, Forward, P>;
pub type ValueIterator<'a, P = DefaultPolicy> = Iterator<'a, ValueType, Forward, P>;
pub type EntryIterator<'a, P = DefaultPolicy> = Iterator<'a, EntryType, Forward, P>;
pub type KeyIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, KeyType, Backward, P>;
pub type ValueIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, ValueType, Backward, P>;
pub type EntryIteratorRev<'a, P = DefaultPolicy> = Iterator<'a, EntryType, Backward, P>;
pub trait Iterable<'a> {
fn iter_with_policy<T, D, P: Policy>(
&'a self,
options: ReadOptions<'a>,
policy: P,
) -> Iterator<'a, T, D, P>;
fn iter<T, D>(&'a self, options: ReadOptions<'a>) -> Iterator<'a, T, D, DefaultPolicy> {
self.iter_with_policy(options, DefaultPolicy)
}
}
impl<'a> Iterable<'a> for Database {
fn iter_with_policy<T, D, P: Policy>(
&'a self,
options: ReadOptions<'a>,
policy: P,
) -> Iterator<'a, T, D, P> {
Iterator::new(self, options, policy, PhantomData, PhantomData)
}
}