use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
pub struct CommaSeparated<T> {
values: Vec<T>,
}
impl<T> CommaSeparated<T> {
pub fn new(values: Vec<T>) -> Self {
Self { values }
}
pub fn values(&self) -> &[T] {
&self.values
}
pub fn values_mut(&mut self) -> &mut Vec<T> {
&mut self.values
}
pub fn into_inner(self) -> Vec<T> {
self.values
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn push(&mut self, value: T) {
self.values.push(value);
}
pub fn contains(&self, value: &T) -> bool
where
T: PartialEq,
{
self.values.contains(value)
}
}
impl<T: FromStr> CommaSeparated<T>
where
T::Err: fmt::Debug,
{
pub fn from_string(s: &str) -> Self {
let values = s
.split(',')
.filter(|s| !s.is_empty())
.filter_map(|s| s.trim().parse().ok())
.collect();
Self { values }
}
}
impl<T> From<Vec<T>> for CommaSeparated<T> {
fn from(values: Vec<T>) -> Self {
Self::new(values)
}
}
impl<T> FromIterator<T> for CommaSeparated<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
values: iter.into_iter().collect(),
}
}
}
impl<T> IntoIterator for CommaSeparated<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.values.into_iter()
}
}
impl<'a, T> IntoIterator for &'a CommaSeparated<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.values.iter()
}
}
impl<T: Serialize> Serialize for CommaSeparated<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.values.serialize(serializer)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for CommaSeparated<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Vec::<T>::deserialize(deserializer).map(|v| Self { values: v })
}
}
impl<T: Default> Default for CommaSeparated<T> {
fn default() -> Self {
Self { values: Vec::new() }
}
}
impl<T: fmt::Display> fmt::Display for CommaSeparated<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = self
.values
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(",");
write!(f, "{}", s)
}
}
impl<T: Clone> Clone for CommaSeparated<T> {
fn clone(&self) -> Self {
Self {
values: self.values.clone(),
}
}
}
impl<T: fmt::Debug> fmt::Debug for CommaSeparated<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CommaSeparated")
.field("values", &self.values)
.finish()
}
}
impl<T: PartialEq> PartialEq for CommaSeparated<T> {
fn eq(&self, other: &Self) -> bool {
self.values == other.values
}
}
impl<T: Eq> Eq for CommaSeparated<T> {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Collection<T> {
items: Vec<T>,
}
impl<T> Collection<T> {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn from_vec(items: Vec<T>) -> Self {
Self { items }
}
pub fn all(&self) -> &[T] {
&self.items
}
pub fn first(&self) -> Option<&T> {
self.items.first()
}
pub fn last(&self) -> Option<&T> {
self.items.last()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn count(&self) -> usize {
self.items.len()
}
pub fn add(&mut self, item: T) {
self.items.push(item);
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index < self.items.len() {
Some(self.items.remove(index))
} else {
None
}
}
pub fn filter<F: Fn(&T) -> bool>(&self, predicate: F) -> Self
where
T: Clone,
{
Self {
items: self
.items
.iter()
.filter(|i| predicate(i))
.cloned()
.collect(),
}
}
pub fn map<U, F: Fn(&T) -> U>(&self, mapper: F) -> Collection<U> {
Collection {
items: self.items.iter().map(mapper).collect(),
}
}
pub fn find<F: Fn(&T) -> bool>(&self, predicate: F) -> Option<&T> {
self.items.iter().find(|i| predicate(i))
}
pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
self.items.iter().any(predicate)
}
pub fn every<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
self.items.iter().all(predicate)
}
pub fn pluck<U, F: Fn(&T) -> U>(&self, extractor: F) -> Vec<U> {
self.items.iter().map(extractor).collect()
}
pub fn sorted<F: FnMut(&T, &T) -> std::cmp::Ordering>(&self, compare: F) -> Self
where
T: Clone,
{
let mut items = self.items.clone();
items.sort_by(compare);
Self { items }
}
pub fn take(&self, n: usize) -> Self
where
T: Clone,
{
Self {
items: self.items.iter().take(n).cloned().collect(),
}
}
pub fn skip(&self, n: usize) -> Self
where
T: Clone,
{
Self {
items: self.items.iter().skip(n).cloned().collect(),
}
}
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.items.clone()
}
pub fn into_inner(self) -> Vec<T> {
self.items
}
}
impl<T> From<Vec<T>> for Collection<T> {
fn from(items: Vec<T>) -> Self {
Self::from_vec(items)
}
}
impl<T> Default for Collection<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> FromIterator<T> for Collection<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
items: iter.into_iter().collect(),
}
}
}
impl<T> IntoIterator for Collection<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<'a, T> IntoIterator for &'a Collection<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.items.iter()
}
}
impl<T: Serialize> Serialize for Collection<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.items.serialize(serializer)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Collection<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Vec::<T>::deserialize(deserializer).map(|v| Self { items: v })
}
}