use blake2::Blake2s256;
use crate::filter::FilterComparator;
use crate::ordering::OrderingDirection;
use crate::value::Value;
use crate::{filter::Filter, schema::SchemaMapped};
use blake2::Digest;
use crate::ordering::Ordering;
pub fn get_page_filter<T: SchemaMapped>(ordering: &Ordering, next_item: &T) -> Filter {
let mut filters = Vec::new();
for term in ordering.iter() {
let term_argument = match next_item.get_field(&term.name) {
Value::Integer(value) => Filter::Value(value.into()),
Value::Float(value) => Filter::Value(value.into()),
Value::Boolean(value) => Filter::Value(value.into()),
Value::String(value) => Filter::Value(value.into()),
Value::Timestamp(value) => Filter::Value(value.into()),
Value::Repeated(value) => Filter::Value(value.into()),
Value::Any => Filter::Value(Value::Any),
};
filters.push(Filter::Restriction(
Box::new(Filter::Name(term.name.clone())),
match term.direction {
OrderingDirection::Ascending => FilterComparator::GreaterOrEqual,
OrderingDirection::Descending => FilterComparator::LessOrEqual,
},
Box::new(term_argument),
));
}
Filter::Conjunction(filters)
}
pub fn make_page_key<const N: usize>(filter: &Filter, ordering: &Ordering, salt: &[u8]) -> [u8; N] {
let mut hasher = Blake2s256::new();
hasher.update(filter.to_string().as_bytes());
hasher.update(ordering.to_string().as_bytes());
hasher.update(salt);
let res = hasher.finalize();
debug_assert_eq!(res.len(), N);
let key: [u8; N] = res[..].try_into().unwrap();
key
}