use crate::*;
pub trait FromPartial<T>: Sized {
fn from(partial: T) -> Result<Self>;
fn from_option(partial: Option<T>, error_missing: &str) -> Result<Self> {
partial
.map(Self::from)
.transpose()?
.ok_or_else(|| syn::Error::new(Span::call_site(), error_missing))
}
fn join(
first: Option<SpannedValue<T>>,
second: SpannedValue<T>,
specified_twice_error: &str,
) -> Result<Option<SpannedValue<T>>> {
if let Some(first) = first {
if let Some(span) = first
.span()
.span_joined()
.and_then(|s| Some((s, second.span().span_joined()?)))
.and_then(|(a, b)| a.join(b))
{
Err(Error::new(span, specified_twice_error))
} else {
let mut error = Error::new(first.span().start, specified_twice_error);
error.combine(Error::new(second.span().start, specified_twice_error));
Err(error)
}
} else {
Ok(Some(second))
}
}
}
impl<T> FromPartial<T> for T {
fn from(partial: T) -> Result<Self> {
Ok(partial)
}
}
#[derive(Clone)]
pub struct Defaulting<T>(pub T);
impl<P, T: Default + FromPartial<P>> FromPartial<Defaulting<P>> for T {
fn from(partial: Defaulting<P>) -> Result<Self> {
Self::from(partial.0)
}
fn from_option(partial: Option<Defaulting<P>>, _error: &str) -> Result<Self> {
partial
.map(|d| Self::from(d.0))
.transpose()
.map(Option::unwrap_or_default)
}
}
pub struct Partial<T>(pub T);