use std::{
borrow::Cow,
ffi::{OsStr, OsString},
net::{
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6,
},
path::{Path, PathBuf},
rc::Rc,
str::FromStr,
sync::Arc,
};
use crate::{
err::{ArgError, Result},
impl_all::impl_all,
};
pub trait FromArg<'a>: Sized {
fn from_arg(arg: &'a str) -> Result<Self>;
fn from_os_arg(arg: &'a OsStr) -> Result<Self> {
Self::from_arg(arg.to_str().ok_or(ArgError::invalid_unicode(arg))?)
}
}
pub trait FromArgStr: FromStr<Err = ArgError> {}
impl<T> FromArg<'_> for T
where
T: FromArgStr,
{
#[inline]
fn from_arg(arg: &str) -> Result<Self> {
T::from_str(arg)
}
}
impl_all! { impl<'a> FromArg<'a>:
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64, usize, isize,
bool, char, String, PathBuf, OsString, IpAddr, SocketAddr, Ipv4Addr,
Ipv6Addr, SocketAddrV4, SocketAddrV6 => {
#[inline(always)]
fn from_arg(arg: &'a str) -> Result<Self> {
Self::from_str(arg).map_err(|e| {
ArgError::failed_to_parse(
e.to_string(), arg
)
})
}
}
}
impl<'a> FromArg<'a> for &'a str {
#[inline(always)]
fn from_arg(arg: &'a str) -> Result<Self> {
Ok(arg)
}
}
impl<'a> FromArg<'a> for &'a Path {
#[inline(always)]
fn from_arg(arg: &'a str) -> Result<Self> {
Ok(Path::new(arg))
}
}
impl<'a> FromArg<'a> for &'a OsStr {
#[inline(always)]
fn from_arg(arg: &'a str) -> Result<Self> {
Ok(OsStr::new(arg))
}
}
impl_all! { impl<'a> FromArg<'a>:
Arc<str>, Rc<str>, Cow<'a, str> => {
#[inline(always)]
fn from_arg(arg: &'a str) -> Result<Self> {
Ok(arg.into())
}
}
}
impl<'a, T> FromArg<'a> for Option<T>
where
T: FromArg<'a>,
{
#[inline]
fn from_arg(arg: &'a str) -> Result<Self> {
if arg.is_empty() {
Ok(None)
} else {
Ok(Some(T::from_arg(arg)?))
}
}
}