mod ser;
pub use ser::*;
pub use serde_view_macros::View;
use std::{collections::HashSet, fmt, hash::Hash};
pub trait ViewFields: Clone + Copy + Hash + PartialEq + Eq {
fn as_str(&self) -> &'static str;
fn from_str(name: &str) -> Result<Self>;
fn from_str_iter<'a>(names: impl IntoIterator<Item = &'a str>) -> Result<HashSet<Self>> {
names.into_iter().map(Self::from_str).collect()
}
fn from_str_split(names: &str) -> Result<HashSet<Self>> {
Self::from_str_iter(names.split(','))
}
}
#[derive(Debug, serde::Serialize)]
pub enum Error {
UnknownField(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
pub trait IntoField<VF: ViewFields> {
fn into_field(self) -> Result<VF>;
}
impl<VF: ViewFields> IntoField<VF> for VF {
fn into_field(self) -> Result<VF> {
Ok(self)
}
}
impl<VF: ViewFields> IntoField<VF> for &str {
fn into_field(self) -> Result<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) -> Result<Self>
where
I: IntoIterator<Item = IF>,
IF: IntoField<T::Fields>,
{
self.fields = fields
.into_iter()
.map(|f| f.into_field())
.collect::<Result<_>>()?;
Ok(self)
}
pub fn add_fields<I, IF>(mut self, fields: I) -> Result<Self>
where
I: IntoIterator<Item = IF>,
IF: IntoField<T::Fields>,
{
self.fields.extend(
fields
.into_iter()
.map(|f| f.into_field())
.collect::<Result<HashSet<T::Fields>>>()?,
);
Ok(self)
}
pub fn add_field(mut self, field: impl IntoField<T::Fields>) -> Result<Self> {
self.fields.insert(field.into_field()?);
Ok(self)
}
}
pub trait View: Sized + serde::Serialize {
type Fields: ViewFields;
fn as_view(&self) -> ViewContext<Self> {
ViewContext {
inner: self,
fields: Default::default(),
}
}
}