use std::ops::Bound;
use std::sync::Arc;
use crate::key::Key;
use crate::map_index::Dir;
use crate::scope::key_math;
type KeyIter<S, K> =
for<'a> fn(&'a S, Bound<&'a K>, Bound<&'a K>, Dir) -> Box<dyn Iterator<Item = K> + 'a>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Selection {
pub queued: usize,
pub done: bool,
}
pub struct TxScope<S, K: Key, const N: usize> {
pub(super) collection: Arc<S>,
pub(super) prefix_key: K,
pub(super) start: Bound<K>,
pub(super) end: Bound<K>,
pub(super) dir: Dir,
keys: KeyIter<S, K>,
}
impl<S, K: Key, const N: usize> TxScope<S, K, N> {
pub(crate) fn from_parts(collection: Arc<S>, key: &K, dir: Dir, keys: KeyIter<S, K>) -> Self {
const { key_math::assert_scope_n::<K>(N) };
let (start, end) = key_math::scope_bounds_n::<K, N>(key);
Self {
collection,
prefix_key: key_math::prefix_key(key, N),
start,
end,
dir,
keys,
}
}
pub fn range<const M: usize>(mut self, start: Bound<&K>, end: Bound<&K>) -> Self {
const { key_math::assert_range_m::<K>(N, M) };
(self.start, self.end) =
key_math::saturate_range_bounds(&self.prefix_key, N, M, start, end);
self
}
pub fn asc(mut self) -> Self {
self.dir = Dir::Asc;
self
}
pub fn desc(mut self) -> Self {
self.dir = Dir::Desc;
self
}
pub(crate) fn keys(&self) -> Box<dyn Iterator<Item = K> + '_> {
(self.keys)(
self.collection.as_ref(),
bound_as_ref(&self.start),
bound_as_ref(&self.end),
self.dir,
)
}
}
fn bound_as_ref<K>(bound: &Bound<K>) -> Bound<&K> {
match bound {
Bound::Included(key) => Bound::Included(key),
Bound::Excluded(key) => Bound::Excluded(key),
Bound::Unbounded => Bound::Unbounded,
}
}