use crate::cursor::Cursor;
use crate::database_entry::DatabaseEntry;
use crate::error::{NoxuError, Result};
use crate::get::Get;
use crate::operation_status::OperationStatus;
use std::ops::Bound;
pub struct DbIter {
cursor: Cursor,
started: bool,
done: bool,
}
impl DbIter {
pub(crate) fn new(cursor: Cursor) -> Self {
Self { cursor, started: false, done: false }
}
}
impl Iterator for DbIter {
type Item = Result<(Vec<u8>, Vec<u8>)>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
let get_type = if self.started { Get::Next } else { Get::First };
self.started = true;
let mut key = DatabaseEntry::new();
let mut val = DatabaseEntry::new();
match self.cursor.get(&mut key, &mut val, get_type, None) {
Err(e) => {
self.done = true;
Some(Err(e))
}
Ok(OperationStatus::Success) => {
let k = key.get_data().unwrap_or(&[]).to_vec();
let v = val.get_data().unwrap_or(&[]).to_vec();
Some(Ok((k, v)))
}
Ok(_) => {
self.done = true;
None
}
}
}
}
pub struct DbRange {
cursor: Cursor,
end_bound: Bound<Vec<u8>>,
done: bool,
positioned: bool,
start_key: Option<Vec<u8>>,
exclude_start: bool,
}
impl DbRange {
pub(crate) fn new(
cursor: Cursor,
start_bound: Bound<Vec<u8>>,
end_bound: Bound<Vec<u8>>,
) -> Self {
let (start_key, exclude_start) = match start_bound {
Bound::Included(k) => (Some(k), false),
Bound::Excluded(k) => (Some(k), true),
Bound::Unbounded => (None, false),
};
Self {
cursor,
end_bound,
done: false,
positioned: false,
start_key,
exclude_start,
}
}
fn past_end(&self, key: &[u8]) -> bool {
match &self.end_bound {
Bound::Unbounded => false,
Bound::Included(end) => key > end.as_slice(),
Bound::Excluded(end) => key >= end.as_slice(),
}
}
}
impl Iterator for DbRange {
type Item = Result<(Vec<u8>, Vec<u8>)>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
let mut key_entry = DatabaseEntry::new();
let mut val_entry = DatabaseEntry::new();
if !self.positioned {
self.positioned = true;
let status = if let Some(ref sk) = self.start_key {
key_entry.set_data(sk);
self.cursor.get(
&mut key_entry,
&mut val_entry,
Get::SearchGte,
None,
)
} else {
self.cursor.get(
&mut key_entry,
&mut val_entry,
Get::First,
None,
)
};
match status {
Err(e) => {
self.done = true;
return Some(Err(e));
}
Ok(OperationStatus::Success) => {
let k = key_entry.get_data().unwrap_or(&[]).to_vec();
let v = val_entry.get_data().unwrap_or(&[]).to_vec();
if self.past_end(&k) {
self.done = true;
return None;
}
if self.exclude_start
&& self
.start_key
.as_ref()
.is_some_and(|sk| k.as_slice() == sk.as_slice())
{
self.positioned = true;
} else {
return Some(Ok((k, v)));
}
}
Ok(_) => {
self.done = true;
return None;
}
}
}
match self.cursor.get(&mut key_entry, &mut val_entry, Get::Next, None) {
Err(e) => {
self.done = true;
Some(Err(e))
}
Ok(OperationStatus::Success) => {
let k = key_entry.get_data().unwrap_or(&[]).to_vec();
let v = val_entry.get_data().unwrap_or(&[]).to_vec();
if self.past_end(&k) {
self.done = true;
None
} else {
Some(Ok((k, v)))
}
}
Ok(_) => {
self.done = true;
None
}
}
}
}