use crate::{Error, Result};
pub trait Value: Sized {
fn new(value: &str) -> Result<Self>;
fn update(&mut self, value: &str) -> Result<()> {
*self = Self::new(value)?;
Ok(())
}
}
macro_rules! impl_value_by_parse {
($t:ty) => {
impl Value for $t {
fn new(value: &str) -> Result<Self> {
value.parse().map_err(Error::custom)
}
}
};
($($t:ty,)*) => {
$(impl_value_by_parse! { $t })*
};
}
mod core_impl {
use super::*;
impl_value_by_parse! {
bool, char,
f32, f64,
i8, i16, i32, i64, isize,
u8, u16, u32, u64, usize,
core::net::IpAddr, core::net::Ipv4Addr, core::net::Ipv6Addr,
core::net::SocketAddr, core::net::SocketAddrV4, core::net::SocketAddrV6,
core::num::NonZero<i8>, core::num::NonZero<i16>,
core::num::NonZero<i32>, core::num::NonZero<i64>,
core::num::NonZero<i128>, core::num::NonZero<isize>,
core::num::NonZero<u8>, core::num::NonZero<u16>,
core::num::NonZero<u32>, core::num::NonZero<u64>,
core::num::NonZero<u128>, core::num::NonZero<usize>,
}
impl<T> Value for Option<T>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
T::new(value).map(Some)
}
}
}
mod alloc_impl {
use super::*;
use alloc::string::String;
impl Value for String {
fn new(value: &str) -> Result<Self> {
Ok(String::from(value))
}
}
}
#[cfg(feature = "std")]
mod std_impl {
use super::*;
use std::ffi::OsString;
use std::path::PathBuf;
impl Value for OsString {
fn new(value: &str) -> Result<Self> {
Ok(OsString::from(value))
}
}
impl Value for PathBuf {
fn new(value: &str) -> Result<Self> {
Ok(PathBuf::from(value))
}
}
}
#[cfg(feature = "module")]
mod module_impl {
use super::*;
use module::types::*;
impl<T> Value for First<T>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
T::new(value).map(First)
}
}
impl<T> Value for Last<T>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
T::new(value).map(Last)
}
}
impl Value for Lines {
fn new(value: &str) -> Result<Self> {
Ok(Lines::new(value))
}
}
impl<T> Value for NoMerge<T>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
T::new(value).map(Self)
}
}
impl<T> Value for Ordered<T>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
let err = match T::new(value) {
Ok(x) => return Ok(Ordered::new(x)),
Err(e) => e,
};
if let Some(value) = value.strip_prefix(':') {
T::new(value).map(|x| Ordered::with_order(x, ordered::Order::After))
} else if let Some(value) = value.strip_suffix(':') {
T::new(value).map(|x| Ordered::with_order(x, ordered::Order::Before))
} else {
Err(err)
}
}
}
impl<T, const DEFAULT: isize> Value for Overridable<T, DEFAULT>
where
T: Value,
{
fn new(value: &str) -> Result<Self> {
let err = match T::new(value) {
Ok(x) => return Ok(Overridable::new(x)),
Err(e) => e,
};
let Some((priority, value)) = value.split_once(':') else {
return Err(err);
};
let priority = priority
.trim()
.parse::<isize>()
.map(overridable::Priority::from)
.map_err(|e| Error::custom(format_args!("invalid priority: {e}")))?;
let value = T::new(value)?;
Ok(Overridable::with_priority(value, priority))
}
}
}