use super::super::{
super::{annotate::*, normal::*},
errors::*,
resolve::*,
};
use {
kutil::std::error::*,
std::{fmt, str::*},
};
pub fn resolve_from_str<FromStrT, AnnotatedT, ErrorReceiverT>(
variant: Variant<AnnotatedT>,
errors: &mut ErrorReceiverT,
) -> ResolveResult<FromStrT, AnnotatedT>
where
FromStrT: FromStr,
FromStrT::Err: fmt::Display,
AnnotatedT: Annotated + Clone + Default,
ErrorReceiverT: ErrorReceiver<ResolveError<AnnotatedT>>,
{
Ok(match variant {
Variant::Text(text) => match text.inner.parse() {
Ok(parsed) => Some(parsed),
Err(error) => {
errors.give(
MalformedError::new(tynm::type_name::<FromStrT>(), error.to_string()).with_annotations_from(&text),
)?;
None
}
},
_ => {
errors.give(IncompatibleVariantTypeError::new_from(&variant, &["text"]))?;
None
}
})
}
#[macro_export]
macro_rules! impl_resolve_from_str {
( $type:ident $(,)? ) => {
impl<AnnotatedT> $crate::resolve::Resolve<$type, AnnotatedT> for $crate::normal::Variant<AnnotatedT>
where
AnnotatedT: $crate::annotate::Annotated + ::std::clone::Clone + ::std::default::Default,
{
fn resolve_with_errors<ErrorReceiverT>(
self,
errors: &mut ErrorReceiverT,
) -> $crate::resolve::ResolveResult<$type, AnnotatedT>
where
ErrorReceiverT: ::kutil::std::error::ErrorReceiver<$crate::resolve::ResolveError<AnnotatedT>>,
{
$crate::resolve::resolve_from_str(self, errors)
}
}
};
}
#[allow(unused_imports)]
pub use impl_resolve_from_str;
#[derive(Clone, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ResolveFromStr<InnerT> {
pub inner: InnerT,
}
impl<InnerT> ResolveFromStr<InnerT> {
pub fn new(inner: InnerT) -> Self {
Self { inner }
}
}
impl<InnerT, AnnotatedT> Resolve<ResolveFromStr<InnerT>, AnnotatedT> for Variant<AnnotatedT>
where
InnerT: FromStr,
InnerT::Err: fmt::Display,
AnnotatedT: Annotated + Clone + Default,
{
fn resolve_with_errors<ErrorReceiverT>(
self,
errors: &mut ErrorReceiverT,
) -> ResolveResult<ResolveFromStr<InnerT>, AnnotatedT>
where
ErrorReceiverT: ErrorReceiver<ResolveError<AnnotatedT>>,
{
resolve_from_str(self, errors).map(|resolved| resolved.map(ResolveFromStr::new))
}
}
impl<InnerT> AsRef<InnerT> for ResolveFromStr<InnerT> {
fn as_ref(&self) -> &InnerT {
&self.inner
}
}
impl<InnerT> From<InnerT> for ResolveFromStr<InnerT> {
fn from(inner: InnerT) -> Self {
Self::new(inner)
}
}
impl<InnerT> fmt::Display for ResolveFromStr<InnerT>
where
InnerT: fmt::Display,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, formatter)
}
}