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