use std::{
convert::{From as FromTrait, Infallible},
default::Default as DefaultTrait,
ffi::OsString,
str::FromStr as FromStrTrait,
};
use crate::error;
#[derive(Debug, Default)]
pub struct FromStr<T>(pub T);
#[derive(Debug, Default)]
pub struct From<T>(pub T);
#[derive(Debug, Default)]
pub struct IntoString(pub String);
#[derive(Debug, Default)]
pub struct Default<T>(pub T);
pub trait Parser
where
Self: Sized,
{
type ErrorUnset: error::Unset;
type ErrorParse;
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>>;
}
impl<T> Parser for Option<T>
where
T: Parser,
{
type ErrorParse = T::ErrorParse;
type ErrorUnset = Infallible;
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>> {
match T::parse(input) {
Ok(x) => Ok(Some(x)),
Err(e) => match e {
error::Value::Unset(_) => Ok(None),
error::Value::Parse(e) => Err(error::Value::Parse(e)),
},
}
}
}
impl<T> Parser for FromStr<T>
where
T: FromStrTrait,
{
type ErrorParse = error::FromStr<T::Err>;
type ErrorUnset = ();
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>> {
let input = input.ok_or(error::Value::Unset(()))?;
let Some(str) = input.to_str() else {
return Err(error::Value::Parse(error::FromStr::Convert(input)));
};
T::from_str(str)
.map(Self)
.map_err(|e| error::Value::Parse(error::FromStr::Parse(e)))
}
}
impl Parser for IntoString {
type ErrorParse = OsString;
type ErrorUnset = ();
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>> {
input
.ok_or(error::Value::Unset(()))?
.into_string()
.map(Self)
.map_err(error::Value::Parse)
}
}
impl<T> Parser for From<T>
where
T: FromTrait<OsString>,
{
type ErrorParse = Infallible;
type ErrorUnset = ();
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>> {
let input = input.ok_or(error::Value::Unset(()))?;
Ok(Self(T::from(input)))
}
}
impl<T> Parser for Default<T>
where
T: Parser + DefaultTrait,
{
type ErrorParse = T::ErrorParse;
type ErrorUnset = Infallible;
fn parse(
input: Option<OsString>,
) -> Result<Self, error::Value<Self::ErrorUnset, Self::ErrorParse>> {
match T::parse(input) {
Ok(x) => Ok(Self(x)),
Err(e) => match e {
error::Value::Unset(_) => Ok(Self(T::default())),
error::Value::Parse(e) => Err(error::Value::Parse(e)),
},
}
}
}