use std::{
ffi::OsString,
net::{Ipv4Addr, SocketAddrV4},
path::PathBuf,
};
use crate::{ArgError, FromRead, Reader, Result};
use super::ReadFmt;
pub trait SetFromRead {
fn set_from_read<'a>(
&mut self,
r: &mut Reader,
fmt: &'a ReadFmt<'a>,
) -> Result<Option<ArgError>>;
}
pub trait AutoSetFromRead: FromRead {}
impl<T: AutoSetFromRead> SetFromRead for T {
fn set_from_read<'a>(
&mut self,
r: &mut Reader,
fmt: &'a ReadFmt<'a>,
) -> Result<Option<ArgError>> {
let err;
(*self, err) = Self::from_read(r, fmt)?;
Ok(err)
}
}
macro_rules! impl_set_from_read {
($($t:ident),* $(,)?) => {
$(impl AutoSetFromRead for $t {})*
};
}
impl_set_from_read!(
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
isize,
i128,
f32,
f64,
bool,
char,
Ipv4Addr,
SocketAddrV4,
OsString,
PathBuf,
);
impl SetFromRead for String {
fn set_from_read<'a>(
&mut self,
r: &mut Reader,
fmt: &'a ReadFmt<'a>,
) -> Result<Option<ArgError>> {
r.trim_left(fmt)?;
let (min, max) = fmt.length_range().unwrap_or((0, usize::MAX));
self.clear();
r.read_to(self, min)?;
if self.len() < min {
return r
.err_parse(format!(
"Expected at least `{min}` characters but there were only \
`{}` characters.",
self.len()
))
.err();
}
r.read_to(self, max - min)?;
if let Some((t, ch)) = fmt.trim()
&& t.right()
{
let s = if let Some(c) = ch {
self[min..].trim_end_matches(c)
} else {
self[min..].trim_ascii_end()
};
self.replace_range(min + s.len().., "");
}
Ok(Some(r.err_parse(format!(
"String is too long. Expected at most `{max}` characters."
))))
}
}