use std::sync::{Arc, RwLock};
use crate::{IntoKey, KvBackend, KvKey, KvResult, KvValue};
pub struct KvListBuilder {
pub(crate) backend: Arc<RwLock<Box<dyn KvBackend>>>,
pub(crate) prefix: Option<KvKey>,
pub(crate) start: Option<KvKey>,
pub(crate) end: Option<KvKey>,
}
impl KvListBuilder {
pub(crate) fn new(backend: Arc<RwLock<Box<dyn KvBackend>>>) -> Self {
Self {
backend,
prefix: None,
start: None,
end: None,
}
}
pub fn prefix(&mut self, prefix: &dyn IntoKey) -> &mut Self {
self.prefix = Some(prefix.to_key());
self
}
pub fn start(&mut self, start: &dyn IntoKey) -> &mut Self {
self.start = Some(start.to_key());
self
}
pub fn end(&mut self, end: &dyn IntoKey) -> &mut Self {
self.end = Some(end.to_key());
self
}
pub fn entries(&self) -> KvResult<Vec<(KvKey, KvValue)>> {
use crate::KvError;
if self.prefix.is_some() && self.start.is_some() && self.end.is_some() {
return Err(KvError::InvalidSelector);
}
let (range_start, range_end) =
match (self.prefix.clone(), self.start.clone(), self.end.clone()) {
(Some(prefix), None, None) => {
let end = prefix.successor();
(Some(prefix), end)
}
(None, Some(start), None) => (Some(start), None),
(None, None, Some(end)) => (None, Some(end)),
(Some(_prefix), Some(start), None) => (Some(start), None), (Some(prefix), None, Some(end)) => (Some(prefix), Some(end)),
(None, Some(start), Some(end)) => (Some(start), Some(end)),
(None, None, None) => (None, None),
_ => return Err(KvError::InvalidSelector),
};
let items = self
.backend
.try_write()?
.get_range(range_start, range_end)?;
let mut result = Vec::with_capacity(items.len());
for (k, v) in items {
let (decoded, _consumed) =
bincode::decode_from_slice::<KvValue, _>(&v, bincode::config::standard())
.map_err(KvError::ValDecodeError)?;
result.push((k, decoded));
}
Ok(result)
}
}