messagepack_serde/value/
number.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor};
2
3/// Represents any number, it could be int or float.
4///
5/// ## Example
6///
7/// ```rust
8/// use serde::{Deserialize, Serialize};
9/// use messagepack_serde::{from_slice,value::Number};
10/// #[derive(Debug, Serialize, Deserialize, PartialEq)]
11/// struct Data{
12///     num: Number
13/// }
14/// let buf:&[u8] = &[0x81,0xa3,0x6e,0x75,0x6d,0x01]; // {"num":1}
15/// let data = from_slice::<Data>(buf).unwrap();
16/// assert_eq!(data.num,Number::UnsignedInt(1));
17///
18/// let buf:&[u8] = &[0x81,0xa3,0x6e,0x75,0x6d,0xd0,0x85]; // {"num":-123}
19/// let data = from_slice::<Data>(buf).unwrap();
20/// assert_eq!(data.num,Number::SignedInt(-123));
21///
22/// let buf:&[u8] = &[0x81,0xa3,0x6e,0x75,0x6d,0xcb,0x3f,0xf8,0x00,0x00,0x00,0x00,0x00,0x00]; // {"num":1.5}
23/// let data = from_slice::<Data>(buf).unwrap();
24/// assert_eq!(data.num,Number::Float(1.5));
25/// ```
26#[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}