/src/libserialize/json.rs
Rust | 4017 lines | 3528 code | 190 blank | 299 comment | 176 complexity | 8d467e4d40ef13e044e61abb847be881 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-2-Clause, 0BSD, Apache-2.0, MIT, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
- // file at the top-level directory of this distribution and at
- // http://rust-lang.org/COPYRIGHT.
- //
- // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
- // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
- // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
- // option. This file may not be copied, modified, or distributed
- // except according to those terms.
- // Rust JSON serialization library
- // Copyright (c) 2011 Google Inc.
- #![forbid(non_camel_case_types)]
- #![allow(missing_docs)]
- //! JSON parsing and serialization
- //!
- //! # What is JSON?
- //!
- //! JSON (JavaScript Object Notation) is a way to write data in Javascript.
- //! Like XML, it allows to encode structured data in a text format that can be easily read by humans
- //! Its simple syntax and native compatibility with JavaScript have made it a widely used format.
- //!
- //! Data types that can be encoded are JavaScript types (see the `Json` enum for more details):
- //!
- //! * `Boolean`: equivalent to rust's `bool`
- //! * `Number`: equivalent to rust's `f64`
- //! * `String`: equivalent to rust's `String`
- //! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
- //! same array
- //! * `Object`: equivalent to rust's `BTreeMap<String, json::Json>`
- //! * `Null`
- //!
- //! An object is a series of string keys mapping to values, in `"key": value` format.
- //! Arrays are enclosed in square brackets ([ ... ]) and objects in curly brackets ({ ... }).
- //! A simple JSON document encoding a person, their age, address and phone numbers could look like
- //!
- //! ```ignore
- //! {
- //! "FirstName": "John",
- //! "LastName": "Doe",
- //! "Age": 43,
- //! "Address": {
- //! "Street": "Downing Street 10",
- //! "City": "London",
- //! "Country": "Great Britain"
- //! },
- //! "PhoneNumbers": [
- //! "+44 1234567",
- //! "+44 2345678"
- //! ]
- //! }
- //! ```
- //!
- //! # Rust Type-based Encoding and Decoding
- //!
- //! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via
- //! the serialization API.
- //! To be able to encode a piece of data, it must implement the `serialize::RustcEncodable` trait.
- //! To be able to decode a piece of data, it must implement the `serialize::RustcDecodable` trait.
- //! The Rust compiler provides an annotation to automatically generate the code for these traits:
- //! `#[derive(RustcDecodable, RustcEncodable)]`
- //!
- //! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects.
- //! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value.
- //! A `json::Json` value can be encoded as a string or buffer using the functions described above.
- //! You can also use the `json::Encoder` object, which implements the `Encoder` trait.
- //!
- //! When using `ToJson` the `RustcEncodable` trait implementation is not mandatory.
- //!
- //! # Examples of use
- //!
- //! ## Using Autoserialization
- //!
- //! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
- //! serialization API, using the derived serialization code.
- //!
- //! ```rust
- //! # #![feature(rustc_private)]
- //! extern crate serialize as rustc_serialize; // for the deriving below
- //! use rustc_serialize::json;
- //!
- //! // Automatically generate `Decodable` and `Encodable` trait implementations
- //! #[derive(RustcDecodable, RustcEncodable)]
- //! pub struct TestStruct {
- //! data_int: u8,
- //! data_str: String,
- //! data_vector: Vec<u8>,
- //! }
- //!
- //! fn main() {
- //! let object = TestStruct {
- //! data_int: 1,
- //! data_str: "homura".to_string(),
- //! data_vector: vec![2,3,4,5],
- //! };
- //!
- //! // Serialize using `json::encode`
- //! let encoded = json::encode(&object).unwrap();
- //!
- //! // Deserialize using `json::decode`
- //! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
- //! }
- //! ```
- //!
- //! ## Using the `ToJson` trait
- //!
- //! The examples above use the `ToJson` trait to generate the JSON string, which is required
- //! for custom mappings.
- //!
- //! ### Simple example of `ToJson` usage
- //!
- //! ```rust
- //! # #![feature(rustc_private)]
- //! extern crate serialize;
- //! use serialize::json::{self, ToJson, Json};
- //!
- //! // A custom data structure
- //! struct ComplexNum {
- //! a: f64,
- //! b: f64,
- //! }
- //!
- //! // JSON value representation
- //! impl ToJson for ComplexNum {
- //! fn to_json(&self) -> Json {
- //! Json::String(format!("{}+{}i", self.a, self.b))
- //! }
- //! }
- //!
- //! // Only generate `RustcEncodable` trait implementation
- //! #[derive(Encodable)]
- //! pub struct ComplexNumRecord {
- //! uid: u8,
- //! dsc: String,
- //! val: Json,
- //! }
- //!
- //! fn main() {
- //! let num = ComplexNum { a: 0.0001, b: 12.539 };
- //! let data: String = json::encode(&ComplexNumRecord{
- //! uid: 1,
- //! dsc: "test".to_string(),
- //! val: num.to_json(),
- //! }).unwrap();
- //! println!("data: {}", data);
- //! // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
- //! }
- //! ```
- //!
- //! ### Verbose example of `ToJson` usage
- //!
- //! ```rust
- //! # #![feature(rustc_private)]
- //! extern crate serialize;
- //! use std::collections::BTreeMap;
- //! use serialize::json::{self, Json, ToJson};
- //!
- //! // Only generate `Decodable` trait implementation
- //! #[derive(Decodable)]
- //! pub struct TestStruct {
- //! data_int: u8,
- //! data_str: String,
- //! data_vector: Vec<u8>,
- //! }
- //!
- //! // Specify encoding method manually
- //! impl ToJson for TestStruct {
- //! fn to_json(&self) -> Json {
- //! let mut d = BTreeMap::new();
- //! // All standard types implement `to_json()`, so use it
- //! d.insert("data_int".to_string(), self.data_int.to_json());
- //! d.insert("data_str".to_string(), self.data_str.to_json());
- //! d.insert("data_vector".to_string(), self.data_vector.to_json());
- //! Json::Object(d)
- //! }
- //! }
- //!
- //! fn main() {
- //! // Serialize using `ToJson`
- //! let input_data = TestStruct {
- //! data_int: 1,
- //! data_str: "madoka".to_string(),
- //! data_vector: vec![2,3,4,5],
- //! };
- //! let json_obj: Json = input_data.to_json();
- //! let json_str: String = json_obj.to_string();
- //!
- //! // Deserialize like before
- //! let decoded: TestStruct = json::decode(&json_str).unwrap();
- //! }
- //! ```
- use self::JsonEvent::*;
- use self::ErrorCode::*;
- use self::ParserError::*;
- use self::DecoderError::*;
- use self::ParserState::*;
- use self::InternalStackElement::*;
- use std::borrow::Cow;
- use std::collections::{HashMap, BTreeMap};
- use std::io::prelude::*;
- use std::io;
- use std::mem::swap;
- use std::num::FpCategory as Fp;
- use std::ops::Index;
- use std::str::FromStr;
- use std::string;
- use std::{char, f64, fmt, str};
- use std;
- use Encodable;
- /// Represents a json value
- #[derive(Clone, PartialEq, PartialOrd, Debug)]
- pub enum Json {
- I64(i64),
- U64(u64),
- F64(f64),
- String(string::String),
- Boolean(bool),
- Array(self::Array),
- Object(self::Object),
- Null,
- }
- pub type Array = Vec<Json>;
- pub type Object = BTreeMap<string::String, Json>;
- pub struct PrettyJson<'a> { inner: &'a Json }
- pub struct AsJson<'a, T: 'a> { inner: &'a T }
- pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option<usize> }
- /// The errors that can arise while parsing a JSON stream.
- #[derive(Clone, Copy, PartialEq, Debug)]
- pub enum ErrorCode {
- InvalidSyntax,
- InvalidNumber,
- EOFWhileParsingObject,
- EOFWhileParsingArray,
- EOFWhileParsingValue,
- EOFWhileParsingString,
- KeyMustBeAString,
- ExpectedColon,
- TrailingCharacters,
- TrailingComma,
- InvalidEscape,
- InvalidUnicodeCodePoint,
- LoneLeadingSurrogateInHexEscape,
- UnexpectedEndOfHexEscape,
- UnrecognizedHex,
- NotFourDigit,
- NotUtf8,
- }
- #[derive(Clone, PartialEq, Debug)]
- pub enum ParserError {
- /// msg, line, col
- SyntaxError(ErrorCode, usize, usize),
- IoError(io::ErrorKind, String),
- }
- // Builder and Parser have the same errors.
- pub type BuilderError = ParserError;
- #[derive(Clone, PartialEq, Debug)]
- pub enum DecoderError {
- ParseError(ParserError),
- ExpectedError(string::String, string::String),
- MissingFieldError(string::String),
- UnknownVariantError(string::String),
- ApplicationError(string::String)
- }
- #[derive(Copy, Clone, Debug)]
- pub enum EncoderError {
- FmtError(fmt::Error),
- BadHashmapKey,
- }
- /// Returns a readable error string for a given error code.
- pub fn error_str(error: ErrorCode) -> &'static str {
- match error {
- InvalidSyntax => "invalid syntax",
- InvalidNumber => "invalid number",
- EOFWhileParsingObject => "EOF While parsing object",
- EOFWhileParsingArray => "EOF While parsing array",
- EOFWhileParsingValue => "EOF While parsing value",
- EOFWhileParsingString => "EOF While parsing string",
- KeyMustBeAString => "key must be a string",
- ExpectedColon => "expected `:`",
- TrailingCharacters => "trailing characters",
- TrailingComma => "trailing comma",
- InvalidEscape => "invalid escape",
- UnrecognizedHex => "invalid \\u{ esc}ape (unrecognized hex)",
- NotFourDigit => "invalid \\u{ esc}ape (not four digits)",
- NotUtf8 => "contents not utf-8",
- InvalidUnicodeCodePoint => "invalid Unicode code point",
- LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape",
- UnexpectedEndOfHexEscape => "unexpected end of hex escape",
- }
- }
- /// Shortcut function to decode a JSON `&str` into an object
- pub fn decode<T: ::Decodable>(s: &str) -> DecodeResult<T> {
- let json = match from_str(s) {
- Ok(x) => x,
- Err(e) => return Err(ParseError(e))
- };
- let mut decoder = Decoder::new(json);
- ::Decodable::decode(&mut decoder)
- }
- /// Shortcut function to encode a `T` into a JSON `String`
- pub fn encode<T: ::Encodable>(object: &T) -> Result<string::String, EncoderError> {
- let mut s = String::new();
- {
- let mut encoder = Encoder::new(&mut s);
- object.encode(&mut encoder)?;
- }
- Ok(s)
- }
- impl fmt::Display for ErrorCode {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- error_str(*self).fmt(f)
- }
- }
- fn io_error_to_error(io: io::Error) -> ParserError {
- IoError(io.kind(), io.to_string())
- }
- impl fmt::Display for ParserError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // FIXME this should be a nicer error
- fmt::Debug::fmt(self, f)
- }
- }
- impl fmt::Display for DecoderError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // FIXME this should be a nicer error
- fmt::Debug::fmt(self, f)
- }
- }
- impl std::error::Error for DecoderError {
- fn description(&self) -> &str { "decoder error" }
- }
- impl fmt::Display for EncoderError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // FIXME this should be a nicer error
- fmt::Debug::fmt(self, f)
- }
- }
- impl std::error::Error for EncoderError {
- fn description(&self) -> &str { "encoder error" }
- }
- impl From<fmt::Error> for EncoderError {
- fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
- }
- pub type EncodeResult = Result<(), EncoderError>;
- pub type DecodeResult<T> = Result<T, DecoderError>;
- fn escape_str(wr: &mut fmt::Write, v: &str) -> EncodeResult {
- wr.write_str("\"")?;
- let mut start = 0;
- for (i, byte) in v.bytes().enumerate() {
- let escaped = match byte {
- b'"' => "\\\"",
- b'\\' => "\\\\",
- b'\x00' => "\\u0000",
- b'\x01' => "\\u0001",
- b'\x02' => "\\u0002",
- b'\x03' => "\\u0003",
- b'\x04' => "\\u0004",
- b'\x05' => "\\u0005",
- b'\x06' => "\\u0006",
- b'\x07' => "\\u0007",
- b'\x08' => "\\b",
- b'\t' => "\\t",
- b'\n' => "\\n",
- b'\x0b' => "\\u000b",
- b'\x0c' => "\\f",
- b'\r' => "\\r",
- b'\x0e' => "\\u000e",
- b'\x0f' => "\\u000f",
- b'\x10' => "\\u0010",
- b'\x11' => "\\u0011",
- b'\x12' => "\\u0012",
- b'\x13' => "\\u0013",
- b'\x14' => "\\u0014",
- b'\x15' => "\\u0015",
- b'\x16' => "\\u0016",
- b'\x17' => "\\u0017",
- b'\x18' => "\\u0018",
- b'\x19' => "\\u0019",
- b'\x1a' => "\\u001a",
- b'\x1b' => "\\u001b",
- b'\x1c' => "\\u001c",
- b'\x1d' => "\\u001d",
- b'\x1e' => "\\u001e",
- b'\x1f' => "\\u001f",
- b'\x7f' => "\\u007f",
- _ => { continue; }
- };
- if start < i {
- wr.write_str(&v[start..i])?;
- }
- wr.write_str(escaped)?;
- start = i + 1;
- }
- if start != v.len() {
- wr.write_str(&v[start..])?;
- }
- wr.write_str("\"")?;
- Ok(())
- }
- fn escape_char(writer: &mut fmt::Write, v: char) -> EncodeResult {
- escape_str(writer, v.encode_utf8(&mut [0; 4]))
- }
- fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult {
- const BUF: &'static str = " ";
- while n >= BUF.len() {
- wr.write_str(BUF)?;
- n -= BUF.len();
- }
- if n > 0 {
- wr.write_str(&BUF[..n])?;
- }
- Ok(())
- }
- fn fmt_number_or_null(v: f64) -> string::String {
- match v.classify() {
- Fp::Nan | Fp::Infinite => string::String::from("null"),
- _ if v.fract() != 0f64 => v.to_string(),
- _ => v.to_string() + ".0",
- }
- }
- /// A structure for implementing serialization to JSON.
- pub struct Encoder<'a> {
- writer: &'a mut (fmt::Write+'a),
- is_emitting_map_key: bool,
- }
- impl<'a> Encoder<'a> {
- /// Creates a new JSON encoder whose output will be written to the writer
- /// specified.
- pub fn new(writer: &'a mut fmt::Write) -> Encoder<'a> {
- Encoder { writer: writer, is_emitting_map_key: false, }
- }
- }
- macro_rules! emit_enquoted_if_mapkey {
- ($enc:ident,$e:expr) => ({
- if $enc.is_emitting_map_key {
- write!($enc.writer, "\"{}\"", $e)?;
- } else {
- write!($enc.writer, "{}", $e)?;
- }
- Ok(())
- })
- }
- impl<'a> ::Encoder for Encoder<'a> {
- type Error = EncoderError;
- fn emit_nil(&mut self) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "null")?;
- Ok(())
- }
- fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u128(&mut self, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i128(&mut self, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_bool(&mut self, v: bool) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if v {
- write!(self.writer, "true")?;
- } else {
- write!(self.writer, "false")?;
- }
- Ok(())
- }
- fn emit_f64(&mut self, v: f64) -> EncodeResult {
- emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
- }
- fn emit_f32(&mut self, v: f32) -> EncodeResult {
- self.emit_f64(v as f64)
- }
- fn emit_char(&mut self, v: char) -> EncodeResult {
- escape_char(self.writer, v)
- }
- fn emit_str(&mut self, v: &str) -> EncodeResult {
- escape_str(self.writer, v)
- }
- fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- f(self)
- }
- fn emit_enum_variant<F>(&mut self,
- name: &str,
- _id: usize,
- cnt: usize,
- f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- // enums are encoded as strings or objects
- // Bunny => "Bunny"
- // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
- if cnt == 0 {
- escape_str(self.writer, name)
- } else {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "{{\"variant\":")?;
- escape_str(self.writer, name)?;
- write!(self.writer, ",\"fields\":[")?;
- f(self)?;
- write!(self.writer, "]}}")?;
- Ok(())
- }
- }
- fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx != 0 {
- write!(self.writer, ",")?;
- }
- f(self)
- }
- fn emit_enum_struct_variant<F>(&mut self,
- name: &str,
- id: usize,
- cnt: usize,
- f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_enum_variant(name, id, cnt, f)
- }
- fn emit_enum_struct_variant_field<F>(&mut self,
- _: &str,
- idx: usize,
- f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_enum_variant_arg(idx, f)
- }
- fn emit_struct<F>(&mut self, _: &str, _: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "{{")?;
- f(self)?;
- write!(self.writer, "}}")?;
- Ok(())
- }
- fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx != 0 { write!(self.writer, ",")?; }
- escape_str(self.writer, name)?;
- write!(self.writer, ":")?;
- f(self)
- }
- fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq(len, f)
- }
- fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq_elt(idx, f)
- }
- fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq(len, f)
- }
- fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq_elt(idx, f)
- }
- fn emit_option<F>(&mut self, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- f(self)
- }
- fn emit_option_none(&mut self) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_nil()
- }
- fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- f(self)
- }
- fn emit_seq<F>(&mut self, _len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "[")?;
- f(self)?;
- write!(self.writer, "]")?;
- Ok(())
- }
- fn emit_seq_elt<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx != 0 {
- write!(self.writer, ",")?;
- }
- f(self)
- }
- fn emit_map<F>(&mut self, _len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "{{")?;
- f(self)?;
- write!(self.writer, "}}")?;
- Ok(())
- }
- fn emit_map_elt_key<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx != 0 { write!(self.writer, ",")? }
- self.is_emitting_map_key = true;
- f(self)?;
- self.is_emitting_map_key = false;
- Ok(())
- }
- fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, ":")?;
- f(self)
- }
- }
- /// Another encoder for JSON, but prints out human-readable JSON instead of
- /// compact data
- pub struct PrettyEncoder<'a> {
- writer: &'a mut (fmt::Write+'a),
- curr_indent: usize,
- indent: usize,
- is_emitting_map_key: bool,
- }
- impl<'a> PrettyEncoder<'a> {
- /// Creates a new encoder whose output will be written to the specified writer
- pub fn new(writer: &'a mut fmt::Write) -> PrettyEncoder<'a> {
- PrettyEncoder {
- writer: writer,
- curr_indent: 0,
- indent: 2,
- is_emitting_map_key: false,
- }
- }
- /// Set the number of spaces to indent for each level.
- /// This is safe to set during encoding.
- pub fn set_indent(&mut self, indent: usize) {
- // self.indent very well could be 0 so we need to use checked division.
- let level = self.curr_indent.checked_div(self.indent).unwrap_or(0);
- self.indent = indent;
- self.curr_indent = level * self.indent;
- }
- }
- impl<'a> ::Encoder for PrettyEncoder<'a> {
- type Error = EncoderError;
- fn emit_nil(&mut self) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "null")?;
- Ok(())
- }
- fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u128(&mut self, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i128(&mut self, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_i8(&mut self, v: i8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
- fn emit_bool(&mut self, v: bool) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if v {
- write!(self.writer, "true")?;
- } else {
- write!(self.writer, "false")?;
- }
- Ok(())
- }
- fn emit_f64(&mut self, v: f64) -> EncodeResult {
- emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
- }
- fn emit_f32(&mut self, v: f32) -> EncodeResult {
- self.emit_f64(v as f64)
- }
- fn emit_char(&mut self, v: char) -> EncodeResult {
- escape_char(self.writer, v)
- }
- fn emit_str(&mut self, v: &str) -> EncodeResult {
- escape_str(self.writer, v)
- }
- fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- f(self)
- }
- fn emit_enum_variant<F>(&mut self,
- name: &str,
- _id: usize,
- cnt: usize,
- f: F)
- -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if cnt == 0 {
- escape_str(self.writer, name)
- } else {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, "{{\n")?;
- self.curr_indent += self.indent;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "\"variant\": ")?;
- escape_str(self.writer, name)?;
- write!(self.writer, ",\n")?;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "\"fields\": [\n")?;
- self.curr_indent += self.indent;
- f(self)?;
- self.curr_indent -= self.indent;
- write!(self.writer, "\n")?;
- spaces(self.writer, self.curr_indent)?;
- self.curr_indent -= self.indent;
- write!(self.writer, "]\n")?;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "}}")?;
- Ok(())
- }
- }
- fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx != 0 {
- write!(self.writer, ",\n")?;
- }
- spaces(self.writer, self.curr_indent)?;
- f(self)
- }
- fn emit_enum_struct_variant<F>(&mut self,
- name: &str,
- id: usize,
- cnt: usize,
- f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_enum_variant(name, id, cnt, f)
- }
- fn emit_enum_struct_variant_field<F>(&mut self,
- _: &str,
- idx: usize,
- f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_enum_variant_arg(idx, f)
- }
- fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if len == 0 {
- write!(self.writer, "{{}}")?;
- } else {
- write!(self.writer, "{{")?;
- self.curr_indent += self.indent;
- f(self)?;
- self.curr_indent -= self.indent;
- write!(self.writer, "\n")?;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "}}")?;
- }
- Ok(())
- }
- fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx == 0 {
- write!(self.writer, "\n")?;
- } else {
- write!(self.writer, ",\n")?;
- }
- spaces(self.writer, self.curr_indent)?;
- escape_str(self.writer, name)?;
- write!(self.writer, ": ")?;
- f(self)
- }
- fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq(len, f)
- }
- fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq_elt(idx, f)
- }
- fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq(len, f)
- }
- fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_seq_elt(idx, f)
- }
- fn emit_option<F>(&mut self, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- f(self)
- }
- fn emit_option_none(&mut self) -> EncodeResult {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- self.emit_nil()
- }
- fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- f(self)
- }
- fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if len == 0 {
- write!(self.writer, "[]")?;
- } else {
- write!(self.writer, "[")?;
- self.curr_indent += self.indent;
- f(self)?;
- self.curr_indent -= self.indent;
- write!(self.writer, "\n")?;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "]")?;
- }
- Ok(())
- }
- fn emit_seq_elt<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx == 0 {
- write!(self.writer, "\n")?;
- } else {
- write!(self.writer, ",\n")?;
- }
- spaces(self.writer, self.curr_indent)?;
- f(self)
- }
- fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if len == 0 {
- write!(self.writer, "{{}}")?;
- } else {
- write!(self.writer, "{{")?;
- self.curr_indent += self.indent;
- f(self)?;
- self.curr_indent -= self.indent;
- write!(self.writer, "\n")?;
- spaces(self.writer, self.curr_indent)?;
- write!(self.writer, "}}")?;
- }
- Ok(())
- }
- fn emit_map_elt_key<F>(&mut self, idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- if idx == 0 {
- write!(self.writer, "\n")?;
- } else {
- write!(self.writer, ",\n")?;
- }
- spaces(self.writer, self.curr_indent)?;
- self.is_emitting_map_key = true;
- f(self)?;
- self.is_emitting_map_key = false;
- Ok(())
- }
- fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
- F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
- {
- if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
- write!(self.writer, ": ")?;
- f(self)
- }
- }
- impl Encodable for Json {
- fn encode<E: ::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
- match *self {
- Json::I64(v) => v.encode(e),
- Json::U64(v) => v.encode(e),
- Json::F64(v) => v.encode(e),
- Json::String(ref v) => v.encode(e),
- Json::Boolean(v) => v.encode(e),
- Json::Array(ref v) => v.encode(e),
- Json::Object(ref v) => v.encode(e),
- Json::Null => e.emit_nil(),
- }
- }
- }
- /// Create an `AsJson` wrapper which can be used to print a value as JSON
- /// on-the-fly via `write!`
- pub fn as_json<T>(t: &T) -> AsJson<T> {
- AsJson { inner: t }
- }
- /// Create an `AsPrettyJson` wrapper which can be used to print a value as JSON
- /// on-the-fly via `write!`
- pub fn as_pretty_json<T>(t: &T) -> AsPrettyJson<T> {
- AsPrettyJson { inner: t, indent: None }
- }
- impl Json {
- /// Borrow this json object as a pretty object to generate a pretty
- /// representation for it via `Display`.
- pub fn pretty(&self) -> PrettyJson {
- PrettyJson { inner: self }
- }
- /// If the Json value is an Object, returns the value associated with the provided key.
- /// Otherwise, returns None.
- pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
- match *self {
- Json::Object(ref map) => map.get(key),
- _ => None
- }
- }
- /// Attempts to get a nested Json Object for each key in `keys`.
- /// If any key is found not to exist, find_path will return None.
- /// Otherwise, it will return the Json value associated with the final key.
- pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Json>{
- let mut target = self;
- for key in keys {
- match target.find(*key) {
- Some(t) => { target = t; },
- None => return None
- }
- }
- Some(target)
- }
- /// If the Json value is an Object, performs a depth-first search until
- /// a value associated with the provided key is found. If no value is found
- /// or the Json value is not an Object, returns None.
- pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
- match self {
- &Json::Object(ref map) => {
- match map.get(key) {
- Some(json_value) => Some(json_value),
- None => {
- for (_, v) in map {
- match v.search(key) {
- x if x.is_some() => return x,
- _ => ()
- }
- }
- None
- }
- }
- },
- _ => None
- }
- }
- /// Returns true if the Json value is an Object. Returns false otherwise.
- pub fn is_object(&self) -> bool {
- self.as_object().is_some()
- }
- /// If the Json value is an Object, returns the associated BTreeMap.
- /// Returns None otherwise.
- pub fn as_object(&self) -> Option<&Object> {
- match *self {
- Json::Object(ref map) => Some(map),
- _ => None
- }
- }
- /// Returns true if the Json value is an Array. Returns false otherwise.
- pub fn is_array(&self) -> bool {
- self.as_array().is_some()
- }
- /// If the Json value is an Array, returns the associated vector.
- /// Returns None otherwise.
- pub fn as_array(&self) -> Option<&Array> {
- match *self {
- Json::Array(ref array) => Some(&*array),
- _ => None
- }
- }
- /// Returns true if the Json value is a String. Returns false otherwise.
- pub fn is_string(&self) -> bool {
- self.as_string().is_some()
- }
- /// If the Json value is a String, returns the associated str.
- /// Returns None otherwise.
- pub fn as_string(&self) -> Option<&str> {
- match *self {
- Json::String(ref s) => Some(&s[..]),
- _ => None
- }
- }
- /// Returns true if the Json value is a Number. Returns false otherwise.
- pub fn is_number(&self) -> bool {
- match *self {
- Json::I64(_) | Json::U64(_) | Json::F64(_) => true,
- _ => false,
- }
- }
- /// Returns true if the Json value is a i64. Returns false otherwise.
- pub fn is_i64(&self) -> bool {
- match *self {
- Json::I64(_) => true,
- _ => false,
- }
- }
- /// Returns true if the Json value is a u64. Returns false otherwise.
- pub fn is_u64(&self) -> bool {
- match *self {
- Json::U64(_) => true,
- _ => false,
- }
- }
- /// Returns true if the Json value is a f64. Returns false otherwise.
- pub fn is_f64(&self) -> bool {
- match *self {
- Json::F64(_) => true,
- _ => false,
- }
- }
- /// If the Json value is a number, return or cast it to a i64.
- /// Returns None otherwise.
- pub fn as_i64(&self) -> Option<i64> {
- match *self {
- Json::I64(n) => Some(n),
- Json::U64(n) => Some(n as i64),
- _ => None
- }
- }
- /// If the Json value is a number, return or cast it to a u64.
- /// Returns None otherwise.
- pub fn as_u64(&self) -> Option<u64> {
- match *self {
- Json::I64(n) => Some(n as u64),
- Json::U64(n) => Some(n),
- _ => None
- }
- }
- /// If the Json value is a number, return or cast it to a f64.
- /// Returns None otherwise.
- pub fn as_f64(&self) -> Option<f64> {
- match *self {
- Json::I64(n) => Some(n as f64),
- Json::U64(n) => Some(n as f64),
- Json::F64(n) => Some(n),
- _ => None
- }
- }
- /// Returns true if the Json value is a Boolean. Returns false otherwise.
- pub fn is_boolean(&self) -> bool {
- self.as_boolean().is_some()
- }
- /// If the Json value is a Boolean, returns the associated bool.
- /// Returns None otherwise.
- pub fn as_boolean(&self) -> Option<bool> {
- match *self {
- Json::Boolean(b) => Some(b),
- _ => None
- }
- }
- /// Returns true if the Json value is a Null. Returns false otherwise.
- pub fn is_null(&self) -> bool {
- self.as_null().is_some()
- }
- /// If the Json value is a Null, returns ().
- /// Returns None otherwise.
- pub fn as_null(&self) -> Option<()> {
- match *self {
- Json::Null => Some(()),
- _ => None
- }
- }
- }
- impl<'a> Index<&'a str> for Json {
- type Output = Json;
- fn index(&self, idx: &'a str) -> &Json {
- self.find(idx).unwrap()
- }
- }
- impl Index<usize> for Json {
- type Output = Json;
- fn index(&self, idx: usize) -> &Json {
- match *self {
- Json::Array(ref v) => &v[idx],
- _ => panic!("can only index Json with usize if it is an array")
- }
- }
- }
- /// The output of the streaming parser.
- #[derive(PartialEq, Clone, Debug)]
- pub enum JsonEvent {
- ObjectStart,
- ObjectEnd,
- ArrayStart,
- ArrayEnd,
- BooleanValue(bool),
- I64Value(i64),
- U64Value(u64),
- F64Value(f64),
- StringValue(string::String),
- NullValue,
- Error(ParserError),
- }
- #[derive(PartialEq, Debug)]
- enum ParserState {
- // Parse a value in an array, true means first element.
- ParseArray(bool),
- // Parse ',' or ']' after an element in an array.
- ParseArrayComma,
- // Parse a key:value in an object, true means first element.
- ParseObject(bool),
- // Parse ',' or ']' after an element in an object.
- ParseObjectComma,
- // Initial state.
- ParseStart,
- // Expecting the stream to end.
- ParseBeforeFinish,
- // Parsing can't continue.
- ParseFinished,
- }
- /// A Stack represents the current position of the parser in the logical
- /// structure of the JSON stream.
- /// For example foo.bar[3].x
- pub struct Stack {
- stack: Vec<InternalStackElement>,
- str_buffer: Vec<u8>,
- }
- /// StackElements compose a Stack.
- /// For example, StackElement::Key("foo"), StackElement::Key("bar"),
- /// StackElement::Index(3) and StackElement::Key("x") are the
- /// StackElements compositing the stack that represents foo.bar[3].x
- #[derive(PartialEq, Clone, Debug)]
- pub enum StackElement<'l> {
- Index(u32),
- Key(&'l str),
- }
- // Internally, Key elements are stored as indices in a buffer to avoid
- // allocating a string for every member of an object.
- #[derive(PartialEq, Clone, Debug)]
- enum InternalStackElement {
- InternalIndex(u32),
- InternalKey(u16, u16), // start, size
- }
- impl Stack {
- pub fn new() -> Stack {
- Stack { stack: Vec::new(), str_buffer: Vec::new() }
- }
- /// Returns The number of elements in the Stack.
- pub fn len(&self) -> usize { self.stack.len() }
- /// Returns true if the stack is empty.
- pub fn is_empty(&self) -> bool { self.stack.is_empty() }
- /// Provides access to the StackElement at a given index.
- /// lower indices are at the bottom of the stack while higher indices are
- /// at the top.
- pub fn get(&self, idx: usize) -> StackElement {
- match self.stack[idx] {
- InternalIndex(i) => StackElement::Index(i),
- InternalKey(start, size) => {
- StackElement::Key(str::from_utf8(
- &self.str_buffer[start as usize .. start as usize + size as usize])
- .unwrap())
- }
- }
- }
- /// Compares this stack with an array of StackElements.
- pub fn is_equal_to(&self, rhs: &[StackElement]) -> bool {
- if self.stack.len() != rhs.len() { return false; }
- for (i, r) in rhs.iter().enumerate() {
- if self.get(i) != *r { return false; }
- }
- true
- }
- /// Returns true if the bottom-most elements of this stack are the same as
- /// the ones passed as parameter.
- pub fn starts_with(&self, rhs: &[StackElement]) -> bool {
- if self.stack.len() < rhs.len() { return false; }
- for (i, r) in rhs.iter().enumerate() {
- if self.get(i) != *r { return false; }
- }
- true
- }
- /// Returns true if the top-most elements of this stack are the same as
- /// the ones passed as parameter.
- pub fn ends_with(&self, rhs: &[StackElement]) -> bool {
- if self.stack.len() < rhs.len() { return false; }
- let offset = self.stack.len() - rhs.len();
- for (i, r) in rhs.iter().enumerate() {
- if self.get(i + offset) != *r { return false; }
- }
- true
- }
- /// Returns the top-most element (if any).
- pub fn top(&self) -> Option<StackElement> {
- match self.stack.last() {
- None => None,
- Some(&InternalIndex(i)) => Some(StackElement::Index(i)),
- Some(&InternalKey(start, size)) => {
- Some(StackElement::Key(str::from_utf8(
- &self.str_buffer[start as usize .. (start+size) as usize]
- ).unwrap()))
- }
- }
- }
- // Used by Parser to insert StackElement::Key elements at the top of the stack.
- fn push_key(&mut self, key: string::String) {
- self.stack.push(InternalKey(self.str_buffer.len() as u16, key.len() as u16));
- for c in key.as_bytes() {
- self.str_buffer.push(*c);
- }
- }
- // Used by Parser to insert StackElement::Index elements at the top of the stack.
- fn push_index(&mut self, index: u32) {
- self.stack.push(InternalIndex(index));
- }
- // Used by Parser to remove the top-most element of the stack.
- fn pop(&mut self) {
- assert!(!self.is_empty());
- match *self.stack.last().unwrap() {
- InternalKey(_, sz) => {
- let new_size = self.str_buffer.len() - sz as usize;
- self.str_buffer.truncate(new_size);
- }
- InternalIndex(_) => {}
- }
- self.stack.pop();
- }
- // Used by Parser to test whether the top-most element is an index.
- fn last_is_index(&self) -> bool {
- if self.is_empty() { return false; }
- return match *self.stack.last().unwrap() {
- InternalIndex(_) => true,
- _ => false,
- }
- }
- // Used by Parser to increment the index of the top-most element.
- fn bump_index(&mut self) {
- let len = self.stack.len();
- let idx = match *self.stack.last().unwrap() {
- InternalIndex(i) => { i + 1 }
- _ => { panic!(); }
- };
- self.stack[len - 1] = InternalIndex(idx);
- }
- }
- /// A streaming JSON parser implemented as an iterator of JsonEvent, consuming
- /// an iterator of char.
- pub struct Parser<T> {
- rdr: T,
- ch: Option<char>,
- line: usize,
- col: usize,
- // We maintain a stack representing where we are in the logical structure
- // of the JSON stream.
- stack: Stack,
- // A state machine is kept to make it possible to interrupt and resume parsing.
- state: ParserState,
- }
- impl<T: Iterator<Item=char>> Iterator for Parser<T> {
- type Item = JsonEvent;
- fn next(&mut self) -> Option<JsonEvent> {
- if self.state == ParseFinished {
- return None;
- }
- if self.state == ParseBeforeFinish {
- self.parse_whitespace();
- // Make sure there is no trailing characters.
- if self.eof() {
- self.state = ParseFinished;
- return None;
- } else {
- return Some(self.error_event(TrailingCharacters));
- }
- }
- Some(self.parse())
- }
- }
- impl<T: Iterator<Item=char>> Parser<T> {
- /// Creates the JSON parser.
- pub fn new(rdr: T) -> Parser<T> {
- let mut p = Parser {
- rdr: rdr,
- ch: Some('\x00'),
- line: 1,
- col: 0,
- stack: Stack::new(),
- state: ParseStart,
- };
- p.bump();
- p
- }
- /// Provides access to the current position in the logical structure of the
- /// JSON stream.
- pub fn stack(&self) -> &Stack {
- &self.stack
- }
- fn eof(&self) -> bool { self.ch.is_none() }
- fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
- fn bump(&mut self) {
- self.ch = self.rdr.next();
- if self.ch_is('\n') {
- self.line += 1;
- self.col = 1;
- } else {
- self.col += 1;
- }
- }
- fn next_char(&mut self) -> Option<char> {
- self.bump();
- self.ch
- }
- fn ch_is(&self, c: char) -> bool {
- self.ch == Some(c)
- }
- fn error<U>(&self, reason: ErrorCode) -> Result<U, ParserError> {
- Err(SyntaxError(reason, self.line, self.col))
- }
- fn parse_whitespace(&mut self) {
- while self.ch_is(' ') ||
- self.ch_is('\n') ||
- self.ch_is('\t') ||
- self.ch_is('\r') { self.bump(); }
- }
- fn parse_number(&mut self) -> JsonEvent {
- let mut neg = false;
- if self.ch_is('-') {
- self.bump();
- neg = true;
- }
- let res = match self.parse_u64() {
- Ok(res) => res,
- Err(e) => { return Error(e); }
- };
- if self.ch_is('.') || self.ch_is('e') || self.ch_is('E') {
- let mut res = res as f64;
- if self.ch_is('.') {
- res = match self.parse_decimal(res) {
- Ok(res) => res,
- Err(e) => { return Error(e); }
- };
- }
- if self.ch_is('e') || self.ch_is('E') {
- res = match self.parse_exponent(res) {
- Ok(res) => res,
- Err(e) => { return Error(e); }
- };
- }
- if neg {
- res *= -1.0;
- }
- F64Value(res)
- } else {
- if neg {
- let res = (res as i64).wrapping_neg();
- // Make sure we didn't underflow.
- if res > 0 {
- Error(SyntaxError(InvalidNumber, self.line, self.col))
- } else {
- I64Value(res)
- }
- } else {
- U64Value(res)
- }
- }
- }
- fn parse_u64(&mut self) -> Result<u64, ParserError> {
- let mut accum = 0u64;
- let last_accum = 0; // necessary to detect overflow.
- match self.ch_or_null() {
- '0' => {
- self.bump();
- // A leading '0' must be the only digit before the decimal …
Large files files are truncated, but you can click here to view the full file