use crate::cacheable::Cacheable;
use crate::predicate::{IntoBasicPredicate, MemQ};
use crate::punnu::Punnu;
use std::cmp::Ordering;
use std::hash::Hash;
use std::sync::Arc;
pub struct PunnuScope<T: Cacheable> {
pool: Arc<Punnu<T>>,
ops: Vec<MemQ<T>>,
}
impl<T: Cacheable> PunnuScope<T> {
pub fn new(pool: Arc<Punnu<T>>, ops: impl Into<Vec<MemQ<T>>>) -> Self {
Self {
pool,
ops: ops.into(),
}
}
pub fn then(mut self, op: MemQ<T>) -> Self {
self.ops.push(op);
self
}
pub fn filter<F>(self, build: F) -> Self
where
F: FnOnce(T::Fields) -> MemQ<T>,
{
self.then(build(T::fields()))
}
pub fn filter_basic<F, P>(self, build: F) -> Self
where
F: FnOnce(T::Fields) -> P,
P: IntoBasicPredicate<T>,
{
self.then(MemQ::filter_basic(build(T::fields())))
}
pub fn filter_closure<F>(self, predicate: F) -> Self
where
F: Fn(&T) -> bool + Send + Sync + 'static,
{
self.then(MemQ::filter(predicate))
}
pub fn map_arc<F>(self, map: F) -> Self
where
F: Fn(Arc<T>) -> Arc<T> + Send + Sync + 'static,
{
self.then(MemQ::map_arc(map))
}
pub fn flat_map_arc<F>(self, flat_map: F) -> Self
where
F: Fn(Arc<T>) -> Vec<Arc<T>> + Send + Sync + 'static,
{
self.then(MemQ::flat_map_arc(flat_map))
}
pub fn take(self, count: usize) -> Self {
self.then(MemQ::take(count))
}
pub fn skip(self, count: usize) -> Self {
self.then(MemQ::skip(count))
}
pub fn chain<I>(self, values: I) -> Self
where
I: IntoIterator<Item = Arc<T>>,
{
self.then(MemQ::chain(values))
}
pub fn sort<F>(self, compare: F) -> Self
where
F: Fn(&Arc<T>, &Arc<T>) -> Ordering + Send + Sync + 'static,
{
self.then(MemQ::sort(compare))
}
pub fn sort_by_key<K, F>(self, key: F) -> Self
where
K: Ord,
F: Fn(&T) -> K + Send + Sync + 'static,
{
self.then(MemQ::sort_by_key(key))
}
pub fn unique(self) -> Self {
self.then(MemQ::unique())
}
pub fn unique_by<K, F>(self, key: F) -> Self
where
K: Eq + Hash + Send + Sync + 'static,
F: Fn(&T) -> K + Send + Sync + 'static,
{
self.then(MemQ::unique_by(key))
}
pub fn group_by<K, F>(self, key: F) -> Self
where
K: Eq + Hash + Send + Sync + 'static,
F: Fn(&T) -> K + Send + Sync + 'static,
{
self.then(MemQ::group_by(key))
}
pub fn partition<F>(self, predicate: F) -> Self
where
F: Fn(&T) -> bool + Send + Sync + 'static,
{
self.then(MemQ::partition(predicate))
}
pub fn fold<F>(self, fold: F) -> Self
where
F: Fn(Vec<Arc<T>>) -> Option<Arc<T>> + Send + Sync + 'static,
{
self.then(MemQ::fold(fold))
}
pub fn collect(self) -> Vec<Arc<T>> {
MemQ::apply_all(&self.ops, self.pool.snapshot_unexpired())
}
pub fn iter(self) -> std::vec::IntoIter<Arc<T>> {
self.collect().into_iter()
}
pub fn first(self) -> Option<Arc<T>> {
self.take(1).collect().into_iter().next()
}
pub fn count(self) -> usize {
self.collect().len()
}
pub fn exists(self) -> bool {
self.first().is_some()
}
}
impl<T> PunnuScope<T>
where
T: Cacheable + Clone,
{
pub fn map<F>(self, map: F) -> Self
where
F: Fn(&T) -> T + Send + Sync + 'static,
{
self.then(MemQ::map(map))
}
pub fn flat_map<F>(self, flat_map: F) -> Self
where
F: Fn(&T) -> Vec<T> + Send + Sync + 'static,
{
self.then(MemQ::flat_map(flat_map))
}
pub fn chain_values<I>(self, values: I) -> Self
where
I: IntoIterator<Item = T>,
{
self.then(MemQ::chain_values(values))
}
}