microjson/
lib.rs

1// microjson - a no_std json parser in rust
2// Copyright (C) 2021  Robert Spencer
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17#![doc = include_str!("../README.md")]
18#![cfg_attr(not(feature = "std"), no_std)]
19
20mod error;
21pub use error::JSONParsingError;
22
23#[cfg(any(feature = "small_number_parsing", test))]
24mod number_parsing;
25
26// NOTE(robert) We could override this with our own implementation, but looking at the source code,
27// it seems sufficiently compact that any gains we make will be marginal.
28static PARSE_INT: fn(&str) -> Result<isize, core::num::ParseIntError> =
29    <isize as core::str::FromStr>::from_str;
30
31#[cfg(not(feature = "small_number_parsing"))]
32static PARSE_FLOAT: fn(&str) -> Result<f32, core::num::ParseFloatError> =
33    <f32 as core::str::FromStr>::from_str;
34#[cfg(feature = "small_number_parsing")]
35static PARSE_FLOAT: fn(&str) -> Result<f32, ()> = number_parsing::parse_float;
36
37/// Denotes the different types of values JSON objects can have
38///
39/// ### Numbers
40/// Both floats and integers have a value type of [`JSONValueType::Number`].
41///
42/// ### Example
43/// ```
44/// # use microjson::*;
45/// let json_value = JSONValue::load("[1,2,3]");
46/// assert_eq!(json_value.value_type, JSONValueType::Array);
47/// ```
48#[derive(Copy, Clone, PartialEq, Eq, Debug)]
49pub enum JSONValueType {
50    String,
51    Number,
52    Object,
53    Array,
54    Bool,
55    Null,
56    Error,
57}
58
59#[derive(Copy, Clone, Debug)]
60pub struct JSONValue<'a> {
61    contents: &'a str,
62    pub value_type: JSONValueType,
63}
64
65fn trim_start(value: &str) -> (&str, usize) {
66    let value_len = value.len();
67    // NOTE(robert): This trims from the "start" which may be different for RTL languages.  What do
68    // we do for JSON?
69    let value = value.trim_start();
70    (value, value_len - value.len())
71}
72
73impl<'a> JSONValue<'a> {
74    /// Create a new `JSONValue` from an input string
75    ///
76    /// This is the primary method of constructing a [`JSONValue`]. It cannot fail, although the
77    /// value might have type [`JSONValueType::Error`]. However, a malformed payload may have a
78    /// type that is not `JSONValueType::Error`.
79    ///
80    /// If you want to load the payload and verify that it is valid JSON, use
81    /// [`JSONValue::load_and_verify`].
82    pub fn load(contents: &'a str) -> JSONValue {
83        let (contents, _) = trim_start(contents);
84        let value_type = JSONValue::peek_value_type(contents);
85        JSONValue {
86            contents,
87            value_type,
88        }
89    }
90
91    /// Guess the type of the JSON variable serialised in the input string
92    ///
93    /// This function will never give the _wrong_ type, though it may return a type even if the
94    /// input string is not well formed.
95    fn peek_value_type(contents: &'a str) -> JSONValueType {
96        // The contents must be trimmed
97        match contents.chars().next() {
98            Some('{') => JSONValueType::Object,
99            Some('[') => JSONValueType::Array,
100            Some('"') => JSONValueType::String,
101            Some('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-') => {
102                JSONValueType::Number
103            }
104            Some('t' | 'f') => JSONValueType::Bool,
105            Some('n') => JSONValueType::Null,
106            _ => JSONValueType::Error,
107        }
108    }
109
110    /// Confirm that this [`JSONValue`] is proper JSON
111    ///
112    /// This will scan through the entire JSON and confirm that it is properly formatted.
113    /// See also [`JSONValue::load_and_verify`].
114    ///
115    /// ## Example
116    /// ```
117    /// # use microjson::JSONValue;
118    /// let value = JSONValue::load("[1,{},\"foo\"]");
119    /// assert!(value.verify().is_ok());
120    ///
121    /// let value = JSONValue::load("[,,{\"");
122    /// assert!(value.verify().is_err());
123    /// ```
124    pub fn verify(&self) -> Result<(), JSONParsingError> {
125        JSONValue::parse_with_len(self.contents)?;
126        Ok(())
127    }
128
129    /// Load a JSON value from a payload and verify that it is valid JSON.
130    ///
131    /// This is equivalent to calling [`JSONValue::load`] followed by [`JSONValue::verify`].
132    pub fn load_and_verify(contents: &'a str) -> Result<JSONValue, JSONParsingError> {
133        let value = JSONValue::load(contents);
134        value.verify()?;
135        Ok(value)
136    }
137
138    /// Parse a payload and return the JSONValue appearing as its prefix, along with the length of
139    /// that prefix
140    fn parse_with_len(contents: &'a str) -> Result<(JSONValue, usize), JSONParsingError> {
141        let (contents, whitespace_trimmed) = trim_start(contents);
142        let (value_type, value_len) = match contents.chars().next() {
143            Some('{') => {
144                let mut value_len = 1;
145                let mut contents = &contents[value_len..];
146                while !contents.is_empty() {
147                    if contents.trim_start().starts_with('}') {
148                        value_len += trim_start(contents).1 + 1;
149                        break;
150                    }
151                    let (item, item_len) = JSONValue::parse_with_len(contents)?;
152                    if item.value_type != JSONValueType::String {
153                        return Err(JSONParsingError::CannotParseString);
154                    }
155                    let (new_contents, whitespace) = trim_start(&contents[item_len..]);
156                    contents = new_contents;
157                    value_len += item_len + whitespace;
158                    if contents.is_empty() {
159                        return Err(JSONParsingError::EndOfStream);
160                    } else if contents.starts_with(':') {
161                        value_len += 1;
162                        contents = &contents[1..];
163                    } else {
164                        return Err(JSONParsingError::UnexpectedToken);
165                    }
166
167                    let (_, item_len) = JSONValue::parse_with_len(contents)?;
168                    let (new_contents, whitespace) = trim_start(&contents[item_len..]);
169                    contents = new_contents;
170                    value_len += item_len + whitespace;
171                    if contents.is_empty() {
172                        return Err(JSONParsingError::EndOfStream);
173                    } else if contents.starts_with(',') {
174                        value_len += 1;
175                        contents = &contents[1..];
176                    } else if !contents.starts_with('}') {
177                        return Err(JSONParsingError::UnexpectedToken);
178                    }
179                }
180                (JSONValueType::Object, value_len)
181            }
182            Some('[') => {
183                let mut value_len = 1;
184                let mut contents = &contents[value_len..];
185                while !contents.is_empty() {
186                    if contents.trim_start().starts_with(']') {
187                        value_len += trim_start(contents).1 + 1;
188                        break;
189                    }
190                    let (_, item_len) = JSONValue::parse_with_len(contents)?;
191                    let (new_contents, whitespace) = trim_start(&contents[item_len..]);
192                    contents = new_contents;
193                    value_len += item_len + whitespace;
194                    if contents.is_empty() {
195                        return Err(JSONParsingError::EndOfStream);
196                    } else if contents.starts_with(',') {
197                        value_len += 1;
198                        contents = &contents[1..];
199                    } else if !contents.starts_with(']') {
200                        return Err(JSONParsingError::UnexpectedToken);
201                    }
202                }
203                (JSONValueType::Array, value_len)
204            }
205            Some('"') => {
206                let mut value_len = 1;
207                let mut is_escaped = false;
208                for chr in contents[1..].chars() {
209                    value_len += chr.len_utf8();
210                    if chr == '"' && !is_escaped {
211                        break;
212                    } else if chr == '\\' {
213                        is_escaped = !is_escaped;
214                    } else {
215                        is_escaped = false;
216                    }
217                }
218                (JSONValueType::String, value_len)
219            }
220            Some('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-') => {
221                let mut value_len = 0;
222                for chr in contents.chars() {
223                    match chr {
224                        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-' | 'e'
225                        | 'E' | '.' => {
226                            value_len += chr.len_utf8();
227                        }
228                        _ => {
229                            break;
230                        }
231                    }
232                }
233                (JSONValueType::Number, value_len)
234            }
235            Some('t') => {
236                if &contents[..4] != "true" {
237                    return Err(JSONParsingError::UnexpectedToken);
238                }
239                (JSONValueType::Bool, 4)
240            }
241            Some('f') => {
242                if &contents[..5] != "false" {
243                    return Err(JSONParsingError::UnexpectedToken);
244                }
245                (JSONValueType::Bool, 5)
246            }
247            Some('n') => {
248                if &contents[..4] != "null" {
249                    return Err(JSONParsingError::UnexpectedToken);
250                }
251                (JSONValueType::Null, 4)
252            }
253            _ => {
254                return Err(JSONParsingError::UnexpectedToken);
255            }
256        };
257        Ok((
258            JSONValue {
259                contents: &contents[..value_len],
260                value_type,
261            },
262            whitespace_trimmed + value_len,
263        ))
264    }
265
266    /// Checks if the [`JSONValue`] is null
267    ///
268    /// If the value is malformed, returns false.
269    ///
270    /// ### Example
271    /// ```
272    /// # use microjson::{JSONValue, JSONParsingError};
273    /// let value = JSONValue::load("null");
274    /// assert_eq!(value.is_null(), true);
275    ///
276    /// let value = JSONValue::load("1293");
277    /// assert_eq!(value.is_null(), false);
278    /// ```
279    pub fn is_null(&self) -> bool {
280        self.contents.trim_end() == "null"
281    }
282
283    /// Reads the [`JSONValue`] as a boolean
284    ///
285    /// If the type is not a [`JSONValueType::Boolean`], returns an `Err`.
286    ///
287    /// ### Example
288    /// ```
289    /// # use microjson::{JSONValue, JSONParsingError};
290    /// let value = JSONValue::load("true");
291    /// assert_eq!(value.read_boolean(), Ok(true));
292    ///
293    /// let value = JSONValue::load("f");
294    /// assert_eq!(value.read_boolean(), Err(JSONParsingError::CannotParseBoolean));
295    /// ```
296    pub fn read_boolean(&self) -> Result<bool, JSONParsingError> {
297        if self.value_type != JSONValueType::Bool {
298            return Err(JSONParsingError::CannotParseBoolean);
299        }
300        let contents = self.contents.trim_end();
301        if contents == "true" {
302            Ok(true)
303        } else if contents == "false" {
304            Ok(false)
305        } else {
306            Err(JSONParsingError::CannotParseBoolean)
307        }
308    }
309
310    /// Reads the [`JSONValue`] as an integer
311    ///
312    /// If the type is not a [`JSONValueType::Number`], returns an `Err`.
313    ///
314    /// ### Example
315    /// ```
316    /// # use microjson::{JSONValue, JSONParsingError};
317    /// let value = JSONValue::load("-24");
318    /// assert_eq!(value.read_integer(), Ok(-24));
319    ///
320    /// let value = JSONValue::load("5pi");
321    /// assert_eq!(value.read_integer(), Err(JSONParsingError::CannotParseInteger));
322    /// ```
323    pub fn read_integer(&self) -> Result<isize, JSONParsingError> {
324        if self.value_type != JSONValueType::Number {
325            return Err(JSONParsingError::CannotParseInteger);
326        }
327        let contents = self.contents.trim_end();
328        PARSE_INT(contents).map_err(|_| JSONParsingError::CannotParseInteger)
329    }
330
331    /// Reads the [`JSONValue`] as a float
332    ///
333    /// If the type is not a [`JSONValueType::Number`], returns an `Err`.
334    ///
335    /// ### Example
336    /// ```
337    /// # use microjson::{JSONValue, JSONParsingError};
338    /// let value = JSONValue::load("2.4");
339    /// assert_eq!(value.read_float(), Ok(2.4));
340    ///
341    /// let value = JSONValue::load("5pi");
342    /// assert_eq!(value.read_float(), Err(JSONParsingError::CannotParseFloat));
343    /// ```
344    pub fn read_float(&self) -> Result<f32, JSONParsingError> {
345        if self.value_type != JSONValueType::Number {
346            return Err(JSONParsingError::CannotParseFloat);
347        }
348        let contents = self.contents.trim_end();
349        PARSE_FLOAT(contents).map_err(|_| JSONParsingError::CannotParseFloat)
350    }
351
352    /// Read the [`JSONValue`] as a string
353    ///
354    /// This returns an unescaped string (actually a slice into the underlying bytes). If you need
355    /// escape sequences to be handled, use [`JSONValue::iter_string`].
356    ///
357    /// ## Example
358    /// ```
359    /// # use microjson::JSONValue;
360    /// let value = JSONValue::load("\"this is a string\"");
361    /// assert_eq!(value.read_string(), Ok("this is a string"));
362    /// ```
363    pub fn read_string(&self) -> Result<&'a str, JSONParsingError> {
364        let (_, length) = JSONValue::parse_with_len(self.contents)?;
365        if self.value_type != JSONValueType::String {
366            return Err(JSONParsingError::CannotParseString);
367        }
368        Ok(&self.contents[1..length - 1])
369    }
370
371    /// Constructs an iterator over this array value
372    ///
373    /// If the value is not an [`JSONValueType::Array`], returns an error.
374    pub fn iter_array(&self) -> Result<JSONArrayIterator<'a>, JSONParsingError> {
375        if self.value_type != JSONValueType::Array {
376            return Err(JSONParsingError::CannotParseArray);
377        }
378        Ok(JSONArrayIterator {
379            contents: &self.contents[1..],
380        })
381    }
382
383    /// Constructs an iterator over this string
384    ///
385    /// If the value is not an [`JSONValueType::String`], returns an error.
386    ///
387    /// The iterator returns [`Result<char, JSONParsingError>`]s and handles escape sequences.
388    /// You can convert this into a `Result<String, _>` using `collect`.
389    ///
390    /// ### Example
391    /// ```
392    /// # use microjson::JSONValue;
393    /// let value = JSONValue::load(r#" "\u27FC This is a string with unicode \u27FB""#);
394    /// let string : Result<String, _> = value.iter_string().unwrap().collect::<Result<String, _>>();
395    /// assert_eq!(string.unwrap(), "⟼ This is a string with unicode ⟻")
396    /// ```
397    pub fn iter_string(&self) -> Result<EscapedStringIterator<'a>, JSONParsingError> {
398        if self.value_type != JSONValueType::String {
399            return Err(JSONParsingError::CannotParseString);
400        }
401        Ok(EscapedStringIterator {
402            contents: self.contents[1..].chars(),
403            done: false,
404        })
405    }
406
407    /// Constructs an iterator over this object
408    ///
409    /// If the value is not an [`JSONValueType::Object`], returns an error.
410    pub fn iter_object(&self) -> Result<JSONObjectIterator<'a>, JSONParsingError> {
411        if self.value_type != JSONValueType::Object {
412            return Err(JSONParsingError::CannotParseObject);
413        }
414        Ok(JSONObjectIterator {
415            contents: &self.contents[1..],
416        })
417    }
418
419    /// Searches this object for a key and returns it's value
420    ///
421    /// Like the function [`Iterator::nth`], this searches linearly through all the keys in the
422    /// object to find the desired one. If parsing the entire object in an arbitrary order, then,
423    /// prefer using [`JSONValue::iter_object`].
424    ///
425    /// Will return `Err(JSONParsingError::KeyNotFound)` if the key is not present.
426    pub fn get_key_value(&self, key: &str) -> Result<JSONValue, JSONParsingError> {
427        self.iter_object()?
428            .find(|item| matches!(item, Ok((k, _)) if k == &key))
429            .map(|item| item.unwrap().1)
430            .ok_or(JSONParsingError::KeyNotFound)
431    }
432}
433
434/// An iterator through a JSON object
435///
436/// Usually constructed with [`JSONValue::iter_object`].
437///
438/// The iterator items are `Result<(key, value), JSONParsingError>`, but the key is not escaped
439pub struct JSONObjectIterator<'a> {
440    contents: &'a str,
441}
442
443impl<'a> Iterator for JSONObjectIterator<'a> {
444    type Item = Result<(&'a str, JSONValue<'a>), JSONParsingError>;
445
446    fn next(&mut self) -> Option<Self::Item> {
447        self.contents = self.contents.trim_start();
448        if self.contents.is_empty() {
449            None
450        } else {
451            if !self.contents.starts_with('\"') {
452                self.contents = &self.contents[..0];
453                return None;
454            }
455            // We expect this to be a string value for the key
456            match JSONValue::parse_with_len(self.contents) {
457                Ok((_, key_len)) => {
458                    let this_key = &self.contents[1..key_len - 1];
459                    self.contents = &self.contents[key_len..].trim_start()[1..];
460
461                    match JSONValue::parse_with_len(self.contents) {
462                        Ok((this_value, value_len)) => {
463                            self.contents = &self.contents[value_len..].trim_start();
464                            if !self.contents.is_empty() {
465                                self.contents = &self.contents[1..];
466                            }
467                            Some(Ok((this_key, this_value)))
468                        }
469                        Err(e) => {
470                            self.contents = &self.contents[..0];
471                            Some(Err(e))
472                        }
473                    }
474                }
475                Err(e) => {
476                    self.contents = &self.contents[..0];
477                    Some(Err(e))
478                }
479            }
480        }
481    }
482}
483
484/// An iterator through a JSON array value
485///
486/// Usually constructed with [`JSONValue::iter_array`].
487pub struct JSONArrayIterator<'a> {
488    contents: &'a str,
489}
490
491impl<'a> Iterator for JSONArrayIterator<'a> {
492    type Item = JSONValue<'a>;
493
494    fn next(&mut self) -> Option<Self::Item> {
495        match JSONValue::parse_with_len(self.contents) {
496            Ok((value, value_len)) => {
497                self.contents = &self.contents[value_len..].trim_start()[1..];
498                Some(value)
499            }
500            _ => None,
501        }
502    }
503}
504
505/// Iterator over a JSON-escaped string
506///
507/// See [`JSONValue::iter_string`] for further documentation.
508pub struct EscapedStringIterator<'a> {
509    contents: core::str::Chars<'a>,
510    done: bool,
511}
512
513impl<'a> Iterator for EscapedStringIterator<'a> {
514    type Item = Result<char, JSONParsingError>;
515
516    fn next(&mut self) -> Option<Self::Item> {
517        if self.done {
518            None
519        } else {
520            let chr = self.contents.next();
521            match chr {
522                Some('\\') => {
523                    let chr = self.contents.next();
524                    match chr {
525                        Some('"' | '\\' | '/') => chr.map(Ok),
526                        Some('b') => Some(Ok('\x08')),
527                        Some('f') => Some(Ok('\x0c')),
528                        Some('n') => Some(Ok('\n')),
529                        Some('t') => Some(Ok('\t')),
530                        Some('r') => Some(Ok('\r')),
531                        Some('u') => {
532                            let mut get_digit = || {
533                                self.contents
534                                    .next()
535                                    .and_then(|x| x.to_digit(16))
536                                    .ok_or(JSONParsingError::TooShortEscapeSequence)
537                            };
538                            let mut parse_unicode = || {
539                                let code = [get_digit()?, get_digit()?, get_digit()?, get_digit()?];
540                                let code =
541                                    (code[0] << 12) | (code[1] << 8) | (code[2] << 4) | code[3];
542                                char::from_u32(code)
543                                    .ok_or(JSONParsingError::InvalidUnicodeEscapeSequence)
544                            };
545                            match parse_unicode() {
546                                Ok(chr) => Some(Ok(chr)),
547                                Err(e) => {
548                                    self.done = true;
549                                    Some(Err(e))
550                                }
551                            }
552                        }
553                        Some(x) => {
554                            self.done = true;
555                            Some(Err(JSONParsingError::InvalidEscapeSequence(x)))
556                        }
557                        None => None,
558                    }
559                }
560                Some('"') => {
561                    self.done = true;
562                    None
563                }
564                None => {
565                    self.done = true;
566                    Some(Err(JSONParsingError::EndOfStream))
567                }
568                _ => chr.map(Ok),
569            }
570        }
571    }
572}
573
574#[cfg(test)]
575mod test {
576    use super::*;
577    extern crate std;
578
579    #[test]
580    fn is_null() {
581        assert_eq!(JSONValue::load("null").is_null(), true);
582        assert_eq!(JSONValue::load("1234").is_null(), false);
583        assert_eq!(JSONValue::load("<!or").is_null(), false);
584    }
585
586    #[test]
587    fn boolean() {
588        assert_eq!(JSONValue::load("true").read_boolean(), Ok(true));
589        assert_eq!(JSONValue::load("false").read_boolean(), Ok(false));
590        assert_eq!(
591            JSONValue::load("foo").read_boolean(),
592            Err(JSONParsingError::CannotParseBoolean)
593        );
594    }
595
596    #[test]
597    fn integer() {
598        let (value, value_len) = JSONValue::parse_with_len("42").unwrap();
599        assert_eq!(value.value_type, JSONValueType::Number);
600        assert_eq!(value_len, 2);
601        assert_eq!(value.read_integer(), Ok(42));
602        assert!(value.read_string().is_err());
603
604        assert_eq!(JSONValue::load("-98").read_integer(), Ok(-98));
605        assert_eq!(JSONValue::load("-99 ").read_integer(), Ok(-99));
606    }
607
608    #[test]
609    fn float() {
610        let (value, value_len) = JSONValue::parse_with_len("3.141592").unwrap();
611        assert_eq!(value.value_type, JSONValueType::Number);
612        assert_eq!(value_len, "3.141592".len());
613        assert_eq!(
614            value.read_integer(),
615            Err(JSONParsingError::CannotParseInteger)
616        );
617        assert_eq!(
618            value.read_string(),
619            Err(JSONParsingError::CannotParseString)
620        );
621        assert!((value.read_float().unwrap() - 3.141592).abs() < 0.0001);
622
623        assert_eq!(
624            JSONValue::load("-3.43w").read_float(),
625            Err(JSONParsingError::CannotParseFloat)
626        );
627    }
628
629    #[test]
630    fn string() {
631        let (value, value_len) = JSONValue::parse_with_len("\"hello world\"").unwrap();
632        assert_eq!(value.value_type, JSONValueType::String);
633        assert_eq!(value_len, "\"hello world\"".len());
634        assert!(value.read_integer().is_err());
635        assert_eq!(value.read_string(), Ok("hello world"));
636
637        let value = JSONValue::load("\"hello world\"   ");
638        assert_eq!(value.read_string(), Ok("hello world"));
639    }
640
641    #[test]
642    fn array() {
643        let (value, value_len) = JSONValue::parse_with_len("[1,2,3]").unwrap();
644        assert_eq!(value.value_type, JSONValueType::Array);
645        assert_eq!(value_len, "[1,2,3]".len());
646        let (value, value_len) = JSONValue::parse_with_len("[]").unwrap();
647        assert_eq!(value.value_type, JSONValueType::Array);
648        assert_eq!(value_len, "[]".len());
649        let (value, value_len) = JSONValue::parse_with_len("  [\n  ]").unwrap();
650        assert_eq!(value.value_type, JSONValueType::Array);
651        assert_eq!(value_len, "  [\n  ]".len());
652        let (value, value_len) = JSONValue::parse_with_len("[1  ,  2\t,\r3\n]").unwrap();
653        assert_eq!(value.value_type, JSONValueType::Array);
654        assert_eq!(value_len, "[1  ,  2\t,\r3\n]".len());
655
656        assert!(value.read_integer().is_err());
657        assert!(value.read_string().is_err());
658        assert_eq!(
659            value.iter_array().unwrap().nth(0).unwrap().read_integer(),
660            Ok(1)
661        );
662        assert_eq!(
663            value.iter_array().unwrap().nth(1).unwrap().read_integer(),
664            Ok(2)
665        );
666        assert_eq!(
667            value.iter_array().unwrap().nth(2).unwrap().read_integer(),
668            Ok(3)
669        );
670    }
671
672    #[test]
673    fn object() {
674        let input = "{
675        \"id\": 0,
676        \"name\": \"Ginger Fuller\"}";
677        let (value, value_len) = JSONValue::parse_with_len(input).unwrap();
678        assert_eq!(value.value_type, JSONValueType::Object);
679        assert_eq!(value_len, input.len());
680
681        assert!(value.read_integer().is_err());
682        assert!(value.read_string().is_err());
683        assert_eq!(value.get_key_value("id").unwrap().read_integer(), Ok(0));
684        assert_eq!(
685            value.get_key_value("name").unwrap().read_string(),
686            Ok("Ginger Fuller")
687        );
688        assert_eq!(
689            value.get_key_value("surname").err(),
690            Some(JSONParsingError::KeyNotFound)
691        );
692
693        assert!(JSONValue::load("{\"foo\":[{}]}").value_type != JSONValueType::Error);
694        assert!(JSONValue::load("[{\"foo\":{}}]").value_type != JSONValueType::Error);
695    }
696    #[test]
697
698    fn this_broke_once() {
699        assert!(
700            JSONValue::load(
701                r##"
702[{"a":{"email":"d@"},"m":"#20\n\n.\n"}]
703    "##
704            )
705            .value_type
706                != JSONValueType::Error
707        )
708    }
709
710    #[test]
711    fn integer_whitespace() {
712        let (value, value_len) = JSONValue::parse_with_len("  42	").unwrap();
713        assert_eq!(value.value_type, JSONValueType::Number);
714        assert_eq!(value_len, "  42".len());
715        let (value, value_len) = JSONValue::parse_with_len("\n 42\r").unwrap();
716        assert_eq!(value.value_type, JSONValueType::Number);
717        assert_eq!(value_len, "\n 42".len());
718    }
719
720    #[test]
721    fn string_whitespace() {
722        let (value, value_len) = JSONValue::parse_with_len("  \"foo me a bar\"	").unwrap();
723        assert_eq!(value.value_type, JSONValueType::String);
724        assert_eq!(value_len, "  \"foo me a bar\"".len());
725        let (value, value_len) = JSONValue::parse_with_len("\n \"a bar\n I said.\"\r").unwrap();
726        assert_eq!(value.value_type, JSONValueType::String);
727        assert_eq!(value_len, "\n \"a bar\n I said.\"".len());
728    }
729
730    #[test]
731    fn peeking_value_type() {
732        assert_eq!(JSONValue::peek_value_type("123"), JSONValueType::Number);
733        assert_eq!(JSONValue::peek_value_type("12.3"), JSONValueType::Number);
734        assert_eq!(JSONValue::peek_value_type("12.3e10"), JSONValueType::Number);
735        assert_eq!(JSONValue::peek_value_type("-3"), JSONValueType::Number);
736        assert_eq!(JSONValue::peek_value_type("-3.5"), JSONValueType::Number);
737        assert_eq!(JSONValue::peek_value_type("null"), JSONValueType::Null);
738        assert_eq!(JSONValue::peek_value_type("true"), JSONValueType::Bool);
739        assert_eq!(JSONValue::peek_value_type("false"), JSONValueType::Bool);
740        assert_eq!(JSONValue::peek_value_type("[]"), JSONValueType::Array);
741        assert_eq!(JSONValue::peek_value_type("[12]"), JSONValueType::Array);
742        assert_eq!(JSONValue::peek_value_type("[1,2]"), JSONValueType::Array);
743        assert_eq!(JSONValue::peek_value_type("[[]]"), JSONValueType::Array);
744        assert_eq!(JSONValue::peek_value_type("\"foo\""), JSONValueType::String);
745        assert_eq!(JSONValue::peek_value_type("{}"), JSONValueType::Object);
746        assert_eq!(
747            JSONValue::peek_value_type("{\"a\":2}"),
748            JSONValueType::Object
749        );
750        assert_eq!(JSONValue::peek_value_type("<"), JSONValueType::Error);
751        assert_eq!(JSONValue::peek_value_type("bar"), JSONValueType::Error);
752    }
753
754    #[test]
755    fn verifying() {
756        assert!(JSONValue::load_and_verify(" 123 ").is_ok());
757        assert!(JSONValue::load_and_verify("[123]").is_ok());
758        assert!(JSONValue::load_and_verify("\"foo\"").is_ok());
759    }
760
761    #[test]
762    fn string_iterator() {
763        let try_parse_string = |s| {
764            JSONValue::load(s)
765                .iter_string()
766                .unwrap()
767                .collect::<Result<std::string::String, _>>()
768        };
769        let value = try_parse_string("\"I have a dream\"").unwrap();
770        assert_eq!(value, "I have a dream");
771
772        let value = try_parse_string("\"\\\"I have a dream\\\"\"").unwrap();
773        assert_eq!(value, "\"I have a dream\"");
774
775        let value = try_parse_string(r#" "\"I\n\thave\b\fa\\dream\/\"\u00a3" "#).unwrap();
776        assert_eq!(value, "\"I\n\thave\x08\x0ca\\dream/\"£");
777
778        let value = try_parse_string(r#" " "#);
779        assert!(matches!(value, Err(JSONParsingError::EndOfStream)));
780        let value = try_parse_string(r#" "foo\" "#);
781        assert!(matches!(value, Err(JSONParsingError::EndOfStream)));
782        let value = try_parse_string(r#" "Odd escape: \?" "#);
783        assert!(matches!(
784            value,
785            Err(JSONParsingError::InvalidEscapeSequence('?'))
786        ));
787        let value = try_parse_string(r#" "\uwxyz" "#);
788        assert!(matches!(
789            value,
790            Err(JSONParsingError::TooShortEscapeSequence)
791        ));
792        let value = try_parse_string(r#" "\u012" "#);
793        assert!(matches!(
794            value,
795            Err(JSONParsingError::TooShortEscapeSequence)
796        ));
797        // This is not a single character codepoint under utf-16
798        let value = try_parse_string(r#" "\ud834" "#);
799        assert!(matches!(
800            value,
801            Err(JSONParsingError::InvalidUnicodeEscapeSequence)
802        ));
803    }
804
805    #[test]
806    fn object_iterator() {
807        let json_value = JSONValue::load("{\"foo\" : [], \"bar\":{\"baz\": 2}}");
808        let keys = ["foo", "bar"];
809        for (item, expected_key) in json_value.iter_object().unwrap().zip(&keys) {
810            assert_eq!(item.unwrap().0, *expected_key);
811        }
812    }
813
814    #[test]
815    fn string_borrow_past_lifetime_of_value() {
816        let s = "\"abc\"";
817        let t: &str;
818        {
819            t = JSONValue::load(s).read_string().unwrap();
820        }
821        assert_eq!(t, &s[1..s.len() - 1]);
822    }
823
824    #[test]
825    fn empty_object() {
826        let json_value = JSONValue::load("{}");
827        assert_eq!(json_value.value_type, JSONValueType::Object);
828        assert_eq!(
829            json_value.get_key_value("foo").err(),
830            Some(JSONParsingError::KeyNotFound)
831        );
832        assert_eq!(json_value.iter_object().unwrap().count(), 0);
833    }
834}