mod zset_macro;
use crate::{
dynamic::{DataTrait, DynUnit, DynWeightTyped, Erase, WeightTrait},
trace::{
Batch, BatchReader, Builder, Cursor, OrdIndexedWSet, OrdIndexedWSetFactories, OrdWSet,
OrdWSetFactories, Trace,
ord::vec::{VecIndexedWSet, VecIndexedWSetFactories, VecWSet, VecWSetFactories},
},
};
use dyn_clone::clone_box;
use std::ops::Neg;
use super::{AddAssignByRef, AddByRef, HasOne, NegByRef, ZRingValue};
pub type ZWeight = i64;
pub type DynZWeight = DynWeightTyped<ZWeight>;
pub type OrdZSet<K> = OrdWSet<K, DynZWeight>;
pub type OrdZSetFactories<K> = OrdWSetFactories<K, DynZWeight>;
pub type VecZSet<K> = VecWSet<K, DynZWeight>;
pub type VecZSetFactories<K> = VecWSetFactories<K, DynZWeight>;
pub type OrdIndexedZSet<K, V> = OrdIndexedWSet<K, V, DynZWeight>;
pub type OrdIndexedZSetFactories<K, V> = OrdIndexedWSetFactories<K, V, DynZWeight>;
pub type VecIndexedZSet<K, V> = VecIndexedWSet<K, V, DynZWeight>;
pub type VecIndexedZSetFactories<K, V> = VecIndexedWSetFactories<K, V, DynZWeight>;
pub trait ZCursor<K: ?Sized, V: ?Sized, T>: Cursor<K, V, T, DynZWeight> {}
impl<K: ?Sized, V: ?Sized, T, C> ZCursor<K, V, T> for C where C: Cursor<K, V, T, DynZWeight> {}
pub trait ZBatchReader: BatchReader<R = DynZWeight> {}
impl<B> ZBatchReader for B where B: BatchReader<R = DynZWeight> {}
pub trait ZBatch: Batch<R = DynZWeight> {}
impl<B> ZBatch for B where B: Batch<R = DynZWeight> {}
pub trait ZTrace: Trace<R = DynZWeight> {}
impl<T> ZTrace for T where T: Trace<R = DynZWeight> {}
pub trait IndexedZSetReader: BatchReader<Time = (), R = DynZWeight> {
fn iter(&self) -> IndexedZSetIterator<'_, Self> {
IndexedZSetIterator::new(self.cursor())
}
}
impl<Z> IndexedZSetReader for Z where Z: BatchReader<Time = (), R = DynZWeight> {}
pub trait IndexedZSet:
Batch<Time = (), R = DynZWeight> + AddByRef + AddAssignByRef + Neg<Output = Self> + NegByRef + Eq
{
fn distinct(&self) -> Self;
fn distinct_owned(self) -> Self {
self.distinct()
}
}
impl<Z> IndexedZSet for Z
where
Z: Batch<Time = (), R = DynZWeight>
+ AddByRef
+ AddAssignByRef
+ Neg<Output = Z>
+ NegByRef
+ Eq,
{
fn distinct(&self) -> Self {
let factories = self.factories();
let mut builder = Self::Builder::with_capacity(&factories, self.key_count(), self.len());
let mut cursor = self.cursor();
while cursor.key_valid() {
let mut n_updates = 0;
while cursor.val_valid() {
let weight = cursor.weight();
if weight.ge0() {
builder.push_val_diff(cursor.val(), ZWeight::one().erase());
n_updates += 1;
}
cursor.step_val();
}
if n_updates > 0 {
builder.push_key(cursor.key());
}
cursor.step_key();
}
builder.done()
}
}
pub struct IndexedZSetIterator<'a, Z>
where
Z: IndexedZSetReader,
{
cursor: Z::Cursor<'a>,
}
impl<'a, Z> IndexedZSetIterator<'a, Z>
where
Z: IndexedZSetReader,
{
fn new(cursor: Z::Cursor<'a>) -> Self {
Self { cursor }
}
}
impl<Z> Iterator for IndexedZSetIterator<'_, Z>
where
Z: IndexedZSetReader,
{
type Item = (Box<Z::Key>, Box<Z::Val>, ZWeight);
fn next(&mut self) -> Option<Self::Item> {
while self.cursor.key_valid() {
if self.cursor.val_valid() {
let weight = **self.cursor.weight();
let retval = (
clone_box(self.cursor.key()),
clone_box(self.cursor.val()),
weight,
);
self.cursor.step_val();
return Some(retval);
}
self.cursor.step_key();
}
None
}
}
pub trait ZSetReader: IndexedZSetReader<Val = DynUnit> {}
impl<Z> ZSetReader for Z where Z: IndexedZSetReader<Val = DynUnit> {}
pub trait ZSet: IndexedZSet<Val = DynUnit> {
fn weighted_count(&self, sum: &mut Self::R);
}
impl<Z, K> ZSet for Z
where
Z: IndexedZSet<Key = K, Val = DynUnit>,
K: DataTrait + ?Sized,
{
fn weighted_count(&self, sum: &mut Self::R) {
sum.set_zero();
let mut cursor = self.cursor();
while cursor.key_valid() {
WeightTrait::add_assign(sum, cursor.weight());
cursor.step_key();
}
}
}
#[cfg(test)]
mod test {
use crate::{
ZWeight,
typed_batch::{IndexedZSetReader, OrdIndexedZSet},
utils::Tup2,
};
#[test]
fn test_indexed_zset_iterator() {
let tuples: Vec<Tup2<Tup2<i64, String>, ZWeight>> = vec![
Tup2(Tup2(1, "a".to_string()), 1),
Tup2(Tup2(1, "b".to_string()), 2),
Tup2(Tup2(1, "c".to_string()), -1),
Tup2(Tup2(2, "d".to_string()), 1),
]
.into_iter()
.collect();
let indexed_zset = <OrdIndexedZSet<i64, String>>::from_tuples((), tuples.clone());
assert_eq!(
indexed_zset
.iter()
.map(|(k, v, w)| Tup2(Tup2(k, v), w))
.collect::<Vec<_>>(),
tuples
);
let indexed_zset = <OrdIndexedZSet<i64, String>>::from_tuples((), vec![]);
assert_eq!(
indexed_zset
.iter()
.map(|(k, v, w)| ((k, v), w))
.collect::<Vec<_>>(),
Vec::new()
);
}
}