yason/
json.rs

1//! Json to Yason
2
3use crate::builder::{ArrBuilder, BuildResult, NumberError, ObjBuilder};
4use crate::{
5    ArrayBuilder, ArrayRefBuilder, BuildError, Number, ObjectBuilder, ObjectRefBuilder, Scalar, Yason, YasonBuf,
6};
7use decimal_rs::DecimalParseError;
8use serde_json::{Map, Value};
9use std::fmt::Write;
10use std::str::FromStr;
11
12impl TryFrom<&serde_json::Value> for YasonBuf {
13    type Error = BuildError;
14
15    #[inline]
16    fn try_from(value: &serde_json::Value) -> Result<Self, Self::Error> {
17        let mut buf = String::new();
18        match value {
19            Value::Null => Scalar::null(),
20            Value::Bool(val) => Scalar::bool(*val),
21            Value::Number(val) => Scalar::number(number2decimal(val, &mut buf)?),
22            Value::String(val) => Scalar::string(val),
23            Value::Array(val) => {
24                let mut array_builder = ArrayBuilder::try_new(val.len() as u16)?;
25                write_array(&mut array_builder, val, &mut buf)?;
26                array_builder.finish()
27            }
28            Value::Object(val) => {
29                let mut object_builder = ObjectBuilder::try_new(val.len() as u16, false)?;
30                write_object(&mut object_builder, val, &mut buf)?;
31                object_builder.finish()
32            }
33        }
34    }
35}
36
37impl YasonBuf {
38    /// Parses a json string to `YasonBuf`.
39    #[inline]
40    pub fn parse<T: AsRef<str>>(str: T) -> BuildResult<Self> {
41        let json: Value = serde_json::from_str(str.as_ref()).map_err(BuildError::JsonError)?;
42        YasonBuf::try_from(&json)
43    }
44}
45
46impl Yason {
47    /// Parses a json string to `Yason`.
48    #[inline]
49    pub fn parse_to<T: AsRef<str>>(bytes: &mut Vec<u8>, str: T) -> BuildResult<&Yason> {
50        let mut buf = String::new();
51
52        let json: Value = serde_json::from_str(str.as_ref()).map_err(BuildError::JsonError)?;
53        match &json {
54            Value::Null => Scalar::null_with_vec(bytes),
55            Value::Bool(val) => Scalar::bool_with_vec(*val, bytes),
56            Value::Number(val) => Scalar::number_with_vec(number2decimal(val, &mut buf)?, bytes),
57            Value::String(val) => Scalar::string_with_vec(val, bytes),
58            Value::Array(array) => {
59                let mut builder = ArrayRefBuilder::try_new(bytes, array.len() as u16)?;
60                write_array(&mut builder, array, &mut buf)?;
61                builder.finish()
62            }
63            Value::Object(object) => {
64                let mut builder = ObjectRefBuilder::try_new(bytes, object.len() as u16, false)?;
65                write_object(&mut builder, object, &mut buf)?;
66                builder.finish()
67            }
68        }
69    }
70}
71
72#[inline]
73fn write_array<T: ArrBuilder>(builder: &mut T, array: &[serde_json::Value], buf: &mut String) -> BuildResult<()> {
74    for value in array {
75        match value {
76            Value::Null => {
77                builder.push_null()?;
78            }
79            Value::Bool(val) => {
80                builder.push_bool(*val)?;
81            }
82            Value::Number(val) => {
83                builder.push_number(number2decimal(val, buf)?)?;
84            }
85            Value::String(val) => {
86                builder.push_string(val)?;
87            }
88            Value::Array(val) => {
89                let mut array_builder = builder.push_array(val.len() as u16)?;
90                write_array(&mut array_builder, val, buf)?;
91                array_builder.finish()?;
92            }
93            Value::Object(val) => {
94                let mut object_builder = builder.push_object(val.len() as u16, false)?;
95                write_object(&mut object_builder, val, buf)?;
96                object_builder.finish()?;
97            }
98        }
99    }
100    Ok(())
101}
102
103#[inline]
104fn write_object<T: ObjBuilder>(
105    builder: &mut T,
106    object: &Map<String, serde_json::Value>,
107    buf: &mut String,
108) -> BuildResult<()> {
109    for (key, value) in object {
110        match value {
111            Value::Null => {
112                builder.push_null(key)?;
113            }
114            Value::Bool(val) => {
115                builder.push_bool(key, *val)?;
116            }
117            Value::Number(val) => {
118                builder.push_number(key, number2decimal(val, buf)?)?;
119            }
120            Value::String(val) => {
121                builder.push_string(key, val)?;
122            }
123            Value::Array(val) => {
124                let mut array_builder = builder.push_array(key, val.len() as u16)?;
125                write_array(&mut array_builder, val, buf)?;
126                array_builder.finish()?;
127            }
128            Value::Object(val) => {
129                let mut object_builder = builder.push_object(key, val.len() as u16, false)?;
130                write_object(&mut object_builder, val, buf)?;
131                object_builder.finish()?;
132            }
133        }
134    }
135    Ok(())
136}
137
138#[inline]
139fn number2decimal(val: &serde_json::Number, buf: &mut String) -> BuildResult<Number> {
140    buf.clear();
141    buf.try_reserve(256)?;
142    write!(buf, "{}", val).map_err(|_| BuildError::NumberError(NumberError::FormatError))?;
143    Number::from_str(buf.as_str()).map_or_else(
144        |e| match e {
145            DecimalParseError::Underflow => Ok(Number::ZERO),
146            DecimalParseError::Overflow => Err(BuildError::NumberError(NumberError::Overflow)),
147            _ => unreachable!("internal error: entered unreachable parsing error"),
148        },
149        Ok,
150    )
151}
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156    use decimal_rs::Decimal;
157    use serde_json::Error;
158    use std::str::FromStr;
159
160    #[test]
161    fn test_number2decimal() {
162        fn assert_number(input: &str, output: &str) {
163            let number: serde_json::Number = serde_json::from_str(input).unwrap();
164            let mut buf = String::with_capacity(256);
165            let decimal = number2decimal(&number, &mut buf).unwrap();
166            assert_eq!(decimal, Decimal::from_str(output).unwrap());
167        }
168
169        fn assert_number_invalid(s: &str) {
170            let number: Result<serde_json::Number, Error> = serde_json::from_str(s);
171            assert!(number.is_err());
172        }
173
174        fn assert_number_overflow(s: &str) {
175            let number: serde_json::Number = serde_json::from_str(s).unwrap();
176            let mut buf = String::with_capacity(256);
177            let decimal = number2decimal(&number, &mut buf);
178            match decimal {
179                Err(BuildError::NumberError(NumberError::Overflow)) => {}
180                _ => panic!("expected numeric overflow"),
181            };
182        }
183
184        assert_number_invalid("Nan");
185        assert_number_invalid("Inf");
186        assert_number_invalid("-Inf");
187        assert_number_invalid("123abc");
188        assert_number_invalid("");
189        assert_number_invalid("   ");
190
191        assert_number_overflow("1e126");
192        assert_number_overflow("1e150");
193
194        assert_number("-123", "-123");
195        assert_number("0", "0");
196        assert_number("123", "123");
197
198        assert_number("9007199254740991", "9007199254740991"); // 2^53-1
199        assert_number("-9007199254740991", "-9007199254740991"); // -2^53+1
200        assert_number("9007199254740993", "9007199254740993"); // 2^53+1
201        assert_number("-9007199254740993", "-9007199254740993"); // -2^53-1
202        assert_number("18446744073709551616", "18446744073709551616"); // 2^64
203
204        assert_number("1e125", "1e125");
205        assert_number("1e-130", "1e-130");
206        assert_number("1e-131", "0");
207        assert_number("1e-150", "0");
208
209        assert_number(
210            "222222222222222222222222222222222222222222",
211            "222222222222222222222222222222222222222200",
212        ); // precision 42 only integral
213        assert_number(
214            "555555555555555555555555555555555555555555",
215            "555555555555555555555555555555555555555600",
216        ); // precision 42 only integral
217
218        assert_number(
219            "0.222222222222222222222222222222222222222222",
220            "0.2222222222222222222222222222222222222222",
221        ); // precision 42 only fractional
222        assert_number(
223            "0.555555555555555555555555555555555555555555",
224            "0.5555555555555555555555555555555555555556",
225        ); // precision 42 only fractional
226
227        assert_number(
228            "0.000000222222222222222222222222222222222222222222",
229            "0.0000002222222222222222222222222222222222222222",
230        ); // precision 42 only fractional
231        assert_number(
232            "0.000000555555555555555555555555555555555555555555",
233            "0.0000005555555555555555555555555555555555555556",
234        ); // precision 42 only fractional
235
236        assert_number(
237            "222222222222222222222222.222222222222222222222e50",
238            "22222222222222222222222222222222222222e36",
239        ); // precision 45
240        assert_number(
241            "555555555555555555555555.555555555555555555555e50",
242            "55555555555555555555555555555555555556e36",
243        ); // precision 45
244    }
245}