1use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor};
2
3#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
27pub enum Number {
28 UnsignedInt(u64),
29 SignedInt(i64),
30 Float(f64),
31}
32
33impl Number {
34 pub fn as_unsigned_int(&self) -> Option<u64> {
35 match self {
36 Number::UnsignedInt(v) => Some(*v),
37 _ => None,
38 }
39 }
40 pub fn as_signed_int(&self) -> Option<i64> {
41 match self {
42 Number::SignedInt(v) => Some(*v),
43 _ => None,
44 }
45 }
46 pub fn as_float(&self) -> Option<f64> {
47 match self {
48 Number::Float(v) => Some(*v),
49 _ => None,
50 }
51 }
52}
53
54macro_rules! impl_from_num {
55 ($from:ident,$ty:path,$cast:path) => {
56 impl From<$from> for Number {
57 fn from(value: $from) -> Self {
58 $ty(value as $cast)
59 }
60 }
61 };
62}
63
64impl_from_num!(u8, Number::UnsignedInt, u64);
65impl_from_num!(u16, Number::UnsignedInt, u64);
66impl_from_num!(u32, Number::UnsignedInt, u64);
67impl_from_num!(u64, Number::UnsignedInt, u64);
68impl_from_num!(i8, Number::SignedInt, i64);
69impl_from_num!(i16, Number::SignedInt, i64);
70impl_from_num!(i32, Number::SignedInt, i64);
71impl_from_num!(i64, Number::SignedInt, i64);
72impl_from_num!(f32, Number::Float, f64);
73impl_from_num!(f64, Number::Float, f64);
74
75impl Serialize for Number {
76 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
77 where
78 S: Serializer,
79 {
80 match self {
81 Number::UnsignedInt(n) => serializer.serialize_u64(*n),
82 Number::SignedInt(n) => serializer.serialize_i64(*n),
83 Number::Float(n) => serializer.serialize_f64(*n),
84 }
85 }
86}
87
88impl<'de> Deserialize<'de> for Number {
89 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
90 where
91 D: Deserializer<'de>,
92 {
93 struct NumberVisitor;
94 impl Visitor<'_> for NumberVisitor {
95 type Value = Number;
96 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
97 formatter.write_str("a number")
98 }
99
100 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
101 where
102 E: serde::de::Error,
103 {
104 Ok(Number::UnsignedInt(v))
105 }
106
107 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
108 where
109 E: serde::de::Error,
110 {
111 Ok(Number::SignedInt(v))
112 }
113
114 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
115 where
116 E: serde::de::Error,
117 {
118 Ok(Number::Float(v))
119 }
120 }
121
122 deserializer.deserialize_any(NumberVisitor)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use crate::from_slice;
130 use rstest::rstest;
131
132 #[rstest]
133 #[case([0x05],5)]
134 #[case([0xcd, 0xff, 0xff],u16::MAX.into())]
135 #[case([0xce, 0xff, 0xff,0xff,0xff],u32::MAX.into())]
136 #[case([0xcf, 0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff],u64::MAX)]
137 fn decode_unsigned_int<Buf: AsRef<[u8]>>(#[case] input: Buf, #[case] expected: u64) {
138 let num = from_slice::<Number>(input.as_ref()).unwrap();
139 assert_eq!(num, Number::UnsignedInt(expected));
140 }
141
142 #[rstest]
143 #[case([0xe0],-32)]
144 #[case([0xd0, 0x7f],i8::MAX.into())]
145 #[case([0xd1, 0x7f, 0xff],i16::MAX.into())]
146 #[case([0xd2, 0x80, 0x00, 0x00, 0x00],i32::MIN.into())]
147 #[case([0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],i64::MAX)]
148 fn decode_signed_int<Buf: AsRef<[u8]>>(#[case] input: Buf, #[case] expected: i64) {
149 let num = from_slice::<Number>(input.as_ref()).unwrap();
150 assert_eq!(num, Number::SignedInt(expected));
151 }
152
153 #[rstest]
154 #[case([0xca, 0x42, 0xf6, 0xe9, 0x79],123.456)]
155 #[case([0xcb, 0x40, 0xfe, 0x24, 0x0c, 0x9f, 0xcb, 0x0c, 0x02],123456.789012)]
156 fn decode_float<Buf: AsRef<[u8]>>(#[case] input: Buf, #[case] expected: f64) {
157 let num = from_slice::<Number>(input.as_ref()).unwrap();
158 match num {
159 Number::Float(n) => {
160 let diff = (n - expected).abs();
161 assert!(diff < (1e-5))
162 }
163 _ => {
164 panic!("Err")
165 }
166 }
167 }
168}