1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use ::serde::{
    de, de::Visitor, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer,
};
use ::std::fmt;

use super::number::Number;
use crate::{util::private::Sealed, Error, JsonNumberTrait};

/// Represents a JSON number with arbitrary precision, like as Golang json.Number
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct RawNumber {
    n: String,
}

impl RawNumber {
    pub(crate) fn new(s: &str) -> Self {
        Self { n: s.to_string() }
    }

    /// as_str returns the underlying string representation of the number.
    pub fn as_str(&self) -> &str {
        self.n.as_str()
    }
}

pub(crate) const TOKEN: &str = "$sonic_rs::private::JsonNumber";

impl<'de> Deserialize<'de> for RawNumber {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<RawNumber, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct JsonNumberVisitor;

        impl<'de> Visitor<'de> for JsonNumberVisitor {
            type Value = RawNumber;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a JSON number")
            }

            fn visit_borrowed_str<E>(self, raw: &'de str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                Ok(RawNumber::new(raw))
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, JsonNumberVisitor)
    }
}

impl Serialize for RawNumber {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(TOKEN, 1)?;
        s.serialize_field(TOKEN, &self.n)?;
        s.end()
    }
}

impl Sealed for RawNumber {}

impl JsonNumberTrait for RawNumber {
    /// Returns true if the `Number` is an integer between `i64::MIN` and
    /// `i64::MAX`.
    ///
    /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
    /// return the integer value.
    #[inline]
    fn is_i64(&self) -> bool {
        self.as_i64().is_some()
    }

    /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
    ///
    /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
    /// return the integer value.
    #[inline]
    fn is_u64(&self) -> bool {
        self.as_u64().is_some()
    }

    /// Returns true if the `Number` can be represented by f64.
    ///
    /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
    /// return the floating point value.
    ///
    /// Currently this function returns true if and only if both `is_i64` and
    /// `is_u64` return false but this is not a guarantee in the future.
    #[inline]
    fn is_f64(&self) -> bool {
        self.as_f64().is_some()
    }

    /// If the `Number` is an integer, represent it as i64 if possible. Returns
    /// None otherwise.
    #[inline]
    fn as_i64(&self) -> Option<i64> {
        self.n.parse().ok()
    }

    /// If the `Number` is an integer, represent it as u64 if possible. Returns
    /// None otherwise.
    #[inline]
    fn as_u64(&self) -> Option<u64> {
        self.n.parse().ok()
    }

    /// Represents the number as finite f64 if possible. Returns None otherwise.
    #[inline]
    fn as_f64(&self) -> Option<f64> {
        self.n.parse::<f64>().ok().filter(|float| float.is_finite())
    }
}

impl TryFrom<RawNumber> for Number {
    type Error = Error;

    fn try_from(value: RawNumber) -> Result<Self, Self::Error> {
        let num: Number = crate::from_str(value.n.as_str())?;
        Ok(num)
    }
}