use newtype::NewType;
use serde::Deserialize;
#[macro_export]
macro_rules! define_num_serde {
($name:ident, $inner_type:ty) => {
#[derive(NewType, Clone, Deserialize, Copy)]
pub struct $name<const N: $inner_type>(pub $inner_type);
impl<const N: $inner_type> ::std::fmt::Debug for $name<N> {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
impl<const N: $inner_type> PartialEq for $name<N> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<const N: $inner_type> PartialEq<$inner_type> for $name<N> {
fn eq(&self, other: &$inner_type) -> bool {
&self.0 == other
}
}
impl<const N: $inner_type> Eq for $name<N> {}
impl<const N: $inner_type> PartialOrd for $name<N> {
fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<const N: $inner_type> PartialOrd<$inner_type> for $name<N> {
fn partial_cmp(&self, other: &$inner_type) -> ::std::option::Option<::std::cmp::Ordering> {
self.0.partial_cmp(other)
}
}
impl<const N: $inner_type> Ord for $name<N> {
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<const N: $inner_type> Default for $name<N> {
fn default() -> Self {
Self(N)
}
}
impl<const N: $inner_type> ::std::fmt::Display for $name<N> {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
define_num_serde!(NumberUsize, usize);
define_num_serde!(NumberU32, u32);
define_num_serde!(NumberU64, u64);
define_num_serde!(NumberU16, u16);
define_num_serde!(NumberU8, u8);
define_num_serde!(NumberI32, i32);
define_num_serde!(NumberI64, i64);
define_num_serde!(NumberI16, i16);
define_num_serde!(NumberI8, i8);
define_num_serde!(NumberBool, bool);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_case_number_deserialize() {
assert_eq!(serde_json::from_str::<NumberUsize<1500>>("123").unwrap(), 123); assert!(serde_json::from_str::<NumberUsize<1500>>("123").unwrap() < 124);
assert_eq!(
*serde_json::from_str::<NumberUsize<1500>>("xxx").unwrap_or_default(),
1500
);
}
#[test]
fn test_case_number_u32_deserialize() {
assert_eq!(*serde_json::from_str::<NumberU32<500>>("123").unwrap(), 123);
assert_eq!(*serde_json::from_str::<NumberU32<500>>("xxx").unwrap_or_default(), 500);
}
#[test]
fn test_case_number_u64_deserialize() {
assert_eq!(*serde_json::from_str::<NumberU64<5000>>("1234").unwrap(), 1234);
assert_eq!(
*serde_json::from_str::<NumberU64<5000>>("xxx").unwrap_or_default(),
5000
);
}
#[test]
fn test_case_number_u16_deserialize() {
assert_eq!(*serde_json::from_str::<NumberU16<300>>("100").unwrap(), 100);
assert_eq!(*serde_json::from_str::<NumberU16<300>>("xxx").unwrap_or_default(), 300);
}
#[test]
fn test_case_number_u8_deserialize() {
assert_eq!(*serde_json::from_str::<NumberU8<200>>("50").unwrap(), 50);
assert_eq!(*serde_json::from_str::<NumberU8<200>>("xxx").unwrap_or_default(), 200);
}
#[test]
fn test_case_number_i32_deserialize() {
assert_eq!(*serde_json::from_str::<NumberI32<-100>>("42").unwrap(), 42);
assert_eq!(
*serde_json::from_str::<NumberI32<-100>>("xxx").unwrap_or_default(),
-100
);
}
#[test]
fn test_case_number_i64_deserialize() {
assert_eq!(*serde_json::from_str::<NumberI64<-5000>>("999").unwrap(), 999);
assert_eq!(
*serde_json::from_str::<NumberI64<-5000>>("xxx").unwrap_or_default(),
-5000
);
}
#[test]
fn test_case_number_i16_deserialize() {
assert_eq!(*serde_json::from_str::<NumberI16<-50>>("25").unwrap(), 25);
assert_eq!(*serde_json::from_str::<NumberI16<-50>>("xxx").unwrap_or_default(), -50);
}
#[test]
fn test_case_number_i8_deserialize() {
assert_eq!(*serde_json::from_str::<NumberI8<-10>>("5").unwrap(), 5);
assert_eq!(*serde_json::from_str::<NumberI8<-10>>("xxx").unwrap_or_default(), -10);
}
#[test]
fn test_case_number_bool_deserialize() {
assert_eq!(*serde_json::from_str::<NumberBool<true>>("false").unwrap(), false);
assert_eq!(
*serde_json::from_str::<NumberBool<true>>("xxx").unwrap_or_default(),
true
);
}
#[test]
fn test_case_number_display_and_debug() {
let usize_val = NumberUsize::<1500>::from(123);
assert_eq!(usize_val.to_string(), "123");
assert_eq!(format!("{:?}", usize_val), "123");
let u32_val = NumberU32::<500>::from(100);
assert_eq!(u32_val.to_string(), "100");
assert_eq!(format!("{:?}", u32_val), "100");
let u64_val = NumberU64::<5000>::from(1000);
assert_eq!(u64_val.to_string(), "1000");
assert_eq!(format!("{:?}", u64_val), "1000");
let u16_val = NumberU16::<300>::from(200);
assert_eq!(u16_val.to_string(), "200");
assert_eq!(format!("{:?}", u16_val), "200");
let u8_val = NumberU8::<200>::from(150);
assert_eq!(u8_val.to_string(), "150");
assert_eq!(format!("{:?}", u8_val), "150");
let i32_val = NumberI32::<-100>::from(42);
assert_eq!(i32_val.to_string(), "42");
assert_eq!(format!("{:?}", i32_val), "42");
let i64_val = NumberI64::<-5000>::from(999);
assert_eq!(i64_val.to_string(), "999");
assert_eq!(format!("{:?}", i64_val), "999");
let i16_val = NumberI16::<-50>::from(25);
assert_eq!(i16_val.to_string(), "25");
assert_eq!(format!("{:?}", i16_val), "25");
let i8_val = NumberI8::<-10>::from(5);
assert_eq!(i8_val.to_string(), "5");
assert_eq!(format!("{:?}", i8_val), "5");
let bool_val = NumberBool::<true>::from(false);
assert_eq!(bool_val.to_string(), "false");
assert_eq!(format!("{:?}", bool_val), "false");
}
}