pub struct RokCollection<T>(Vec<T>);
#[cfg(feature = "api")]
use crate::api::ApiResponse;
#[cfg(feature = "api")]
impl<T: Serialize> RokCollection<T> {
pub fn to_response(&self) -> ApiResponse {
ApiResponse::ok(&self.0)
}
}
impl<T> RokCollection<T> {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn from_vec(items: Vec<T>) -> Self {
Self(items)
}
}
impl<T> Default for RokCollection<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> From<Vec<T>> for RokCollection<T> {
fn from(v: Vec<T>) -> Self {
Self(v)
}
}
impl<T> From<RokCollection<T>> for Vec<T> {
fn from(c: RokCollection<T>) -> Self {
c.0
}
}
pub trait IntoCollection<T> {
fn into_collection(self) -> RokCollection<T>;
}
impl<T> IntoCollection<T> for Vec<T> {
fn into_collection(self) -> RokCollection<T> {
RokCollection::from_vec(self)
}
}
impl<T> IntoCollection<T> for RokCollection<T> {
fn into_collection(self) -> RokCollection<T> {
self
}
}
impl<T> RokCollection<T> {
pub fn count(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_not_empty(&self) -> bool {
!self.0.is_empty()
}
pub fn items(&self) -> &Vec<T> {
&self.0
}
pub fn to_vec(self) -> Vec<T> {
self.0
}
pub fn first(&self) -> Option<&T> {
self.0.first()
}
pub fn last(&self) -> Option<&T> {
self.0.last()
}
pub fn contains<F>(&self, predicate: F) -> bool
where
F: Fn(&T) -> bool,
{
self.0.iter().any(predicate)
}
pub fn map<U, F>(self, f: F) -> RokCollection<U>
where
F: FnMut(T) -> U,
{
RokCollection(self.0.into_iter().map(f).collect())
}
pub fn map_ref<U, F>(&self, f: F) -> RokCollection<U>
where
F: FnMut(&T) -> U,
{
RokCollection(self.0.iter().map(f).collect())
}
pub fn filter<F>(self, predicate: F) -> Self
where
F: FnMut(&T) -> bool,
{
Self(self.0.into_iter().filter(predicate).collect())
}
pub fn reject<F>(self, mut predicate: F) -> Self
where
F: FnMut(&T) -> bool,
{
self.filter(|x| !predicate(x))
}
pub fn reduce<F>(self, initial: T, f: F) -> T
where
F: Fn(T, T) -> T,
{
self.0.into_iter().fold(initial, f)
}
pub fn fold<A, F>(self, initial: A, f: F) -> A
where
F: FnMut(A, T) -> A,
{
self.0.into_iter().fold(initial, f)
}
pub fn for_each<F>(self, f: F)
where
F: FnMut(T),
{
self.0.into_iter().for_each(f)
}
pub fn sum(self) -> T
where
T: std::ops::Add<Output = T> + Default,
{
self.0.into_iter().fold(T::default(), |a, b| a + b)
}
pub fn avg(self) -> f64
where
T: Into<f64> + Clone,
{
let len = self.0.len();
if len == 0 {
return 0.0;
}
let sum: f64 = self.0.iter().map(|x| x.clone().into()).sum();
sum / len as f64
}
pub fn min(self) -> Option<T>
where
T: Ord,
{
self.0.into_iter().min()
}
pub fn max(self) -> Option<T>
where
T: Ord,
{
self.0.into_iter().max()
}
pub fn take(self, n: usize) -> Self {
let mut vec = self.0;
vec.truncate(n);
Self(vec)
}
pub fn skip(self, n: usize) -> Self {
Self(self.0.into_iter().skip(n).collect())
}
pub fn slice(self, start: usize, length: usize) -> Self {
Self(self.0.into_iter().skip(start).take(length).collect())
}
pub fn chunk(self, size: usize) -> RokCollection<Self> {
let mut chunks = Vec::new();
let mut current = Vec::new();
for item in self.0 {
current.push(item);
if current.len() >= size {
chunks.push(Self(std::mem::take(&mut current)));
}
}
if !current.is_empty() {
chunks.push(Self(current));
}
RokCollection(chunks)
}
pub fn sort_by<F>(mut self, compare: F) -> Self
where
F: FnMut(&T, &T) -> std::cmp::Ordering,
{
self.0.sort_by(compare);
self
}
pub fn sort_by_key<K, F>(mut self, f: F) -> Self
where
F: FnMut(&T) -> K,
K: Ord,
{
self.0.sort_by_key(f);
self
}
pub fn reverse(mut self) -> Self {
self.0.reverse();
self
}
pub fn group_by<K, F>(self, mut f: F) -> RokCollection<(K, Self)>
where
K: Eq + std::hash::Hash,
F: FnMut(&T) -> K,
{
let mut map: std::collections::HashMap<K, Vec<T>> = std::collections::HashMap::new();
for item in self.0 {
let key = f(&item);
map.entry(key).or_default().push(item);
}
RokCollection(map.into_iter().map(|(k, v)| (k, Self(v))).collect())
}
pub fn partition<F>(self, predicate: F) -> (Self, Self)
where
F: FnMut(&T) -> bool,
{
let (a, b): (Vec<T>, Vec<T>) = self.0.into_iter().partition(predicate);
(Self(a), Self(b))
}
pub fn unique(self) -> Self
where
T: Eq + std::hash::Hash + Clone,
{
let mut seen = std::collections::HashSet::new();
Self(
self.0
.into_iter()
.filter(|x| seen.insert(x.clone()))
.collect(),
)
}
pub fn pipe<U, F>(self, f: F) -> U
where
F: FnOnce(Self) -> U,
{
f(self)
}
pub fn tap<F>(self, f: F) -> Self
where
F: FnOnce(&Self),
{
f(&self);
self
}
pub fn join(self, sep: &str) -> String
where
T: ToString,
{
self.0
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(sep)
}
pub fn flatten<U>(self) -> RokCollection<U>
where
T: IntoIterator<Item = U>,
{
RokCollection(self.0.into_iter().flat_map(|x| x).collect())
}
}