sonic_rs/serde/rawnumber.rs
1use ::serde::{
2 de, de::Visitor, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer,
3};
4use ::std::fmt;
5use faststr::FastStr;
6
7use super::number::Number;
8use crate::{util::private::Sealed, Error, JsonNumberTrait};
9
10/// Represents a JSON number with arbitrary precision, the underlying representation of a string,
11/// like as Golang `json.Number`.
12///
13/// Example1:
14///
15/// ```
16/// use sonic_rs::RawNumber;
17///
18/// use crate::sonic_rs::JsonNumberTrait;
19///
20/// // RawNumber can be parsed from a JSON number text.
21/// let num: RawNumber = sonic_rs::from_str("123").unwrap();
22/// assert_eq!(num.as_i64(), Some(123));
23/// assert_eq!(num.as_str(), "123");
24///
25/// // RawNumber can be parsed from a JSON string text that contains a number.
26/// let num: RawNumber =
27/// sonic_rs::from_str("\"1.2333333333333333333333333333333333333333\"").unwrap();
28/// assert_eq!(num.as_f64(), Some(1.2333333333333334));
29/// assert_eq!(num.as_str(), "1.2333333333333333333333333333333333333333");
30/// ```
31#[derive(Clone, PartialEq, Eq, Hash, Debug)]
32pub struct RawNumber {
33 n: FastStr,
34}
35
36impl RawNumber {
37 pub(crate) fn new(s: &str) -> Self {
38 Self { n: FastStr::new(s) }
39 }
40
41 pub(crate) fn from_faststr(n: FastStr) -> Self {
42 Self { n }
43 }
44
45 /// as_str returns the underlying string representation of the number.
46 pub fn as_str(&self) -> &str {
47 self.n.as_str()
48 }
49}
50
51pub(crate) const TOKEN: &str = "$sonic_rs::private::JsonNumber";
52
53impl<'de> Deserialize<'de> for RawNumber {
54 #[inline]
55 fn deserialize<D>(deserializer: D) -> Result<RawNumber, D::Error>
56 where
57 D: Deserializer<'de>,
58 {
59 struct JsonNumberVisitor;
60
61 impl<'de> Visitor<'de> for JsonNumberVisitor {
62 type Value = RawNumber;
63
64 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
65 formatter.write_str("a JSON number")
66 }
67
68 fn visit_borrowed_str<E>(self, raw: &'de str) -> Result<Self::Value, E>
69 where
70 E: de::Error,
71 {
72 Ok(RawNumber::new(raw))
73 }
74 }
75
76 deserializer.deserialize_newtype_struct(TOKEN, JsonNumberVisitor)
77 }
78}
79
80impl Serialize for RawNumber {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 let mut s = serializer.serialize_struct(TOKEN, 1)?;
86 s.serialize_field(TOKEN, &self.n)?;
87 s.end()
88 }
89}
90
91impl Sealed for RawNumber {}
92
93impl JsonNumberTrait for RawNumber {
94 /// Returns true if the `Number` is an integer between `i64::MIN` and
95 /// `i64::MAX`.
96 ///
97 /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
98 /// return the integer value.
99 #[inline]
100 fn is_i64(&self) -> bool {
101 self.as_i64().is_some()
102 }
103
104 /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
105 ///
106 /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
107 /// return the integer value.
108 #[inline]
109 fn is_u64(&self) -> bool {
110 self.as_u64().is_some()
111 }
112
113 /// Returns true if the `Number` can be represented by f64.
114 ///
115 /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
116 /// return the floating point value.
117 ///
118 /// Currently this function returns true if and only if both `is_i64` and
119 /// `is_u64` return false but this is not a guarantee in the future.
120 #[inline]
121 fn is_f64(&self) -> bool {
122 self.as_f64().is_some()
123 }
124
125 /// If the `Number` is an integer, represent it as i64 if possible. Returns
126 /// None otherwise.
127 #[inline]
128 fn as_i64(&self) -> Option<i64> {
129 self.n.parse().ok()
130 }
131
132 /// If the `Number` is an integer, represent it as u64 if possible. Returns
133 /// None otherwise.
134 #[inline]
135 fn as_u64(&self) -> Option<u64> {
136 self.n.parse().ok()
137 }
138
139 /// Represents the number as finite f64 if possible. Returns None otherwise.
140 #[inline]
141 fn as_f64(&self) -> Option<f64> {
142 self.n.parse::<f64>().ok().filter(|float| float.is_finite())
143 }
144}
145
146impl TryFrom<RawNumber> for Number {
147 type Error = Error;
148
149 fn try_from(value: RawNumber) -> Result<Self, Self::Error> {
150 let num: Number = crate::from_str(value.n.as_str())?;
151 Ok(num)
152 }
153}