use std::{ops::Deref, str::FromStr};
#[derive(Clone, Debug, PartialEq)]
#[repr(transparent)]
pub struct Number<InnerT>(InnerT);
impl<InnerT> Deref for Number<InnerT> {
type Target = InnerT;
fn deref(&self) -> &InnerT {
&self.0
}
}
impl<InnerT> std::fmt::Display for Number<InnerT>
where
InnerT: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{}", &self.0)
}
}
impl<InnerT> FromStr for Number<InnerT>
where
InnerT: FromStr,
InnerT::Err: std::fmt::Debug,
{
type Err = InnerT::Err;
fn from_str(input: &str) -> Result<Self, Self::Err> {
Ok(Self(input.parse()?))
}
}
#[cfg(feature = "serde")]
mod serde {
use super::Number;
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
impl<InnerT> Serialize for Number<InnerT>
where
InnerT: std::fmt::Display,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
String::serialize(&self.to_string(), serializer)
}
}
impl<'de, InnerT> Deserialize<'de> for Number<InnerT>
where
InnerT: std::str::FromStr,
InnerT::Err: std::fmt::Debug,
{
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s = String::deserialize(d)?;
s.parse().map_err(|e| D::Error::custom(format!("{e:?}")))
}
}
}
#[cfg(test)]
mod tests {
use super::Number;
use crate::control::{def_failing_parse_test, def_parse_test};
def_failing_parse_test!(fail_empty, Number<usize>, "");
def_failing_parse_test!(fail_neg_one, Number<usize>, "-1");
def_parse_test!(parse_zero, Number<usize>, "0", Number::<usize>(0));
def_parse_test!(parse_one, Number<usize>, "1", Number::<usize>(1));
def_parse_test!(parse_neg_one, Number<i32>, "-1", Number::<i32>(-1));
}