mod ser;
pub use ser::*;
pub use serde_view_macros::View;
use std::{collections::HashSet, hash::Hash};
pub trait ViewFields: Clone + Copy + Hash + PartialEq + Eq {
fn as_str(&self) -> &'static str;
fn from_str(name: &str) -> Option<Self>;
fn from_str_iter<'a>(names: impl IntoIterator<Item = &'a str>) -> HashSet<Self> {
names.into_iter().filter_map(Self::from_str).collect()
}
fn from_str_split(names: &str) -> HashSet<Self> {
Self::from_str_iter(names.split(","))
}
}
pub trait IntoField<VF: ViewFields> {
fn into_field(self) -> Option<VF>;
}
impl<VF: ViewFields> IntoField<VF> for VF {
fn into_field(self) -> Option<VF> {
Some(self)
}
}
impl<VF: ViewFields> IntoField<VF> for &str {
fn into_field(self) -> Option<VF> {
VF::from_str(self)
}
}
pub struct ViewContext<'v, T>
where
T: View,
{
inner: &'v T,
fields: HashSet<T::Fields>,
}
impl<'v, T> ViewContext<'v, T>
where
T: View,
{
pub fn with_fields<I, IF>(mut self, fields: I) -> Self
where
I: IntoIterator<Item = IF>,
IF: IntoField<T::Fields>,
{
self.fields = fields.into_iter().filter_map(|f| f.into_field()).collect();
self
}
pub fn add_fields<I, IF>(mut self, fields: I) -> Self
where
I: IntoIterator<Item = IF>,
IF: IntoField<T::Fields>,
{
self.fields
.extend(fields.into_iter().filter_map(|f| f.into_field()));
self
}
pub fn add_field(mut self, field: impl IntoField<T::Fields>) -> Self {
if let Some(field) = field.into_field() {
self.fields.insert(field);
}
self
}
}
pub trait View: Sized + serde::Serialize {
type Fields: ViewFields;
fn as_view(self: &Self) -> ViewContext<Self> {
ViewContext {
inner: self,
fields: Default::default(),
}
}
}