use std::borrow::Cow;
use crate::error::{Result, Error, ErrorKind};
use crate::value::Spectrum;
pub trait IntoProp<'d> {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>>;
}
pub trait FromProp: Sized {
fn from_prop(values: &Spectrum<str>) -> Result<Self>;
}
macro_rules! impl_prop_for_parse {
( $ty:ty ) => {
impl<'d> IntoProp<'d> for $ty {
#[inline]
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
Some(Cow::<str>::Owned(format!("{self}")))
}
}
impl<'d> IntoProp<'d> for &'_ $ty {
#[inline]
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
(*self).into_prop()
}
}
impl FromProp for $ty {
fn from_prop(values: &Spectrum<str>) -> Result<Self> {
match values.len() {
0 => Err(Error::new(ErrorKind::InvalidProp)
.with_description(concat!("No value in the property, could not convert it to ", stringify!($ty)))),
1 => values.iter().next().expect("one value").parse::<$ty>()
.map_err(|e| Error::new(ErrorKind::InvalidProp)
.with_description(concat!("Failed to parse property value to ", stringify!($ty)))
.with_source(Box::new(e))),
2.. => Err(Error::new(ErrorKind::InvalidProp)
.with_description(concat!("More than one value in the property, could not convert it to ", stringify!($ty)))),
}
}
}
impl FromProp for Vec<$ty> {
fn from_prop(values: &Spectrum<str>) -> Result<Self> {
let mut ret = Vec::with_capacity(values.len());
for val in values.iter() {
ret.push(val.parse::<$ty>()
.map_err(|e| Error::new(ErrorKind::InvalidProp)
.with_description(concat!("Failed to parse property value to ", stringify!($ty)))
.with_source(Box::new(e)))?);
}
Ok(ret)
}
}
};
}
impl_prop_for_parse!(bool);
impl_prop_for_parse!(u8);
impl_prop_for_parse!(i8);
impl_prop_for_parse!(u16);
impl_prop_for_parse!(i16);
impl_prop_for_parse!(u32);
impl_prop_for_parse!(i32);
impl_prop_for_parse!(u64);
impl_prop_for_parse!(i64);
impl_prop_for_parse!(f32);
impl_prop_for_parse!(f64);
impl<'d> IntoProp<'d> for Cow<'d, str> {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
Some(self)
}
}
impl<'d> IntoProp<'d> for &'d str {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
Cow::<str>::Borrowed(self).into_prop()
}
}
impl<'d> IntoProp<'d> for String {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
Cow::<str>::Owned(self).into_prop()
}
}
impl<'d> IntoProp<'d> for Vec<String> {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
self.into_iter().map(Cow::Owned)
}
}
impl<'d> IntoProp<'d> for &'d String {
fn into_prop(self) -> impl IntoIterator<Item = Cow<'d, str>> {
Cow::<str>::Borrowed(self).into_prop()
}
}
impl FromProp for String {
fn from_prop(values: &Spectrum<str>) -> Result<Self> {
let mut buf = String::new();
for val in values.iter() {
if !buf.is_empty() {
buf.push('\n');
}
buf.push_str(val);
}
Ok(buf)
}
}
impl FromProp for Vec<String> {
fn from_prop(values: &Spectrum<str>) -> Result<Self> {
Ok(values.iter().map(str::to_string).collect())
}
}
impl FromProp for Spectrum<str> {
fn from_prop(values: &Spectrum<str>) -> Result<Self> {
Ok(values.clone())
}
}