rustc-serialize-0.3.24/.gitignore01006000001750000175000000000024124423607050015125 0ustar0000000000000000/target /Cargo.lock rustc-serialize-0.3.24/.travis.yml01006640001750000175000000001062130141131300015243 0ustar0000000000000000language: rust rust: - 1.0.0 - stable - beta - nightly sudo: false before_script: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo build --verbose - cargo test --verbose - cargo doc --no-deps after_success: - travis-cargo --only nightly doc-upload env: global: secure: "kJnqqAXRl0C7Afx0c8Y3vA6TAEZsxlasu7eIZMdCbNS4N1+Rwh0jNTa2jy2D3CQCrzW5OCefnkpkPTu8mADrAjedM4p/9X5UXZi0sgg2lzCgfGwrRzitTnyPDkdYidiu4QeC/r0WPC8lYZKHkJXYhF8bZgchB9ypnZ6LAHCcDkA=" notifications: email: on_success: never rustc-serialize-0.3.24/Cargo.toml01006640001750000175000000002123130764112740015103 0ustar0000000000000000# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "rustc-serialize" version = "0.3.24" authors = ["The Rust Project Developers"] description = "Generic serialization/deserialization support corresponding to the\n`derive(RustcEncodable, RustcDecodable)` mode in the compiler. Also includes\nsupport for hex, base64, and json encoding and decoding.\n" homepage = "https://github.com/rust-lang/rustc-serialize" documentation = "https://doc.rust-lang.org/rustc-serialize" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/rust-lang/rustc-serialize" [dev-dependencies.rand] version = "0.3" rustc-serialize-0.3.24/Cargo.toml.orig01006640001750000175000000001103130764112740016037 0ustar0000000000000000[package] name = "rustc-serialize" version = "0.3.24" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/rust-lang/rustc-serialize" homepage = "https://github.com/rust-lang/rustc-serialize" documentation = "https://doc.rust-lang.org/rustc-serialize" description = """ Generic serialization/deserialization support corresponding to the `derive(RustcEncodable, RustcDecodable)` mode in the compiler. Also includes support for hex, base64, and json encoding and decoding. """ [dev-dependencies] rand = "0.3" rustc-serialize-0.3.24/LICENSE-APACHE01006640001750000175000000025137124423607210015105 0ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. rustc-serialize-0.3.24/LICENSE-MIT01006640001750000175000000002057124423607210014611 0ustar0000000000000000Copyright (c) 2014 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rustc-serialize-0.3.24/README.md01006640001750000175000000001741130764103050014431 0ustar0000000000000000# rustc-serialize > **NOTE**: This crate is deprecated in favor of [`serde`]. No new feature > development will happen in this crate, although bug fixes proposed through PRs > will still be merged. It is very highly recommended by the Rust Library Team > that you use [`serde`], not this crate. [`serde`]: https://serde.rs Serialization and deserialization support provided by the compiler in the form of `derive(RustcEncodable, RustcDecodable)`. [![Linux Build Status](https://travis-ci.org/rust-lang-nursery/rustc-serialize.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rustc-serialize) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ka194de75aapwpft?svg=true)](https://ci.appveyor.com/project/alexcrichton/rustc-serialize) [Documentation](https://doc.rust-lang.org/rustc-serialize) ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] rustc-serialize = "0.3" ``` and this to your crate root: ```rust extern crate rustc_serialize; ``` rustc-serialize-0.3.24/appveyor.yml01006640001750000175000000000736125567414560015565 0ustar0000000000000000environment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc - TARGET: i686-pc-windows-gnu install: - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - SET PATH=%PATH%;C:\MinGW\bin - rustc -V - cargo -V build: false test_script: - cargo test --verbose rustc-serialize-0.3.24/benches/base64.rs01006640001750000175000000002500125346231640016214 0ustar0000000000000000#![feature(test)] extern crate test; extern crate rustc_serialize; use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD}; use test::Bencher; #[bench] fn bench_to_base64(b: &mut Bencher) { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; b.iter(|| { s.as_bytes().to_base64(STANDARD); }); b.bytes = s.len() as u64; } #[bench] fn bench_from_base64(b: &mut Bencher) { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; let sb = s.as_bytes().to_base64(STANDARD); b.iter(|| { sb.from_base64().unwrap(); }); b.bytes = sb.len() as u64; } #[bench] fn bench_to_base64_large(b: &mut Bencher) { let s: Vec<_> = (0..10000).map(|i| ((i as u32 * 12345) % 256) as u8).collect(); b.iter(|| { s.to_base64(STANDARD); }); b.bytes = s.len() as u64; } #[bench] fn bench_from_base64_large(b: &mut Bencher) { let s: Vec<_> = (0..10000).map(|i| ((i as u32 * 12345) % 256) as u8).collect(); let sb = s.to_base64(STANDARD); b.iter(|| { sb.from_base64().unwrap(); }); b.bytes = sb.len() as u64; } rustc-serialize-0.3.24/benches/hex.rs01006640001750000175000000001440125346250750015721 0ustar0000000000000000#![feature(test)] extern crate test; extern crate rustc_serialize; use test::Bencher; use rustc_serialize::hex::{FromHex, ToHex}; #[bench] fn bench_to_hex(b: &mut Bencher) { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; b.iter(|| { s.as_bytes().to_hex(); }); b.bytes = s.len() as u64; } #[bench] fn bench_from_hex(b: &mut Bencher) { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; let sb = s.as_bytes().to_hex(); b.iter(|| { sb.from_hex().unwrap(); }); b.bytes = sb.len() as u64; } rustc-serialize-0.3.24/benches/json.rs01006640001750000175000000003463125260232460016106 0ustar0000000000000000#![feature(test)] extern crate test; extern crate rustc_serialize; use std::string; use rustc_serialize::json::{Json, Parser}; use test::Bencher; #[bench] fn bench_streaming_small(b: &mut Bencher) { b.iter( || { let mut parser = Parser::new( r#"{ "a": 1.0, "b": [ true, "foo\nbar", { "c": {"d": null} } ] }"#.chars() ); loop { match parser.next() { None => return, _ => {} } } }); } #[bench] fn bench_small(b: &mut Bencher) { b.iter( || { let _ = Json::from_str(r#"{ "a": 1.0, "b": [ true, "foo\nbar", { "c": {"d": null} } ] }"#); }); } #[bench] fn bench_decode_hex_escape(b: &mut Bencher) { let mut src = "\"".to_string(); for _ in 0..10 { src.push_str("\\uF975\\uf9bc\\uF9A0\\uF9C4\\uF975\\uf9bc\\uF9A0\\uF9C4"); } src.push_str("\""); b.iter( || { let _ = Json::from_str(&src); }); } fn big_json() -> string::String { let mut src = "[\n".to_string(); for _ in 0..500 { src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \ [1,2,3]},"#); } src.push_str("{}]"); return src; } #[bench] fn bench_streaming_large(b: &mut Bencher) { let src = big_json(); b.iter( || { let mut parser = Parser::new(src.chars()); loop { match parser.next() { None => return, _ => {} } } }); } #[bench] fn bench_large(b: &mut Bencher) { let src = big_json(); b.iter( || { let _ = Json::from_str(&src); }); } rustc-serialize-0.3.24/src/base64.rs01006640001750000175000000041024130764100500015366 0ustar0000000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // // ignore-lexer-test FIXME #15679 //! Base64 binary-to-text encoding pub use self::FromBase64Error::*; pub use self::CharacterSet::*; use std::fmt; use std::error; /// Available encoding character sets #[derive(Clone, Copy, Debug)] pub enum CharacterSet { /// The standard character set (uses `+` and `/`) Standard, /// The URL safe character set (uses `-` and `_`) UrlSafe } /// Available newline types #[derive(Clone, Copy, Debug)] pub enum Newline { /// A linefeed (i.e. Unix-style newline) LF, /// A carriage return and a linefeed (i.e. Windows-style newline) CRLF } /// Contains configuration parameters for `to_base64`. #[derive(Clone, Copy, Debug)] pub struct Config { /// Character set to use pub char_set: CharacterSet, /// Newline to use pub newline: Newline, /// True to pad output with `=` characters pub pad: bool, /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping pub line_length: Option } /// Configuration for RFC 4648 standard base64 encoding pub static STANDARD: Config = Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: None}; /// Configuration for RFC 4648 base64url encoding pub static URL_SAFE: Config = Config {char_set: UrlSafe, newline: Newline::CRLF, pad: false, line_length: None}; /// Configuration for RFC 2045 MIME base64 encoding pub static MIME: Config = Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: Some(76)}; static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789+/"; static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789-_"; /// A trait for converting a value to base64 encoding. pub trait ToBase64 { /// Converts the value of `self` to a base64 value following the specified /// format configuration, returning the owned string. fn to_base64(&self, config: Config) -> String; } impl ToBase64 for [u8] { /// Turn a vector of `u8` bytes into a base64 string. /// /// # Example /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::base64::{ToBase64, STANDARD}; /// /// fn main () { /// let str = [52,32].to_base64(STANDARD); /// println!("base 64 output: {:?}", str); /// } /// ``` fn to_base64(&self, config: Config) -> String { let bytes = match config.char_set { Standard => STANDARD_CHARS, UrlSafe => URLSAFE_CHARS }; let len = self.len(); let newline = match config.newline { Newline::LF => "\n", Newline::CRLF => "\r\n", }; // Preallocate memory. let mut prealloc_len = (len + 2) / 3 * 4; if let Some(line_length) = config.line_length { let num_lines = match prealloc_len { 0 => 0, n => (n - 1) / line_length }; prealloc_len += num_lines * newline.bytes().count(); } let mut out_bytes = vec![b'='; prealloc_len]; // Deal with padding bytes let mod_len = len % 3; // Use iterators to reduce branching { let mut cur_length = 0; let mut s_in = self[..len - mod_len].iter().map(|&x| x as u32); let mut s_out = out_bytes.iter_mut(); // Convenient shorthand let enc = |val| bytes[val as usize]; let mut write = |val| *s_out.next().unwrap() = val; // Iterate though blocks of 4 while let (Some(first), Some(second), Some(third)) = (s_in.next(), s_in.next(), s_in.next()) { // Line break if needed if let Some(line_length) = config.line_length { if cur_length >= line_length { for b in newline.bytes() { write(b) }; cur_length = 0; } } let n = first << 16 | second << 8 | third; // This 24-bit number gets separated into four 6-bit numbers. write(enc((n >> 18) & 63)); write(enc((n >> 12) & 63)); write(enc((n >> 6 ) & 63)); write(enc((n >> 0 ) & 63)); cur_length += 4; } // Line break only needed if padding is required if mod_len != 0 { if let Some(line_length) = config.line_length { if cur_length >= line_length { for b in newline.bytes() { write(b) }; } } } // Heh, would be cool if we knew this was exhaustive // (the dream of bounded integer types) match mod_len { 0 => (), 1 => { let n = (self[len-1] as u32) << 16; write(enc((n >> 18) & 63)); write(enc((n >> 12) & 63)); } 2 => { let n = (self[len-2] as u32) << 16 | (self[len-1] as u32) << 8; write(enc((n >> 18) & 63)); write(enc((n >> 12) & 63)); write(enc((n >> 6 ) & 63)); } _ => panic!("Algebra is broken, please alert the math police") } } // We get padding for "free", so only have to drop it if unwanted. if !config.pad { while let Some(&b'=') = out_bytes.last() { out_bytes.pop(); } } unsafe { String::from_utf8_unchecked(out_bytes) } } } impl<'a, T: ?Sized + ToBase64> ToBase64 for &'a T { fn to_base64(&self, config: Config) -> String { (**self).to_base64(config) } } /// A trait for converting from base64 encoded values. pub trait FromBase64 { /// Converts the value of `self`, interpreted as base64 encoded data, into /// an owned vector of bytes, returning the vector. fn from_base64(&self) -> Result, FromBase64Error>; } /// Errors that can occur when decoding a base64 encoded string #[derive(Clone, Copy)] pub enum FromBase64Error { /// The input contained a character not part of the base64 format InvalidBase64Byte(u8, usize), /// The input had an invalid length InvalidBase64Length, } impl fmt::Debug for FromBase64Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { InvalidBase64Byte(ch, idx) => write!(f, "Invalid character '{}' at position {}", ch, idx), InvalidBase64Length => write!(f, "Invalid length"), } } } impl error::Error for FromBase64Error { fn description(&self) -> &str { match *self { InvalidBase64Byte(_, _) => "invalid character", InvalidBase64Length => "invalid length", } } } impl fmt::Display for FromBase64Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self, f) } } impl FromBase64 for str { /// Convert any base64 encoded string (literal, `@`, `&`, or `~`) /// to the byte values it encodes. /// /// You can use the `String::from_utf8` function to turn a `Vec` into a /// string with characters corresponding to those values. /// /// # Example /// /// This converts a string literal to base64 and back. /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::base64::{ToBase64, FromBase64, STANDARD}; /// /// fn main () { /// let hello_str = b"Hello, World".to_base64(STANDARD); /// println!("base64 output: {}", hello_str); /// let res = hello_str.from_base64(); /// if res.is_ok() { /// let opt_bytes = String::from_utf8(res.unwrap()); /// if opt_bytes.is_ok() { /// println!("decoded from base64: {:?}", opt_bytes.unwrap()); /// } /// } /// } /// ``` #[inline] fn from_base64(&self) -> Result, FromBase64Error> { self.as_bytes().from_base64() } } impl FromBase64 for [u8] { fn from_base64(&self) -> Result, FromBase64Error> { let mut r = Vec::with_capacity(self.len()); let mut buf: u32 = 0; let mut modulus = 0; let mut it = self.iter(); for byte in it.by_ref() { let code = DECODE_TABLE[*byte as usize]; if code >= SPECIAL_CODES_START { match code { NEWLINE_CODE => continue, EQUALS_CODE => break, INVALID_CODE => return Err(InvalidBase64Byte( *byte, (byte as *const _ as usize) - self.as_ptr() as usize)), _ => unreachable!(), } } buf = (buf | code as u32) << 6; modulus += 1; if modulus == 4 { modulus = 0; r.push((buf >> 22) as u8); r.push((buf >> 14) as u8); r.push((buf >> 6 ) as u8); } } for byte in it { match *byte { b'=' | b'\r' | b'\n' => continue, _ => return Err(InvalidBase64Byte( *byte, (byte as *const _ as usize) - self.as_ptr() as usize)), } } match modulus { 2 => { r.push((buf >> 10) as u8); } 3 => { r.push((buf >> 16) as u8); r.push((buf >> 8 ) as u8); } 0 => (), _ => return Err(InvalidBase64Length), } Ok(r) } } impl<'a, T: ?Sized + FromBase64> FromBase64 for &'a T { fn from_base64(&self) -> Result, FromBase64Error> { (**self).from_base64() } } /// Base64 decoding lookup table, generated using: /// /// ``` /// let mut ch = 0u8; /// for ch in 0..255 { /// let mut ch = ch as u8; /// let code = match ch { /// b'A'...b'Z' => ch - 0x41, /// b'a'...b'z' => ch - 0x47, /// b'0'...b'9' => ch + 0x04, /// b'+' | b'-' => 0x3E, /// b'/' | b'_' => 0x3F, /// b'=' => 0xFE, /// b'\r' | b'\n' => 0xFD, /// _ => 0xFF, /// }; /// print!("0x{:02X}, ", code); /// if ch % 16 == 15 { println!(""); } /// else if ch == 0xFF { break; } /// ch += 1; /// } /// println!(""); /// ``` const DECODE_TABLE: [u8; 256] = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0x3E, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ]; const INVALID_CODE: u8 = 0xFF; const EQUALS_CODE: u8 = 0xFE; const NEWLINE_CODE: u8 = 0xFD; const SPECIAL_CODES_START: u8 = NEWLINE_CODE; #[cfg(test)] mod tests { use base64::{Config, Newline, FromBase64, ToBase64, STANDARD, URL_SAFE}; #[test] fn test_to_base64_basic() { assert_eq!("".as_bytes().to_base64(STANDARD), ""); assert_eq!("f".as_bytes().to_base64(STANDARD), "Zg=="); assert_eq!("fo".as_bytes().to_base64(STANDARD), "Zm8="); assert_eq!("foo".as_bytes().to_base64(STANDARD), "Zm9v"); assert_eq!("foob".as_bytes().to_base64(STANDARD), "Zm9vYg=="); assert_eq!("fooba".as_bytes().to_base64(STANDARD), "Zm9vYmE="); assert_eq!("foobar".as_bytes().to_base64(STANDARD), "Zm9vYmFy"); } #[test] fn test_to_base64_crlf_line_break() { assert!(![0; 1000].to_base64(Config {line_length: None, ..STANDARD}) .contains("\r\n")); assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), ..STANDARD}), "Zm9v\r\nYmFy"); } #[test] fn test_to_base64_lf_line_break() { assert!(![0; 1000].to_base64(Config {line_length: None, newline: Newline::LF, ..STANDARD}) .contains("\n")); assert_eq!(b"foobar".to_base64(Config {line_length: Some(4), newline: Newline::LF, ..STANDARD}), "Zm9v\nYmFy"); } #[test] fn test_to_base64_padding() { assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg"); assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zm8"); } #[test] fn test_to_base64_url_safe() { assert_eq!([251, 255].to_base64(URL_SAFE), "-_8"); assert_eq!([251, 255].to_base64(STANDARD), "+/8="); } #[test] fn test_to_base64_empty_line_length() { [].to_base64(Config {line_length: Some(72), ..STANDARD}); } #[test] fn test_from_base64_basic() { assert_eq!("".from_base64().unwrap(), b""); assert_eq!("Zg==".from_base64().unwrap(), b"f"); assert_eq!("Zm8=".from_base64().unwrap(), b"fo"); assert_eq!("Zm9v".from_base64().unwrap(), b"foo"); assert_eq!("Zm9vYg==".from_base64().unwrap(), b"foob"); assert_eq!("Zm9vYmE=".from_base64().unwrap(), b"fooba"); assert_eq!("Zm9vYmFy".from_base64().unwrap(), b"foobar"); } #[test] fn test_from_base64_bytes() { assert_eq!(b"Zm9vYmFy".from_base64().unwrap(), b"foobar"); } #[test] fn test_from_base64_newlines() { assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(), b"foobar"); assert_eq!("Zm9vYg==\r\n".from_base64().unwrap(), b"foob"); assert_eq!("Zm9v\nYmFy".from_base64().unwrap(), b"foobar"); assert_eq!("Zm9vYg==\n".from_base64().unwrap(), b"foob"); } #[test] fn test_from_base64_urlsafe() { assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap()); } #[test] fn test_from_base64_invalid_char() { assert!("Zm$=".from_base64().is_err()); assert!("Zg==$".from_base64().is_err()); } #[test] fn test_from_base64_invalid_padding() { assert!("Z===".from_base64().is_err()); } #[test] fn test_base64_random() { use rand::{thread_rng, Rng}; for _ in 0..1000 { let times = thread_rng().gen_range(1, 100); let v = thread_rng().gen_iter::().take(times) .collect::>(); assert_eq!(v.to_base64(STANDARD) .from_base64() .unwrap(), v); } } } rustc-serialize-0.3.24/src/collection_impls.rs01006640001750000175000000012772127461563360017672 0ustar0000000000000000// Copyright 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Implementations of serialization for structures found in libcollections use std::hash::Hash; use {Decodable, Encodable, Decoder, Encoder, cap_capacity}; use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet}; impl< T: Encodable > Encodable for LinkedList { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { try!(s.emit_seq_elt(i, |s| e.encode(s))); } Ok(()) }) } } impl Decodable for LinkedList { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut list = LinkedList::new(); for i in 0..len { list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } Ok(list) }) } } impl Encodable for VecDeque { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { try!(s.emit_seq_elt(i, |s| e.encode(s))); } Ok(()) }) } } impl Decodable for VecDeque { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut deque: VecDeque = VecDeque::new(); for i in 0..len { deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } Ok(deque) }) } } impl< K: Encodable + Ord, V: Encodable > Encodable for BTreeMap { fn encode(&self, e: &mut S) -> Result<(), S::Error> { e.emit_map(self.len(), |e| { let mut i = 0; for (key, val) in self.iter() { try!(e.emit_map_elt_key(i, |e| key.encode(e))); try!(e.emit_map_elt_val(i, |e| val.encode(e))); i += 1; } Ok(()) }) } } impl< K: Decodable + Ord, V: Decodable > Decodable for BTreeMap { fn decode(d: &mut D) -> Result, D::Error> { d.read_map(|d, len| { let mut map = BTreeMap::new(); for i in 0..len { let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d))); let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d))); map.insert(key, val); } Ok(map) }) } } impl< T: Encodable + Ord > Encodable for BTreeSet { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { let mut i = 0; for e in self.iter() { try!(s.emit_seq_elt(i, |s| e.encode(s))); i += 1; } Ok(()) }) } } impl< T: Decodable + Ord > Decodable for BTreeSet { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut set = BTreeSet::new(); for i in 0..len { set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } Ok(set) }) } } impl Encodable for HashMap where K: Encodable + Hash + Eq, V: Encodable, { fn encode(&self, e: &mut E) -> Result<(), E::Error> { e.emit_map(self.len(), |e| { let mut i = 0; for (key, val) in self.iter() { try!(e.emit_map_elt_key(i, |e| key.encode(e))); try!(e.emit_map_elt_val(i, |e| val.encode(e))); i += 1; } Ok(()) }) } } impl Decodable for HashMap where K: Decodable + Hash + Eq, V: Decodable, { fn decode(d: &mut D) -> Result, D::Error> { d.read_map(|d, len| { let mut map = HashMap::with_capacity(cap_capacity::<(K, V)>(len)); for i in 0..len { let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d))); let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d))); map.insert(key, val); } Ok(map) }) } } impl Encodable for HashSet where T: Encodable + Hash + Eq { fn encode(&self, s: &mut E) -> Result<(), E::Error> { s.emit_seq(self.len(), |s| { let mut i = 0; for e in self.iter() { try!(s.emit_seq_elt(i, |s| e.encode(s))); i += 1; } Ok(()) }) } } impl Decodable for HashSet where T: Decodable + Hash + Eq, { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut set = HashSet::with_capacity(cap_capacity::(len)); for i in 0..len { set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } Ok(set) }) } } rustc-serialize-0.3.24/src/hex.rs01006640001750000175000000014105130764100500015066 0ustar0000000000000000// Copyright 2013-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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // // ignore-lexer-test FIXME #15679 //! Hex binary-to-text encoding pub use self::FromHexError::*; use std::fmt; use std::error; /// A trait for converting a value to hexadecimal encoding pub trait ToHex { /// Converts the value of `self` to a hex value, returning the owned /// string. fn to_hex(&self) -> String; } static CHARS: &'static[u8] = b"0123456789abcdef"; impl ToHex for [u8] { /// Turn a vector of `u8` bytes into a hexadecimal string. /// /// # Example /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::hex::ToHex; /// /// fn main () { /// let str = [52,32].to_hex(); /// println!("{}", str); /// } /// ``` fn to_hex(&self) -> String { let mut v = Vec::with_capacity(self.len() * 2); for &byte in self.iter() { v.push(CHARS[(byte >> 4) as usize]); v.push(CHARS[(byte & 0xf) as usize]); } unsafe { String::from_utf8_unchecked(v) } } } impl<'a, T: ?Sized + ToHex> ToHex for &'a T { fn to_hex(&self) -> String { (**self).to_hex() } } /// A trait for converting hexadecimal encoded values pub trait FromHex { /// Converts the value of `self`, interpreted as hexadecimal encoded data, /// into an owned vector of bytes, returning the vector. fn from_hex(&self) -> Result, FromHexError>; } /// Errors that can occur when decoding a hex encoded string #[derive(Clone, Copy)] pub enum FromHexError { /// The input contained a character not part of the hex format InvalidHexCharacter(char, usize), /// The input had an invalid length InvalidHexLength, } impl fmt::Debug for FromHexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { InvalidHexCharacter(ch, idx) => write!(f, "Invalid character '{}' at position {}", ch, idx), InvalidHexLength => write!(f, "Invalid input length"), } } } impl error::Error for FromHexError { fn description(&self) -> &str { match *self { InvalidHexCharacter(_, _) => "invalid character", InvalidHexLength => "invalid length", } } } impl fmt::Display for FromHexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self, f) } } impl FromHex for str { /// Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`) /// to the byte values it encodes. /// /// You can use the `String::from_utf8` function to turn a /// `Vec` into a string with characters corresponding to those values. /// /// # Example /// /// This converts a string literal to hexadecimal and back. /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::hex::{FromHex, ToHex}; /// /// fn main () { /// let hello_str = "Hello, World".as_bytes().to_hex(); /// println!("{}", hello_str); /// let bytes = hello_str.from_hex().unwrap(); /// println!("{:?}", bytes); /// let result_str = String::from_utf8(bytes).unwrap(); /// println!("{}", result_str); /// } /// ``` fn from_hex(&self) -> Result, FromHexError> { // This may be an overestimate if there is any whitespace let mut b = Vec::with_capacity(self.len() / 2); let mut modulus = 0; let mut buf = 0; for (idx, byte) in self.bytes().enumerate() { buf <<= 4; match byte { b'A'...b'F' => buf |= byte - b'A' + 10, b'a'...b'f' => buf |= byte - b'a' + 10, b'0'...b'9' => buf |= byte - b'0', b' '|b'\r'|b'\n'|b'\t' => { buf >>= 4; continue } _ => { let ch = self[idx..].chars().next().unwrap(); return Err(InvalidHexCharacter(ch, idx)) } } modulus += 1; if modulus == 2 { modulus = 0; b.push(buf); } } match modulus { 0 => Ok(b.into_iter().collect()), _ => Err(InvalidHexLength), } } } impl<'a, T: ?Sized + FromHex> FromHex for &'a T { fn from_hex(&self) -> Result, FromHexError> { (**self).from_hex() } } #[cfg(test)] mod tests { use hex::{FromHex, ToHex}; #[test] pub fn test_to_hex() { assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172"); } #[test] pub fn test_from_hex_okay() { assert_eq!("666f6f626172".from_hex().unwrap(), b"foobar"); assert_eq!("666F6F626172".from_hex().unwrap(), b"foobar"); } #[test] pub fn test_from_hex_odd_len() { assert!("666".from_hex().is_err()); assert!("66 6".from_hex().is_err()); } #[test] pub fn test_from_hex_invalid_char() { assert!("66y6".from_hex().is_err()); } #[test] pub fn test_from_hex_ignores_whitespace() { assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(), b"foobar"); } #[test] pub fn test_to_hex_all_bytes() { for i in 0..256 { assert_eq!([i as u8].to_hex(), format!("{:02x}", i)); } } #[test] pub fn test_from_hex_all_bytes() { for i in 0..256 { let ii: &[u8] = &[i as u8]; assert_eq!(format!("{:02x}", i).from_hex().unwrap(), ii); assert_eq!(format!("{:02X}", i).from_hex().unwrap(), ii); } } } rustc-serialize-0.3.24/src/json.rs01006640001750000175000000405523130622512540015267 0ustar0000000000000000// 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 or the MIT license // , 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. //! JSON parsing and serialization //! //! # What is JSON? //! //! JSON (JavaScript Object Notation) is a way to write data in Javascript. //! Like XML, it allows encoding 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): //! //! * `I64`: equivalent to rust's `i64` //! * `U64`: equivalent to rust's `u64` //! * `F64`: equivalent to rust's `f64` //! * `Boolean`: equivalent to rust's `bool` //! * `String`: equivalent to rust's `String` //! * `Array`: equivalent to rust's `Vec`, but also allowing objects of //! different types in the //! same array //! * `Object`: equivalent to rust's `BTreeMap` //! * `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 `rustc_serialize::Encodable` trait. To be //! able to decode a piece of data, it must implement the //! `rustc_serialize::Decodable` 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 `Encodable` 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 //! extern crate rustc_serialize; //! use rustc_serialize::json; //! //! // Automatically generate `RustcDecodable` and `RustcEncodable` trait //! // implementations //! #[derive(RustcDecodable, RustcEncodable)] //! pub struct TestStruct { //! data_int: u8, //! data_str: String, //! data_vector: Vec, //! } //! //! 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 below use the `ToJson` trait to generate the JSON string, //! which is required for custom mappings. //! //! ### Simple example of `ToJson` usage //! //! ```rust //! extern crate rustc_serialize; //! use rustc_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(RustcEncodable)] //! 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 //! extern crate rustc_serialize; //! use std::collections::BTreeMap; //! use rustc_serialize::json::{self, Json, ToJson}; //! //! // Only generate `Decodable` trait implementation //! #[derive(RustcDecodable)] //! pub struct TestStruct { //! data_int: u8, //! data_str: String, //! data_vector: Vec, //! } //! //! // 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(); //! } //! ``` //! //! ## Parsing a `str` to `Json` and reading the result //! //! ```rust //! extern crate rustc_serialize; //! use rustc_serialize::json::Json; //! //! fn main() { //! let data = Json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap(); //! println!("data: {}", data); //! // data: {"bar":"baz","foo":13} //! println!("object? {}", data.is_object()); //! // object? true //! //! let obj = data.as_object().unwrap(); //! let foo = obj.get("foo").unwrap(); //! //! println!("array? {:?}", foo.as_array()); //! // array? None //! println!("u64? {:?}", foo.as_u64()); //! // u64? Some(13u64) //! //! for (key, value) in obj.iter() { //! println!("{}: {}", key, match *value { //! Json::U64(v) => format!("{} (u64)", v), //! Json::String(ref v) => format!("{} (string)", v), //! _ => format!("other") //! }); //! } //! // bar: baz (string) //! // foo: 13 (u64) //! } //! ``` //! //! # The status of this library //! //! While this library is the standard way of working with JSON in Rust, //! there is a next-generation library called Serde that's in the works (it's //! faster, overcomes some design limitations of rustc-serialize and has more //! features). You might consider using it when starting a new project or //! evaluating Rust JSON performance. use self::JsonEvent::*; use self::ErrorCode::*; use self::ParserError::*; use self::DecoderError::*; use self::ParserState::*; use self::InternalStackElement::*; use std::collections::{HashMap, BTreeMap}; use std::error::Error as StdError; use std::i64; use std::io::prelude::*; use std::mem::swap; use std::ops::Index; use std::str::FromStr; use std::string; use std::{char, f64, fmt, io, str}; 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; pub type Object = BTreeMap; 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 } /// The errors that can arise while parsing a JSON stream. #[derive(Clone, Copy, PartialEq)] pub enum ErrorCode { InvalidSyntax, InvalidNumber, EOFWhileParsingObject, EOFWhileParsingArray, EOFWhileParsingValue, EOFWhileParsingString, KeyMustBeAString, ExpectedColon, TrailingCharacters, TrailingComma, InvalidEscape, InvalidUnicodeCodePoint, LoneLeadingSurrogateInHexEscape, UnexpectedEndOfHexEscape, UnrecognizedHex, NotFourDigit, ControlCharacterInString, NotUtf8, } #[derive(Debug)] pub enum ParserError { /// msg, line, col SyntaxError(ErrorCode, usize, usize), IoError(io::Error), } impl PartialEq for ParserError { fn eq(&self, other: &ParserError) -> bool { match (self, other) { (&SyntaxError(msg0, line0, col0), &SyntaxError(msg1, line1, col1)) => msg0 == msg1 && line0 == line1 && col0 == col1, (&IoError(_), _) => false, (_, &IoError(_)) => false, } } } // Builder and Parser have the same errors. pub type BuilderError = ParserError; #[derive(PartialEq, Debug)] pub enum DecoderError { ParseError(ParserError), ExpectedError(string::String, string::String), MissingFieldError(string::String), UnknownVariantError(string::String), ApplicationError(string::String), EOF, } #[derive(Copy, Debug)] pub enum EncoderError { FmtError(fmt::Error), BadHashmapKey, } impl PartialEq for EncoderError { fn eq(&self, other: &EncoderError) -> bool { match (*self, *other) { (EncoderError::FmtError(_), EncoderError::FmtError(_)) => true, (EncoderError::BadHashmapKey, EncoderError::BadHashmapKey) => true, _ => false, } } } impl Clone for EncoderError { fn clone(&self) -> Self { *self } } /// 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)", ControlCharacterInString => "unescaped control character in string", 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(s: &str) -> DecodeResult { let json = match Json::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(object: &T) -> EncodeResult { let mut s = String::new(); { let mut encoder = Encoder::new(&mut s); try!(object.encode(&mut encoder)); } Ok(s) } impl fmt::Debug for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { error_str(*self).fmt(f) } } impl StdError for DecoderError { fn description(&self) -> &str { "decoder error" } fn cause(&self) -> Option<&StdError> { match *self { DecoderError::ParseError(ref e) => Some(e), _ => None, } } } impl fmt::Display for DecoderError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self, f) } } impl From for DecoderError { fn from(err: ParserError) -> DecoderError { ParseError(From::from(err)) } } impl StdError for ParserError { fn description(&self) -> &str { "failed to parse json" } } impl fmt::Display for ParserError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self, f) } } impl From for ParserError { fn from(err: io::Error) -> ParserError { IoError(err) } } impl StdError for EncoderError { fn description(&self) -> &str { "encoder error" } } impl fmt::Display for EncoderError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self, f) } } impl From for EncoderError { fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } } pub type EncodeResult = Result; pub type DecodeResult = Result; fn escape_str(wr: &mut fmt::Write, v: &str) -> EncodeResult<()> { try!(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 { try!(wr.write_str(&v[start..i])); } try!(wr.write_str(escaped)); start = i + 1; } if start != v.len() { try!(wr.write_str(&v[start..])); } try!(wr.write_str("\"")); Ok(()) } fn escape_char(writer: &mut fmt::Write, v: char) -> EncodeResult<()> { let mut buf = [0; 4]; let _ = write!(&mut &mut buf[..], "{}", v); let buf = unsafe { str::from_utf8_unchecked(&buf[..v.len_utf8()]) }; escape_str(writer, buf) } fn spaces(wr: &mut fmt::Write, n: u32) -> EncodeResult<()> { let mut n = n as usize; const BUF: &'static str = " "; while n >= BUF.len() { try!(wr.write_str(BUF)); n -= BUF.len(); } if n > 0 { try!(wr.write_str(&BUF[..n])); } Ok(()) } fn fmt_number_or_null(v: f64) -> string::String { use std::num::FpCategory::{Nan, Infinite}; match v.classify() { Nan | Infinite => "null".to_string(), _ => { let s = v.to_string(); if s.contains(".") {s} else {s + ".0"} } } } macro_rules! emit_enquoted_if_mapkey { ($enc:ident,$e:expr) => { if $enc.is_emitting_map_key { try!(write!($enc.writer, "\"{}\"", $e)); Ok(()) } else { try!(write!($enc.writer, "{}", $e)); Ok(()) } } } enum EncodingFormat { Compact, Pretty { curr_indent: u32, indent: u32 } } /// A structure for implementing serialization to JSON. pub struct Encoder<'a> { writer: &'a mut (fmt::Write+'a), format : EncodingFormat, is_emitting_map_key: bool, } impl<'a> Encoder<'a> { /// Creates a new encoder whose output will be written in human-readable /// JSON to the specified writer pub fn new_pretty(writer: &'a mut fmt::Write) -> Encoder<'a> { Encoder { writer: writer, format: EncodingFormat::Pretty { curr_indent: 0, indent: 2, }, is_emitting_map_key: false, } } /// Creates a new encoder whose output will be written in compact /// JSON to the specified writer pub fn new(writer: &'a mut fmt::Write) -> Encoder<'a> { Encoder { writer: writer, format: EncodingFormat::Compact, 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, new_indent: u32) -> Result<(), ()> { if let EncodingFormat::Pretty{ref mut curr_indent, ref mut indent} = self.format { // self.indent very well could be 0 so we need to use checked division. let level = curr_indent.checked_div(*indent).unwrap_or(0); *indent = new_indent; *curr_indent = level * *indent; Ok(()) } else { Err(()) } } } 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); } try!(write!(self.writer, "null")); Ok(()) } fn emit_usize(&mut self, v: usize) -> 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_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 { try!(write!(self.writer, "true")); } else { try!(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(&mut self, _name: &str, f: F) -> EncodeResult<()> where F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>, { f(self) } fn emit_enum_variant(&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); } if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { try!(write!(self.writer, "{{\n")); *curr_indent += indent; try!(spaces(self.writer, *curr_indent)); try!(write!(self.writer, "\"variant\": ")); try!(escape_str(self.writer, name)); try!(write!(self.writer, ",\n")); try!(spaces(self.writer, *curr_indent)); try!(write!(self.writer, "\"fields\": [\n")); *curr_indent += indent; } else { try!(write!(self.writer, "{{\"variant\":")); try!(escape_str(self.writer, name)); try!(write!(self.writer, ",\"fields\":[")); } try!(f(self)); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent -= indent; try!(write!(self.writer, "\n")); try!(spaces(self.writer, *curr_indent)); *curr_indent -= indent; try!(write!(self.writer, "]\n")); try!(spaces(self.writer, *curr_indent)); try!(write!(self.writer, "}}")); } else { try!(write!(self.writer, "]}}")); } Ok(()) } } fn emit_enum_variant_arg(&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 { try!(write!(self.writer, ",")); if let EncodingFormat::Pretty{..} = self.format { try!(write!(self.writer, "\n")); } } if let EncodingFormat::Pretty{curr_indent, ..} = self.format { try!(spaces(self.writer, curr_indent)); } f(self) } fn emit_enum_struct_variant(&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(&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(&mut self, _: &str, len: usize, f: F) -> EncodeResult<()> where F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } if len == 0 { try!(write!(self.writer, "{{}}")); } else { try!(write!(self.writer, "{{")); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent += indent; } try!(f(self)); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent -= indent; try!(write!(self.writer, "\n")); try!(spaces(self.writer, *curr_indent)); } try!(write!(self.writer, "}}")); } Ok(()) } fn emit_struct_field(&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 { try!(write!(self.writer, ",")); } if let EncodingFormat::Pretty{curr_indent, ..} = self.format { try!(write!(self.writer, "\n")); try!(spaces(self.writer, curr_indent)); } try!(escape_str(self.writer, name)); if let EncodingFormat::Pretty{..} = self.format { try!(write!(self.writer, ": ")); } else { try!(write!(self.writer, ":")); } f(self) } fn emit_tuple(&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(&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(&mut self, _: &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(&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(&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(&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(&mut self, len: usize, f: F) -> EncodeResult<()> where F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } if len == 0 { try!(write!(self.writer, "[]")); } else { try!(write!(self.writer, "[")); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent += indent; } try!(f(self)); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent -= indent; try!(write!(self.writer, "\n")); try!(spaces(self.writer, *curr_indent)); } try!(write!(self.writer, "]")); } Ok(()) } fn emit_seq_elt(&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 { try!(write!(self.writer, ",")); } if let EncodingFormat::Pretty{ref mut curr_indent, ..} = self.format { try!(write!(self.writer, "\n")); try!(spaces(self.writer, *curr_indent)); } f(self) } fn emit_map(&mut self, len: usize, f: F) -> EncodeResult<()> where F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } if len == 0 { try!(write!(self.writer, "{{}}")); } else { try!(write!(self.writer, "{{")); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent += indent; } try!(f(self)); if let EncodingFormat::Pretty{ref mut curr_indent, indent} = self.format { *curr_indent -= indent; try!(write!(self.writer, "\n")); try!(spaces(self.writer, *curr_indent)); } try!(write!(self.writer, "}}")); } Ok(()) } fn emit_map_elt_key(&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 { try!(write!(self.writer, ",")); } if let EncodingFormat::Pretty{curr_indent, ..} = self.format { try!(write!(self.writer, "\n")); try!(spaces(self.writer, curr_indent)); } self.is_emitting_map_key = true; try!(f(self)); self.is_emitting_map_key = false; Ok(()) } fn emit_map_elt_val(&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 let EncodingFormat::Pretty{..} = self.format { try!(write!(self.writer, ": ")); } else { try!(write!(self.writer, ":")); } f(self) } } impl Encodable for Json { fn encode(&self, e: &mut S) -> Result<(), S::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) -> AsJson { 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) -> AsPrettyJson { AsPrettyJson { inner: t, indent: None } } impl Json { /// Decodes a json value from an `&mut io::Read` pub fn from_reader(rdr: &mut io::Read) -> Result { let contents = { let mut c = Vec::new(); try!(rdr.read_to_end(&mut c)); c }; let s = match str::from_utf8(&contents).ok() { Some(s) => s, _ => return Err(SyntaxError(NotUtf8, 0, 0)) }; let mut builder = Builder::new(s.chars()); builder.build() } /// Decodes a json value from a string pub fn from_str(s: &str) -> Result { let mut builder = Builder::new(s.chars()); builder.build() } /// 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.iter() { 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.iter() { 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<'a>(&'a self) -> bool { self.as_object().is_some() } /// If the Json value is an Object, returns a reference to the associated BTreeMap. /// Returns None otherwise. pub fn as_object<'a>(&'a self) -> Option<&'a Object> { match self { &Json::Object(ref map) => Some(map), _ => None } } /// If the Json value is an Object, returns a mutable reference to the associated BTreeMap. /// Returns None otherwise. pub fn as_object_mut<'a>(&'a mut self) -> Option<&'a mut Object> { match self { &mut Json::Object(ref mut map) => Some(map), _ => None } } /// If the Json value is an Object, returns the associated BTreeMap. /// Returns None otherwise. pub fn into_object(self) -> Option { match self { Json::Object(map) => Some(map), _ => None } } /// Returns true if the Json value is an Array. Returns false otherwise. pub fn is_array<'a>(&'a self) -> bool { self.as_array().is_some() } /// If the Json value is an Array, returns a reference to the associated vector. /// Returns None otherwise. pub fn as_array<'a>(&'a self) -> Option<&'a Array> { match self { &Json::Array(ref array) => Some(&*array), _ => None } } /// If the Json value is an Array, returns a mutable reference to the associated vector. /// Returns None otherwise. pub fn as_array_mut<'a>(&'a mut self) -> Option<&'a mut Array> { match self { &mut Json::Array(ref mut list) => Some(list), _ => None } } /// If the Json value is an Array, returns the associated vector. /// Returns None otherwise. pub fn into_array(self) -> Option { match self { Json::Array(array) => Some(array), _ => None } } /// Returns true if the Json value is a String. Returns false otherwise. pub fn is_string<'a>(&'a 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<'a>(&'a self) -> Option<&'a 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 { match *self { Json::I64(n) => Some(n), Json::U64(n) if n >= i64::MAX as u64 => None, 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 { match *self { Json::I64(n) if n >= 0 => 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 { 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 { 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: &str) -> &Json { self.find(idx).unwrap() } } impl Index for Json { type Output = Json; fn index<'a>(&'a self, idx: usize) -> &'a 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, 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, str_buffer: Vec, } /// StackElements compose a Stack. /// For example, Key("foo"), Key("bar"), Index(3) and 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<'l>(&'l self, idx: usize) -> StackElement<'l> { 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 in 0..rhs.len() { if self.get(i) != rhs[i] { return false; } } return 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 in 0..rhs.len() { if self.get(i) != rhs[i] { return false; } } return 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 in 0..rhs.len() { if self.get(i + offset) != rhs[i] { return false; } } return true; } /// Returns the top-most element (if any). pub fn top<'l>(&'l self) -> Option> { return 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 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().iter() { self.str_buffer.push(*c); } } // Used by Parser to insert 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 { rdr: T, ch: Option, 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> Iterator for Parser { type Item = JsonEvent; fn next(&mut self) -> Option { 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)); } } return Some(self.parse()); } } impl> Parser { /// Creates the JSON parser. pub fn new(rdr: T) -> Parser { let mut p = Parser { rdr: rdr, ch: Some('\x00'), line: 1, col: 0, stack: Stack::new(), state: ParseStart, }; p.bump(); return p; } /// Provides access to the current position in the logical structure of the /// JSON stream. pub fn stack<'l>(&'l self) -> &'l Stack { return &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 { self.bump(); self.ch } fn ch_is(&self, c: char) -> bool { self.ch == Some(c) } fn error(&self, reason: ErrorCode) -> Result { 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 { // Make sure we don't underflow. if res > (i64::MAX as u64) + 1 { Error(SyntaxError(InvalidNumber, self.line, self.col)) } else if res == 0 { I64Value(res as i64) } else { I64Value((!res + 1) as i64) } } else { U64Value(res) } } } fn parse_u64(&mut self) -> Result { let mut accum: u64 = 0; match self.ch_or_null() { '0' => { self.bump(); // A leading '0' must be the only digit before the decimal point. match self.ch_or_null() { '0' ... '9' => return self.error(InvalidNumber), _ => () } }, '1' ... '9' => { while !self.eof() { match self.ch_or_null() { c @ '0' ... '9' => { macro_rules! try_or_invalid { ($e: expr) => { match $e { Some(v) => v, None => return self.error(InvalidNumber) } } } accum = try_or_invalid!(accum.checked_mul(10)); accum = try_or_invalid!(accum.checked_add((c as u64) - ('0' as u64))); self.bump(); } _ => break, } } } _ => return self.error(InvalidNumber), } Ok(accum) } fn parse_decimal(&mut self, mut res: f64) -> Result { self.bump(); // Make sure a digit follows the decimal place. match self.ch_or_null() { '0' ... '9' => (), _ => return self.error(InvalidNumber) } let mut dec = 1.0; let mut frac = 0.0; while !self.eof() { match self.ch_or_null() { c @ '0' ... '9' => { dec /= 10.0; frac += (((c as isize) - ('0' as isize)) as f64) * dec; self.bump(); } _ => break, } } res += frac; Ok(res) } fn parse_exponent(&mut self, mut res: f64) -> Result { self.bump(); let mut exp = 0; let mut neg_exp = false; if self.ch_is('+') { self.bump(); } else if self.ch_is('-') { self.bump(); neg_exp = true; } // Make sure a digit follows the exponent place. match self.ch_or_null() { '0' ... '9' => (), _ => return self.error(InvalidNumber) } while !self.eof() { match self.ch_or_null() { c @ '0' ... '9' => { exp *= 10; exp += (c as usize) - ('0' as usize); self.bump(); } _ => break } } let exp = 10_f64.powi(exp as i32); if neg_exp { res /= exp; } else { res *= exp; } Ok(res) } fn decode_hex_escape(&mut self) -> Result { let mut i = 0; let mut n = 0; while i < 4 { self.bump(); n = match self.ch_or_null() { c @ '0' ... '9' => n * 16 + ((c as u16) - ('0' as u16)), c @ 'a' ... 'f' => n * 16 + (10 + (c as u16) - ('a' as u16)), c @ 'A' ... 'F' => n * 16 + (10 + (c as u16) - ('A' as u16)), _ => return self.error(InvalidEscape) }; i += 1; } Ok(n) } fn parse_str(&mut self) -> Result { let mut escape = false; let mut res = string::String::new(); loop { self.bump(); if self.eof() { return self.error(EOFWhileParsingString); } if escape { match self.ch_or_null() { '"' => res.push('"'), '\\' => res.push('\\'), '/' => res.push('/'), 'b' => res.push('\x08'), 'f' => res.push('\x0c'), 'n' => res.push('\n'), 'r' => res.push('\r'), 't' => res.push('\t'), 'u' => match try!(self.decode_hex_escape()) { 0xDC00 ... 0xDFFF => { return self.error(LoneLeadingSurrogateInHexEscape) } // Non-BMP characters are encoded as a sequence of // two hex escapes, representing UTF-16 surrogates. n1 @ 0xD800 ... 0xDBFF => { match (self.next_char(), self.next_char()) { (Some('\\'), Some('u')) => (), _ => return self.error(UnexpectedEndOfHexEscape), } let n2 = try!(self.decode_hex_escape()); if n2 < 0xDC00 || n2 > 0xDFFF { return self.error(LoneLeadingSurrogateInHexEscape) } let c = (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000; res.push(char::from_u32(c).unwrap()); } n => match char::from_u32(n as u32) { Some(c) => res.push(c), None => return self.error(InvalidUnicodeCodePoint), }, }, _ => return self.error(InvalidEscape), } escape = false; } else if self.ch_is('\\') { escape = true; } else { match self.ch { Some('"') => { self.bump(); return Ok(res); }, Some(c) if c <= '\u{1F}' => return self.error(ControlCharacterInString), Some(c) => res.push(c), None => unreachable!() } } } } // Invoked at each iteration, consumes the stream until it has enough // information to return a JsonEvent. // Manages an internal state so that parsing can be interrupted and resumed. // Also keeps track of the position in the logical structure of the json // stream int the form of a stack that can be queried by the user using the // stack() method. fn parse(&mut self) -> JsonEvent { loop { // The only paths where the loop can spin a new iteration // are in the cases ParseArrayComma and ParseObjectComma if ',' // is parsed. In these cases the state is set to (respectively) // ParseArray(false) and ParseObject(false), which always return, // so there is no risk of getting stuck in an infinite loop. // All other paths return before the end of the loop's iteration. self.parse_whitespace(); match self.state { ParseStart => { return self.parse_start(); } ParseArray(first) => { return self.parse_array(first); } ParseArrayComma => { match self.parse_array_comma_or_end() { Some(evt) => { return evt; } None => {} } } ParseObject(first) => { return self.parse_object(first); } ParseObjectComma => { self.stack.pop(); if self.ch_is(',') { self.state = ParseObject(false); self.bump(); } else { return self.parse_object_end(); } } _ => { return self.error_event(InvalidSyntax); } } } } fn parse_start(&mut self) -> JsonEvent { let val = self.parse_value(); self.state = match val { Error(_) => ParseFinished, ArrayStart => ParseArray(true), ObjectStart => ParseObject(true), _ => ParseBeforeFinish, }; return val; } fn parse_array(&mut self, first: bool) -> JsonEvent { if self.ch_is(']') { if !first { self.error_event(InvalidSyntax) } else { self.state = if self.stack.is_empty() { ParseBeforeFinish } else if self.stack.last_is_index() { ParseArrayComma } else { ParseObjectComma }; self.bump(); ArrayEnd } } else { if first { self.stack.push_index(0); } let val = self.parse_value(); self.state = match val { Error(_) => ParseFinished, ArrayStart => ParseArray(true), ObjectStart => ParseObject(true), _ => ParseArrayComma, }; val } } fn parse_array_comma_or_end(&mut self) -> Option { if self.ch_is(',') { self.stack.bump_index(); self.state = ParseArray(false); self.bump(); None } else if self.ch_is(']') { self.stack.pop(); self.state = if self.stack.is_empty() { ParseBeforeFinish } else if self.stack.last_is_index() { ParseArrayComma } else { ParseObjectComma }; self.bump(); Some(ArrayEnd) } else if self.eof() { Some(self.error_event(EOFWhileParsingArray)) } else { Some(self.error_event(InvalidSyntax)) } } fn parse_object(&mut self, first: bool) -> JsonEvent { if self.ch_is('}') { if !first { if self.stack.is_empty() { return self.error_event(TrailingComma); } else { self.stack.pop(); } } self.state = if self.stack.is_empty() { ParseBeforeFinish } else if self.stack.last_is_index() { ParseArrayComma } else { ParseObjectComma }; self.bump(); return ObjectEnd; } if self.eof() { return self.error_event(EOFWhileParsingObject); } if !self.ch_is('"') { return self.error_event(KeyMustBeAString); } let s = match self.parse_str() { Ok(s) => s, Err(e) => { self.state = ParseFinished; return Error(e); } }; self.parse_whitespace(); if self.eof() { return self.error_event(EOFWhileParsingObject); } else if self.ch_or_null() != ':' { return self.error_event(ExpectedColon); } self.stack.push_key(s); self.bump(); self.parse_whitespace(); let val = self.parse_value(); self.state = match val { Error(_) => ParseFinished, ArrayStart => ParseArray(true), ObjectStart => ParseObject(true), _ => ParseObjectComma, }; return val; } fn parse_object_end(&mut self) -> JsonEvent { if self.ch_is('}') { self.state = if self.stack.is_empty() { ParseBeforeFinish } else if self.stack.last_is_index() { ParseArrayComma } else { ParseObjectComma }; self.bump(); ObjectEnd } else if self.eof() { self.error_event(EOFWhileParsingObject) } else { self.error_event(InvalidSyntax) } } fn parse_value(&mut self) -> JsonEvent { if self.eof() { return self.error_event(EOFWhileParsingValue); } match self.ch_or_null() { 'n' => { self.parse_ident("ull", NullValue) } 't' => { self.parse_ident("rue", BooleanValue(true)) } 'f' => { self.parse_ident("alse", BooleanValue(false)) } '0' ... '9' | '-' => self.parse_number(), '"' => match self.parse_str() { Ok(s) => StringValue(s), Err(e) => Error(e), }, '[' => { self.bump(); ArrayStart } '{' => { self.bump(); ObjectStart } _ => { self.error_event(InvalidSyntax) } } } fn parse_ident(&mut self, ident: &str, value: JsonEvent) -> JsonEvent { if ident.chars().all(|c| Some(c) == self.next_char()) { self.bump(); value } else { Error(SyntaxError(InvalidSyntax, self.line, self.col)) } } fn error_event(&mut self, reason: ErrorCode) -> JsonEvent { self.state = ParseFinished; Error(SyntaxError(reason, self.line, self.col)) } } /// A Builder consumes a json::Parser to create a generic Json structure. pub struct Builder { parser: Parser, token: Option, } impl> Builder { /// Create a JSON Builder. pub fn new(src: T) -> Builder { Builder { parser: Parser::new(src), token: None, } } // Decode a Json value from a Parser. pub fn build(&mut self) -> Result { self.bump(); let result = self.build_value(); self.bump(); match self.token.take() { None => {} Some(Error(e)) => { return Err(e); } _ => { return Err(SyntaxError(InvalidSyntax, self.parser.line, self.parser.col)); } } result } fn bump(&mut self) { self.token = self.parser.next(); } fn build_value(&mut self) -> Result { return match self.token.take() { Some(NullValue) => Ok(Json::Null), Some(I64Value(n)) => Ok(Json::I64(n)), Some(U64Value(n)) => Ok(Json::U64(n)), Some(F64Value(n)) => Ok(Json::F64(n)), Some(BooleanValue(b)) => Ok(Json::Boolean(b)), Some(StringValue(ref mut s)) => { let mut temp = string::String::new(); swap(s, &mut temp); Ok(Json::String(temp)) } Some(Error(e)) => Err(e), Some(ArrayStart) => self.build_array(), Some(ObjectStart) => self.build_object(), Some(ObjectEnd) => self.parser.error(InvalidSyntax), Some(ArrayEnd) => self.parser.error(InvalidSyntax), None => self.parser.error(EOFWhileParsingValue), } } fn build_array(&mut self) -> Result { self.bump(); let mut values = Vec::new(); loop { if let Some(ArrayEnd) = self.token { return Ok(Json::Array(values.into_iter().collect())); } match self.build_value() { Ok(v) => values.push(v), Err(e) => { return Err(e) } } self.bump(); } } fn build_object(&mut self) -> Result { self.bump(); let mut values = BTreeMap::new(); loop { match self.token.take() { Some(ObjectEnd) => { return Ok(Json::Object(values)); } Some(Error(e)) => { return Err(e); } None => { break; } token => { self.token = token; } } let key = match self.parser.stack().top() { Some(StackElement::Key(k)) => { k.to_string() } _ => { panic!("invalid state"); } }; match self.build_value() { Ok(value) => { values.insert(key, value); } Err(e) => { return Err(e); } } self.bump(); } return self.parser.error(EOFWhileParsingObject); } } /// A structure to decode JSON to values in rust. pub struct Decoder { stack: Vec, } impl Decoder { /// Creates a new decoder instance for decoding the specified JSON value. pub fn new(json: Json) -> Decoder { Decoder { stack: vec![json] } } } impl Decoder { fn pop(&mut self) -> DecodeResult { match self.stack.pop() { Some(s) => Ok(s), None => Err(EOF), } } } macro_rules! expect { ($e:expr, Null) => ({ match try!($e) { Json::Null => Ok(()), other => Err(ExpectedError("Null".to_string(), format!("{}", other))) } }); ($e:expr, $t:ident) => ({ match try!($e) { Json::$t(v) => Ok(v), other => { Err(ExpectedError(stringify!($t).to_string(), format!("{}", other))) } } }) } macro_rules! read_primitive { ($name:ident, $ty:ident) => { #[allow(unused_comparisons)] fn $name(&mut self) -> DecodeResult<$ty> { match try!(self.pop()) { Json::I64(i) => { let other = i as $ty; if i == other as i64 && (other > 0) == (i > 0) { Ok(other) } else { Err(ExpectedError("Number".to_string(), i.to_string())) } } Json::U64(u) => { let other = u as $ty; if u == other as u64 && other >= 0 { Ok(other) } else { Err(ExpectedError("Number".to_string(), u.to_string())) } } Json::F64(f) => { Err(ExpectedError("Integer".to_string(), f.to_string())) } // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. Json::String(s) => match s.parse() { Ok(f) => Ok(f), Err(_) => Err(ExpectedError("Number".to_string(), s)), }, value => { Err(ExpectedError("Number".to_string(), value.to_string())) } } } } } impl ::Decoder for Decoder { type Error = DecoderError; fn read_nil(&mut self) -> DecodeResult<()> { expect!(self.pop(), Null) } read_primitive! { read_usize, usize } read_primitive! { read_u8, u8 } read_primitive! { read_u16, u16 } read_primitive! { read_u32, u32 } read_primitive! { read_u64, u64 } read_primitive! { read_isize, isize } read_primitive! { read_i8, i8 } read_primitive! { read_i16, i16 } read_primitive! { read_i32, i32 } read_primitive! { read_i64, i64 } fn read_f32(&mut self) -> DecodeResult { self.read_f64().map(|x| x as f32) } fn read_f64(&mut self) -> DecodeResult { match try!(self.pop()) { Json::I64(f) => Ok(f as f64), Json::U64(f) => Ok(f as f64), Json::F64(f) => Ok(f), Json::String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. match s.parse() { Ok(f) => Ok(f), Err(_) => Err(ExpectedError("Number".to_string(), s)), } }, Json::Null => Ok(f64::NAN), value => Err(ExpectedError("Number".to_string(), format!("{}", value))) } } fn read_bool(&mut self) -> DecodeResult { expect!(self.pop(), Boolean) } fn read_char(&mut self) -> DecodeResult { let s = try!(self.read_str()); { let mut it = s.chars(); match (it.next(), it.next()) { // exactly one character (Some(c), None) => return Ok(c), _ => () } } Err(ExpectedError("single character string".to_string(), format!("{}", s))) } fn read_str(&mut self) -> DecodeResult { expect!(self.pop(), String) } fn read_enum(&mut self, _name: &str, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_enum_variant(&mut self, names: &[&str], mut f: F) -> DecodeResult where F: FnMut(&mut Decoder, usize) -> DecodeResult, { let name = match try!(self.pop()) { Json::String(s) => s, Json::Object(mut o) => { let n = match o.remove(&"variant".to_string()) { Some(Json::String(s)) => s, Some(val) => { return Err(ExpectedError("String".to_string(), format!("{}", val))) } None => { return Err(MissingFieldError("variant".to_string())) } }; match o.remove(&"fields".to_string()) { Some(Json::Array(l)) => { for field in l.into_iter().rev() { self.stack.push(field); } }, Some(val) => { return Err(ExpectedError("Array".to_string(), format!("{}", val))) } None => { return Err(MissingFieldError("fields".to_string())) } } n } json => { return Err(ExpectedError("String or Object".to_string(), format!("{}", json))) } }; let idx = match names.iter().position(|n| *n == name) { Some(idx) => idx, None => return Err(UnknownVariantError(name)) }; f(self, idx) } fn read_enum_variant_arg(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> DecodeResult where F: FnMut(&mut Decoder, usize) -> DecodeResult, { self.read_enum_variant(names, f) } fn read_enum_struct_variant_field(&mut self, _name: &str, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_enum_variant_arg(idx, f) } fn read_struct(&mut self, _name: &str, _len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { let value = try!(f(self)); try!(self.pop()); Ok(value) } fn read_struct_field(&mut self, name: &str, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { let mut obj = try!(expect!(self.pop(), Object)); let value = match obj.remove(&name.to_string()) { None => { // Add a Null and try to parse it as an Option<_> // to get None as a default value. self.stack.push(Json::Null); match f(self) { Ok(x) => x, Err(_) => return Err(MissingFieldError(name.to_string())), } }, Some(json) => { self.stack.push(json); try!(f(self)) } }; self.stack.push(Json::Object(obj)); Ok(value) } fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_seq(move |d, len| { if len == tuple_len { f(d) } else { Err(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len))) } }) } fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_seq_elt(idx, f) } fn read_tuple_struct(&mut self, _name: &str, len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_tuple(len, f) } fn read_tuple_struct_arg(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_tuple_arg(idx, f) } fn read_option(&mut self, mut f: F) -> DecodeResult where F: FnMut(&mut Decoder, bool) -> DecodeResult, { match try!(self.pop()) { Json::Null => f(self, false), value => { self.stack.push(value); f(self, true) } } } fn read_seq(&mut self, f: F) -> DecodeResult where F: FnOnce(&mut Decoder, usize) -> DecodeResult, { let array = try!(expect!(self.pop(), Array)); let len = array.len(); for v in array.into_iter().rev() { self.stack.push(v); } f(self, len) } fn read_seq_elt(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_map(&mut self, f: F) -> DecodeResult where F: FnOnce(&mut Decoder, usize) -> DecodeResult, { let obj = try!(expect!(self.pop(), Object)); let len = obj.len(); for (key, value) in obj.into_iter() { self.stack.push(value); self.stack.push(Json::String(key)); } f(self, len) } fn read_map_elt_key(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_map_elt_val(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn error(&mut self, err: &str) -> DecoderError { ApplicationError(err.to_string()) } } /// A trait for converting values to JSON pub trait ToJson { /// Converts the value of `self` to an instance of JSON fn to_json(&self) -> Json; } macro_rules! to_json_impl_i64 { ($($t:ty), +) => ( $(impl ToJson for $t { fn to_json(&self) -> Json { Json::I64(*self as i64) } })+ ) } to_json_impl_i64! { isize, i8, i16, i32, i64 } macro_rules! to_json_impl_u64 { ($($t:ty), +) => ( $(impl ToJson for $t { fn to_json(&self) -> Json { Json::U64(*self as u64) } })+ ) } to_json_impl_u64! { usize, u8, u16, u32, u64 } impl ToJson for Json { fn to_json(&self) -> Json { self.clone() } } impl ToJson for f32 { fn to_json(&self) -> Json { (*self as f64).to_json() } } impl ToJson for f64 { fn to_json(&self) -> Json { use std::num::FpCategory::{Nan, Infinite}; match self.classify() { Nan | Infinite => Json::Null, _ => Json::F64(*self) } } } impl ToJson for () { fn to_json(&self) -> Json { Json::Null } } impl ToJson for bool { fn to_json(&self) -> Json { Json::Boolean(*self) } } impl ToJson for str { fn to_json(&self) -> Json { Json::String(self.to_string()) } } impl ToJson for string::String { fn to_json(&self) -> Json { Json::String((*self).clone()) } } macro_rules! tuple_impl { // use variables to indicate the arity of the tuple ($($tyvar:ident),* ) => { // the trailing commas are for the 1 tuple impl< $( $tyvar : ToJson ),* > ToJson for ( $( $tyvar ),* , ) { #[inline] #[allow(non_snake_case)] fn to_json(&self) -> Json { match *self { ($(ref $tyvar),*,) => Json::Array(vec![$($tyvar.to_json()),*]) } } } } } tuple_impl!{A} tuple_impl!{A, B} tuple_impl!{A, B, C} tuple_impl!{A, B, C, D} tuple_impl!{A, B, C, D, E} tuple_impl!{A, B, C, D, E, F} tuple_impl!{A, B, C, D, E, F, G} tuple_impl!{A, B, C, D, E, F, G, H} tuple_impl!{A, B, C, D, E, F, G, H, I} tuple_impl!{A, B, C, D, E, F, G, H, I, J} tuple_impl!{A, B, C, D, E, F, G, H, I, J, K} tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L} impl ToJson for [A] { fn to_json(&self) -> Json { Json::Array(self.iter().map(|elt| elt.to_json()).collect()) } } impl ToJson for Vec { fn to_json(&self) -> Json { Json::Array(self.iter().map(|elt| elt.to_json()).collect()) } } impl ToJson for BTreeMap { fn to_json(&self) -> Json { let mut d = BTreeMap::new(); for (key, value) in self.iter() { d.insert((*key).clone(), value.to_json()); } Json::Object(d) } } impl ToJson for HashMap { fn to_json(&self) -> Json { let mut d = BTreeMap::new(); for (key, value) in self.iter() { d.insert((*key).clone(), value.to_json()); } Json::Object(d) } } impl ToJson for Option { fn to_json(&self) -> Json { match *self { None => Json::Null, Some(ref value) => value.to_json() } } } struct FormatShim<'a, 'b: 'a> { inner: &'a mut fmt::Formatter<'b>, } impl<'a, 'b> fmt::Write for FormatShim<'a, 'b> { fn write_str(&mut self, s: &str) -> fmt::Result { match self.inner.write_str(s) { Ok(_) => Ok(()), Err(_) => Err(fmt::Error) } } } impl fmt::Display for Json { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new(&mut shim); match self.encode(&mut encoder) { Ok(_) => Ok(()), Err(_) => Err(fmt::Error) } } } impl<'a> fmt::Display for PrettyJson<'a> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new_pretty(&mut shim); match self.inner.encode(&mut encoder) { Ok(_) => Ok(()), Err(_) => Err(fmt::Error) } } } impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new(&mut shim); match self.inner.encode(&mut encoder) { Ok(_) => Ok(()), Err(_) => Err(fmt::Error) } } } impl<'a, T> AsPrettyJson<'a, T> { /// Set the indentation level for the emitted JSON pub fn indent(mut self, indent: u32) -> AsPrettyJson<'a, T> { self.indent = Some(indent); self } } impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> { /// Encodes a json value into a string fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new_pretty(&mut shim); if let Some(n) = self.indent { // unwrap cannot panic for pretty encoders let _ = encoder.set_indent(n); } match self.inner.encode(&mut encoder) { Ok(_) => Ok(()), Err(_) => Err(fmt::Error) } } } impl FromStr for Json { type Err = ParserError; fn from_str(s: &str) -> Result { Json::from_str(s) } } #[cfg(test)] mod tests { use self::Animal::*; use {Encodable, Decodable}; use super::Json::*; use super::ErrorCode::*; use super::ParserError::*; use super::DecoderError::*; use super::JsonEvent::*; use super::StackElement::*; use super::{Json, DecodeResult, DecoderError, JsonEvent, Parser, StackElement, Stack, Decoder, Encoder, EncoderError}; use std::{i64, u64, f32, f64}; use std::collections::BTreeMap; use std::string; #[derive(RustcDecodable, Eq, PartialEq, Debug)] struct OptionData { opt: Option, } #[test] fn test_decode_option_none() { let s ="{}"; let obj: OptionData = super::decode(s).unwrap(); assert_eq!(obj, OptionData { opt: None }); } #[test] fn test_decode_option_some() { let s = "{ \"opt\": 10 }"; let obj: OptionData = super::decode(s).unwrap(); assert_eq!(obj, OptionData { opt: Some(10) }); } #[test] fn test_decode_option_malformed() { check_err::("{ \"opt\": [] }", ExpectedError("Number".to_string(), "[]".to_string())); check_err::("{ \"opt\": false }", ExpectedError("Number".to_string(), "false".to_string())); } #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] enum Animal { Dog, Frog(string::String, isize) } #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] struct Inner { a: (), b: usize, c: Vec, } #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] struct Outer { inner: Vec, } fn mk_object(items: &[(string::String, Json)]) -> Json { let mut d = BTreeMap::new(); for item in items.iter() { match *item { (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); }, } }; Object(d) } #[test] fn test_from_str_trait() { let s = "null"; assert!(s.parse::().unwrap() == s.parse().unwrap()); } #[test] fn test_write_null() { assert_eq!(Null.to_string(), "null"); assert_eq!(Null.pretty().to_string(), "null"); } #[test] fn test_write_i64() { assert_eq!(U64(0).to_string(), "0"); assert_eq!(U64(0).pretty().to_string(), "0"); assert_eq!(U64(1234).to_string(), "1234"); assert_eq!(U64(1234).pretty().to_string(), "1234"); assert_eq!(I64(-5678).to_string(), "-5678"); assert_eq!(I64(-5678).pretty().to_string(), "-5678"); assert_eq!(U64(7650007200025252000).to_string(), "7650007200025252000"); assert_eq!(U64(7650007200025252000).pretty().to_string(), "7650007200025252000"); } #[test] fn test_write_f64() { assert_eq!(F64(3.0).to_string(), "3.0"); assert_eq!(F64(3.0).pretty().to_string(), "3.0"); assert_eq!(F64(3.1).to_string(), "3.1"); assert_eq!(F64(3.1).pretty().to_string(), "3.1"); assert_eq!(F64(-1.5).to_string(), "-1.5"); assert_eq!(F64(-1.5).pretty().to_string(), "-1.5"); assert_eq!(F64(0.5).to_string(), "0.5"); assert_eq!(F64(0.5).pretty().to_string(), "0.5"); assert_eq!(F64(f64::NAN).to_string(), "null"); assert_eq!(F64(f64::NAN).pretty().to_string(), "null"); assert_eq!(F64(f64::INFINITY).to_string(), "null"); assert_eq!(F64(f64::INFINITY).pretty().to_string(), "null"); assert_eq!(F64(f64::NEG_INFINITY).to_string(), "null"); assert_eq!(F64(f64::NEG_INFINITY).pretty().to_string(), "null"); } #[test] fn test_write_str() { assert_eq!(String("".to_string()).to_string(), "\"\""); assert_eq!(String("".to_string()).pretty().to_string(), "\"\""); assert_eq!(String("homura".to_string()).to_string(), "\"homura\""); assert_eq!(String("madoka".to_string()).pretty().to_string(), "\"madoka\""); } #[test] fn test_write_bool() { assert_eq!(Boolean(true).to_string(), "true"); assert_eq!(Boolean(true).pretty().to_string(), "true"); assert_eq!(Boolean(false).to_string(), "false"); assert_eq!(Boolean(false).pretty().to_string(), "false"); } #[test] fn test_write_array() { assert_eq!(Array(vec![]).to_string(), "[]"); assert_eq!(Array(vec![]).pretty().to_string(), "[]"); assert_eq!(Array(vec![Boolean(true)]).to_string(), "[true]"); assert_eq!( Array(vec![Boolean(true)]).pretty().to_string(), "\ [\n \ true\n\ ]" ); let long_test_array = Array(vec![ Boolean(false), Null, Array(vec![String("foo\nbar".to_string()), F64(3.5)])]); assert_eq!(long_test_array.to_string(), "[false,null,[\"foo\\nbar\",3.5]]"); assert_eq!( long_test_array.pretty().to_string(), "\ [\n \ false,\n \ null,\n \ [\n \ \"foo\\nbar\",\n \ 3.5\n \ ]\n\ ]" ); } #[test] fn test_write_object() { assert_eq!(mk_object(&[]).to_string(), "{}"); assert_eq!(mk_object(&[]).pretty().to_string(), "{}"); assert_eq!( mk_object(&[ ("a".to_string(), Boolean(true)) ]).to_string(), "{\"a\":true}" ); assert_eq!( mk_object(&[("a".to_string(), Boolean(true))]).pretty().to_string(), "\ {\n \ \"a\": true\n\ }" ); let complex_obj = mk_object(&[ ("b".to_string(), Array(vec![ mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), mk_object(&[("d".to_string(), String("".to_string()))]) ])) ]); assert_eq!( complex_obj.to_string(), "{\ \"b\":[\ {\"c\":\"\\f\\r\"},\ {\"d\":\"\"}\ ]\ }" ); assert_eq!( complex_obj.pretty().to_string(), "\ {\n \ \"b\": [\n \ {\n \ \"c\": \"\\f\\r\"\n \ },\n \ {\n \ \"d\": \"\"\n \ }\n \ ]\n\ }" ); let a = mk_object(&[ ("a".to_string(), Boolean(true)), ("b".to_string(), Array(vec![ mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), mk_object(&[("d".to_string(), String("".to_string()))]) ])) ]); // We can't compare the strings directly because the object fields be // printed in a different order. assert_eq!(a.clone(), a.to_string().parse().unwrap()); assert_eq!(a.clone(), a.pretty().to_string().parse().unwrap()); } #[test] fn test_write_enum() { let animal = Dog; assert_eq!( format!("{}", super::as_json(&animal)), "\"Dog\"" ); assert_eq!( format!("{}", super::as_pretty_json(&animal)), "\"Dog\"" ); let animal = Frog("Henry".to_string(), 349); assert_eq!( format!("{}", super::as_json(&animal)), "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}" ); assert_eq!( format!("{}", super::as_pretty_json(&animal)), "{\n \ \"variant\": \"Frog\",\n \ \"fields\": [\n \ \"Henry\",\n \ 349\n \ ]\n\ }" ); } macro_rules! check_encoder_for_simple { ($value:expr, $expected:expr) => ({ let s = format!("{}", super::as_json(&$value)); assert_eq!(s, $expected); let s = format!("{}", super::as_pretty_json(&$value)); assert_eq!(s, $expected); }) } #[test] fn test_write_some() { check_encoder_for_simple!(Some("jodhpurs".to_string()), "\"jodhpurs\""); } #[test] fn test_write_none() { check_encoder_for_simple!(None::, "null"); } #[test] fn test_write_char() { check_encoder_for_simple!('a', "\"a\""); check_encoder_for_simple!('\t', "\"\\t\""); check_encoder_for_simple!('\u{0000}', "\"\\u0000\""); check_encoder_for_simple!('\u{001b}', "\"\\u001b\""); check_encoder_for_simple!('\u{007f}', "\"\\u007f\""); check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\""); check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\""); check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\""); } #[test] fn test_trailing_characters() { assert_eq!(Json::from_str("nulla"), Err(SyntaxError(TrailingCharacters, 1, 5))); assert_eq!(Json::from_str("truea"), Err(SyntaxError(TrailingCharacters, 1, 5))); assert_eq!(Json::from_str("falsea"), Err(SyntaxError(TrailingCharacters, 1, 6))); assert_eq!(Json::from_str("1a"), Err(SyntaxError(TrailingCharacters, 1, 2))); assert_eq!(Json::from_str("[]a"), Err(SyntaxError(TrailingCharacters, 1, 3))); assert_eq!(Json::from_str("{}a"), Err(SyntaxError(TrailingCharacters, 1, 3))); } #[test] fn test_read_identifiers() { assert_eq!(Json::from_str("n"), Err(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(Json::from_str("nul"), Err(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(Json::from_str("t"), Err(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(Json::from_str("truz"), Err(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(Json::from_str("f"), Err(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(Json::from_str("faz"), Err(SyntaxError(InvalidSyntax, 1, 3))); assert_eq!(Json::from_str("null"), Ok(Null)); assert_eq!(Json::from_str("true"), Ok(Boolean(true))); assert_eq!(Json::from_str("false"), Ok(Boolean(false))); assert_eq!(Json::from_str(" null "), Ok(Null)); assert_eq!(Json::from_str(" true "), Ok(Boolean(true))); assert_eq!(Json::from_str(" false "), Ok(Boolean(false))); } #[test] fn test_decode_identifiers() { let v: () = super::decode("null").unwrap(); assert_eq!(v, ()); let v: bool = super::decode("true").unwrap(); assert_eq!(v, true); let v: bool = super::decode("false").unwrap(); assert_eq!(v, false); } #[test] fn test_read_number() { assert_eq!(Json::from_str("+"), Err(SyntaxError(InvalidSyntax, 1, 1))); assert_eq!(Json::from_str("."), Err(SyntaxError(InvalidSyntax, 1, 1))); assert_eq!(Json::from_str("NaN"), Err(SyntaxError(InvalidSyntax, 1, 1))); assert_eq!(Json::from_str("-"), Err(SyntaxError(InvalidNumber, 1, 2))); assert_eq!(Json::from_str("00"), Err(SyntaxError(InvalidNumber, 1, 2))); assert_eq!(Json::from_str("1."), Err(SyntaxError(InvalidNumber, 1, 3))); assert_eq!(Json::from_str("1e"), Err(SyntaxError(InvalidNumber, 1, 3))); assert_eq!(Json::from_str("1e+"), Err(SyntaxError(InvalidNumber, 1, 4))); assert_eq!(Json::from_str("18446744073709551616"), Err(SyntaxError(InvalidNumber, 1, 20))); assert_eq!(Json::from_str("18446744073709551617"), Err(SyntaxError(InvalidNumber, 1, 20))); assert_eq!(Json::from_str("-9223372036854775809"), Err(SyntaxError(InvalidNumber, 1, 21))); assert_eq!(Json::from_str("3"), Ok(U64(3))); assert_eq!(Json::from_str("3.1"), Ok(F64(3.1))); assert_eq!(Json::from_str("-1.2"), Ok(F64(-1.2))); assert_eq!(Json::from_str("0.4"), Ok(F64(0.4))); assert_eq!(Json::from_str("0.4e5"), Ok(F64(0.4e5))); assert_eq!(Json::from_str("0.4e+15"), Ok(F64(0.4e15))); assert_eq!(Json::from_str("0.4e-01"), Ok(F64(0.4e-01))); assert_eq!(Json::from_str("123456789.5024"), Ok(F64(123456789.5024))); assert_eq!(Json::from_str(" 3 "), Ok(U64(3))); assert_eq!(Json::from_str("-9223372036854775808"), Ok(I64(i64::MIN))); assert_eq!(Json::from_str("9223372036854775807"), Ok(U64(i64::MAX as u64))); assert_eq!(Json::from_str("18446744073709551615"), Ok(U64(u64::MAX))); } #[test] fn test_decode_numbers() { let v: f64 = super::decode("3").unwrap(); assert_eq!(v, 3.0); let v: f64 = super::decode("3.1").unwrap(); assert_eq!(v, 3.1); let v: f64 = super::decode("-1.2").unwrap(); assert_eq!(v, -1.2); let v: f64 = super::decode("0.4").unwrap(); assert_eq!(v, 0.4); let v: f64 = super::decode("0.4e5").unwrap(); assert_eq!(v, 0.4e5); let v: f64 = super::decode("0.4e15").unwrap(); assert_eq!(v, 0.4e15); let v: f64 = super::decode("0.4e-01").unwrap(); assert_eq!(v, 0.4e-01); let v: f64 = super::decode("123456789.5024").unwrap(); assert_eq!(v, 123456789.5024); let v: u64 = super::decode("0").unwrap(); assert_eq!(v, 0); let v: u64 = super::decode("18446744073709551615").unwrap(); assert_eq!(v, u64::MAX); let v: i64 = super::decode("-9223372036854775808").unwrap(); assert_eq!(v, i64::MIN); let v: i64 = super::decode("9223372036854775807").unwrap(); assert_eq!(v, i64::MAX); let res: DecodeResult = super::decode("765.25252"); match res { Ok(..) => panic!("expected an error"), Err(ExpectedError(ref s, _)) => assert_eq!(s, "Integer"), Err(..) => panic!("expected an 'expected integer' error"), } } #[test] fn test_read_str() { assert_eq!(Json::from_str("\""), Err(SyntaxError(EOFWhileParsingString, 1, 2))); assert_eq!(Json::from_str("\"lol"), Err(SyntaxError(EOFWhileParsingString, 1, 5))); assert_eq!(Json::from_str("\"\n\""), Err(SyntaxError(ControlCharacterInString, 2, 1))); assert_eq!(Json::from_str("\"\0\""), Err(SyntaxError(ControlCharacterInString, 1, 2))); assert_eq!(Json::from_str("\"\u{1}\""), Err(SyntaxError(ControlCharacterInString, 1, 2))); assert_eq!(Json::from_str("\"\u{1F}\""), Err(SyntaxError(ControlCharacterInString, 1, 2))); // Only C0 control characters are excluded. assert!('\u{7F}'.is_control()); assert!('\u{80}'.is_control()); assert!('\u{9F}'.is_control()); let c1_controls = "\u{7F}\u{80}\u{9F}".to_string(); assert_eq!(Json::from_str(&format!("\"{}\"", c1_controls)), Ok(String(c1_controls))); assert_eq!(Json::from_str("\"\""), Ok(String("".to_string()))); assert_eq!(Json::from_str("\"foo\""), Ok(String("foo".to_string()))); assert_eq!(Json::from_str("\"\\\"\""), Ok(String("\"".to_string()))); assert_eq!(Json::from_str("\"\\b\""), Ok(String("\x08".to_string()))); assert_eq!(Json::from_str("\"\\n\""), Ok(String("\n".to_string()))); assert_eq!(Json::from_str("\"\\r\""), Ok(String("\r".to_string()))); assert_eq!(Json::from_str("\"\\t\""), Ok(String("\t".to_string()))); assert_eq!(Json::from_str(" \"foo\" "), Ok(String("foo".to_string()))); assert_eq!(Json::from_str("\"\\u12ab\""), Ok(String("\u{12ab}".to_string()))); assert_eq!(Json::from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string()))); } #[test] fn test_decode_str() { let s = [("\"\"", ""), ("\"foo\"", "foo"), ("\"\\\"\"", "\""), ("\"\\b\"", "\x08"), ("\"\\n\"", "\n"), ("\"\\r\"", "\r"), ("\"\\t\"", "\t"), ("\"\\u12ab\"", "\u{12ab}"), ("\"\\uAB12\"", "\u{AB12}")]; for &(i, o) in s.iter() { let v: string::String = super::decode(i).unwrap(); assert_eq!(v, o); } } #[test] fn test_read_array() { assert_eq!(Json::from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); assert_eq!(Json::from_str("[1"), Err(SyntaxError(EOFWhileParsingArray, 1, 3))); assert_eq!(Json::from_str("[1,"), Err(SyntaxError(EOFWhileParsingValue, 1, 4))); assert_eq!(Json::from_str("[1,]"), Err(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(Json::from_str("[6 7]"), Err(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(Json::from_str("[]"), Ok(Array(vec![]))); assert_eq!(Json::from_str("[ ]"), Ok(Array(vec![]))); assert_eq!(Json::from_str("[true]"), Ok(Array(vec![Boolean(true)]))); assert_eq!(Json::from_str("[ false ]"), Ok(Array(vec![Boolean(false)]))); assert_eq!(Json::from_str("[null]"), Ok(Array(vec![Null]))); assert_eq!(Json::from_str("[3, 1]"), Ok(Array(vec![U64(3), U64(1)]))); assert_eq!(Json::from_str("\n[3, 2]\n"), Ok(Array(vec![U64(3), U64(2)]))); assert_eq!(Json::from_str("[2, [4, 1]]"), Ok(Array(vec![U64(2), Array(vec![U64(4), U64(1)])]))); } #[test] fn test_decode_array() { let v: Vec<()> = super::decode("[]").unwrap(); assert_eq!(v, vec![]); let v: Vec<()> = super::decode("[null]").unwrap(); assert_eq!(v, vec![()]); let v: Vec = super::decode("[true]").unwrap(); assert_eq!(v, vec![true]); let v: Vec = super::decode("[3, 1]").unwrap(); assert_eq!(v, vec![3, 1]); let v: Vec> = super::decode("[[3], [1, 2]]").unwrap(); assert_eq!(v, vec![vec![3], vec![1, 2]]); } #[test] fn test_decode_tuple() { let t: (usize, usize, usize) = super::decode("[1, 2, 3]").unwrap(); assert_eq!(t, (1, 2, 3)); let t: (usize, string::String) = super::decode("[1, \"two\"]").unwrap(); assert_eq!(t, (1, "two".to_string())); } #[test] fn test_decode_tuple_malformed_types() { assert!(super::decode::<(usize, string::String)>("[1, 2]").is_err()); } #[test] fn test_decode_tuple_malformed_length() { assert!(super::decode::<(usize, usize)>("[1, 2, 3]").is_err()); } #[test] fn test_read_object() { assert_eq!(Json::from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2))); assert_eq!(Json::from_str("{ "), Err(SyntaxError(EOFWhileParsingObject, 1, 3))); assert_eq!(Json::from_str("{1"), Err(SyntaxError(KeyMustBeAString, 1, 2))); assert_eq!(Json::from_str("{ \"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); assert_eq!(Json::from_str("{\"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 5))); assert_eq!(Json::from_str("{\"a\" "), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); assert_eq!(Json::from_str("{\"a\" 1"), Err(SyntaxError(ExpectedColon, 1, 6))); assert_eq!(Json::from_str("{\"a\":"), Err(SyntaxError(EOFWhileParsingValue, 1, 6))); assert_eq!(Json::from_str("{\"a\":1"), Err(SyntaxError(EOFWhileParsingObject, 1, 7))); assert_eq!(Json::from_str("{\"a\":1 1"), Err(SyntaxError(InvalidSyntax, 1, 8))); assert_eq!(Json::from_str("{\"a\":1,"), Err(SyntaxError(EOFWhileParsingObject, 1, 8))); assert_eq!(Json::from_str("{}").unwrap(), mk_object(&[])); assert_eq!(Json::from_str("{\"a\": 3}").unwrap(), mk_object(&[("a".to_string(), U64(3))])); assert_eq!(Json::from_str( "{ \"a\": null, \"b\" : true }").unwrap(), mk_object(&[ ("a".to_string(), Null), ("b".to_string(), Boolean(true))])); assert_eq!(Json::from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(), mk_object(&[ ("a".to_string(), Null), ("b".to_string(), Boolean(true))])); assert_eq!(Json::from_str( "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(), mk_object(&[ ("a".to_string(), F64(1.0)), ("b".to_string(), Array(vec![Boolean(true)])) ])); assert_eq!(Json::from_str( "{\ \"a\": 1.0, \ \"b\": [\ true,\ \"foo\\nbar\", \ { \"c\": {\"d\": null} } \ ]\ }").unwrap(), mk_object(&[ ("a".to_string(), F64(1.0)), ("b".to_string(), Array(vec![ Boolean(true), String("foo\nbar".to_string()), mk_object(&[ ("c".to_string(), mk_object(&[("d".to_string(), Null)])) ]) ])) ])); } #[test] fn test_decode_struct() { let s = "{ \"inner\": [ { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] } ] }"; let v: Outer = super::decode(s).unwrap(); assert_eq!( v, Outer { inner: vec![ Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] } ] } ); } #[derive(RustcDecodable)] struct FloatStruct { f: f64, a: Vec } #[test] fn test_decode_struct_with_nan() { let s = "{\"f\":null,\"a\":[null,123]}"; let obj: FloatStruct = super::decode(s).unwrap(); assert!(obj.f.is_nan()); assert!(obj.a[0].is_nan()); assert_eq!(obj.a[1], 123f64); } #[test] fn test_decode_option() { let value: Option = super::decode("null").unwrap(); assert_eq!(value, None); let value: Option = super::decode("\"jodhpurs\"").unwrap(); assert_eq!(value, Some("jodhpurs".to_string())); } #[test] fn test_decode_enum() { let value: Animal = super::decode("\"Dog\"").unwrap(); assert_eq!(value, Dog); let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"; let value: Animal = super::decode(s).unwrap(); assert_eq!(value, Frog("Henry".to_string(), 349)); } #[test] fn test_decode_result() { let value: Result = Ok(4); let json_value = super::encode(&value).unwrap(); assert_eq!(json_value, "{\"variant\":\"Ok\",\"fields\":[4]}"); let decoded_value: Result = super::decode(&json_value).unwrap(); assert_eq!(decoded_value, Ok(4)); } #[test] fn test_decode_map() { let s = "{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\ \"fields\":[\"Henry\", 349]}}"; let mut map: BTreeMap = super::decode(s).unwrap(); assert_eq!(map.remove(&"a".to_string()), Some(Dog)); assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349))); } #[test] fn test_multiline_errors() { assert_eq!(Json::from_str("{\n \"foo\":\n \"bar\""), Err(SyntaxError(EOFWhileParsingObject, 3, 8))); } #[derive(RustcDecodable)] #[allow(dead_code)] struct DecodeStruct { x: f64, y: bool, z: string::String, w: Vec } #[derive(RustcDecodable)] enum DecodeEnum { A(f64), B(string::String) } fn check_err(to_parse: &'static str, expected: DecoderError) { let res: DecodeResult = match Json::from_str(to_parse) { Err(e) => Err(ParseError(e)), Ok(json) => Decodable::decode(&mut Decoder::new(json)) }; match res { Ok(_) => panic!("`{:?}` parsed & decoded ok, expecting error `{:?}`", to_parse, expected), Err(ParseError(e)) => panic!("`{}` is not valid json: {:?}", to_parse, e), Err(e) => { assert_eq!(e, expected); } } } #[test] fn test_decode_errors_struct() { check_err::("[]", ExpectedError("Object".to_string(), "[]".to_string())); check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", ExpectedError("Number".to_string(), "true".to_string())); check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", ExpectedError("Boolean".to_string(), "[]".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", ExpectedError("String".to_string(), "{}".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", ExpectedError("Array".to_string(), "null".to_string())); check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", MissingFieldError("w".to_string())); } #[test] fn test_decode_errors_enum() { check_err::("{}", MissingFieldError("variant".to_string())); check_err::("{\"variant\": 1}", ExpectedError("String".to_string(), "1".to_string())); check_err::("{\"variant\": \"A\"}", MissingFieldError("fields".to_string())); check_err::("{\"variant\": \"A\", \"fields\": null}", ExpectedError("Array".to_string(), "null".to_string())); check_err::("{\"variant\": \"C\", \"fields\": []}", UnknownVariantError("C".to_string())); } #[test] fn test_find(){ let json_value = Json::from_str("{\"dog\" : \"cat\"}").unwrap(); let found_str = json_value.find("dog"); assert!(found_str.unwrap().as_string().unwrap() == "cat"); } #[test] fn test_find_path(){ let json_value = Json::from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); let found_str = json_value.find_path(&["dog", "cat", "mouse"]); assert!(found_str.unwrap().as_string().unwrap() == "cheese"); } #[test] fn test_search(){ let json_value = Json::from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); let found_str = json_value.search("mouse").and_then(|j| j.as_string()); assert!(found_str.unwrap() == "cheese"); } #[test] fn test_index(){ let json_value = Json::from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap(); let ref array = json_value["animals"]; assert_eq!(array[0].as_string().unwrap(), "dog"); assert_eq!(array[1].as_string().unwrap(), "cat"); assert_eq!(array[2].as_string().unwrap(), "mouse"); } #[test] fn test_is_object(){ let json_value = Json::from_str("{}").unwrap(); assert!(json_value.is_object()); } #[test] fn test_as_object(){ let json_value = Json::from_str("{}").unwrap(); let json_object = json_value.as_object(); assert!(json_object.is_some()); } #[test] fn test_is_array(){ let json_value = Json::from_str("[1, 2, 3]").unwrap(); assert!(json_value.is_array()); } #[test] fn test_as_array(){ let json_value = Json::from_str("[1, 2, 3]").unwrap(); let json_array = json_value.as_array(); let expected_length = 3; assert!(json_array.is_some() && json_array.unwrap().len() == expected_length); } #[test] fn test_is_string(){ let json_value = Json::from_str("\"dog\"").unwrap(); assert!(json_value.is_string()); } #[test] fn test_as_string(){ let json_value = Json::from_str("\"dog\"").unwrap(); let json_str = json_value.as_string(); let expected_str = "dog"; assert_eq!(json_str, Some(expected_str)); } #[test] fn test_is_number(){ let json_value = Json::from_str("12").unwrap(); assert!(json_value.is_number()); } #[test] fn test_is_i64(){ let json_value = Json::from_str("-12").unwrap(); assert!(json_value.is_i64()); let json_value = Json::from_str("12").unwrap(); assert!(!json_value.is_i64()); let json_value = Json::from_str("12.0").unwrap(); assert!(!json_value.is_i64()); } #[test] fn test_is_u64(){ let json_value = Json::from_str("12").unwrap(); assert!(json_value.is_u64()); let json_value = Json::from_str("-12").unwrap(); assert!(!json_value.is_u64()); let json_value = Json::from_str("12.0").unwrap(); assert!(!json_value.is_u64()); } #[test] fn test_is_f64(){ let json_value = Json::from_str("12").unwrap(); assert!(!json_value.is_f64()); let json_value = Json::from_str("-12").unwrap(); assert!(!json_value.is_f64()); let json_value = Json::from_str("12.0").unwrap(); assert!(json_value.is_f64()); let json_value = Json::from_str("-12.0").unwrap(); assert!(json_value.is_f64()); } #[test] fn test_as_i64(){ let json_value = Json::from_str("-12").unwrap(); let json_num = json_value.as_i64(); assert_eq!(json_num, Some(-12)); } #[test] fn test_as_u64(){ let json_value = Json::from_str("12").unwrap(); let json_num = json_value.as_u64(); assert_eq!(json_num, Some(12)); } #[test] fn test_as_f64(){ let json_value = Json::from_str("12.0").unwrap(); let json_num = json_value.as_f64(); assert_eq!(json_num, Some(12f64)); } #[test] fn test_is_boolean(){ let json_value = Json::from_str("false").unwrap(); assert!(json_value.is_boolean()); } #[test] fn test_as_boolean(){ let json_value = Json::from_str("false").unwrap(); let json_bool = json_value.as_boolean(); let expected_bool = false; assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool); } #[test] fn test_is_null(){ let json_value = Json::from_str("null").unwrap(); assert!(json_value.is_null()); } #[test] fn test_as_null(){ let json_value = Json::from_str("null").unwrap(); let json_null = json_value.as_null(); let expected_null = (); assert!(json_null.is_some() && json_null.unwrap() == expected_null); } #[test] fn test_encode_hashmap_with_numeric_key() { use std::collections::HashMap; let mut hm: HashMap = HashMap::new(); hm.insert(1, true); let json_str = super::as_pretty_json(&hm).to_string(); match Json::from_str(&json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), _ => {} // it parsed and we are good to go } } #[test] fn test_negative_zero() { Json::from_str("{\"test\":-0}").unwrap(); } #[test] fn test_prettyencode_hashmap_with_numeric_key() { use std::collections::HashMap; let mut hm: HashMap = HashMap::new(); hm.insert(1, true); let json_str = super::as_pretty_json(&hm).to_string(); match Json::from_str(&json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), _ => {} // it parsed and we are good to go } } #[test] fn test_prettyencoder_indent_level_param() { use std::collections::BTreeMap; let mut tree = BTreeMap::new(); tree.insert("hello".to_string(), String("guten tag".to_string())); tree.insert("goodbye".to_string(), String("sayonara".to_string())); let json = Array( // The following layout below should look a lot like // the pretty-printed JSON (indent * x) vec! ( // 0x String("greetings".to_string()), // 1x Object(tree), // 1x + 2x + 2x + 1x ) // 0x // End JSON array (7 lines) ); // Helper function for counting indents fn indents(source: &str) -> usize { let trimmed = source.trim_left_matches(' '); source.len() - trimmed.len() } // Test up to 4 spaces of indents (more?) for i in 0..4 { let printed = super::as_pretty_json(&json).indent(i as u32) .to_string(); // Check for indents at each line let lines: Vec<&str> = printed.lines().collect(); assert_eq!(lines.len(), 7); // JSON should be 7 lines assert_eq!(indents(lines[0]), 0 * i); // [ assert_eq!(indents(lines[1]), 1 * i); // "greetings", assert_eq!(indents(lines[2]), 1 * i); // { assert_eq!(indents(lines[3]), 2 * i); // "hello": "guten tag", assert_eq!(indents(lines[4]), 2 * i); // "goodbye": "sayonara" assert_eq!(indents(lines[5]), 1 * i); // }, assert_eq!(indents(lines[6]), 0 * i); // ] // Finally, test that the pretty-printed JSON is valid Json::from_str(&printed).ok() .expect("Pretty-printed JSON is invalid!"); } } #[test] fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { use std::collections::HashMap; use Decodable; let json_str = "{\"1\":true}"; let json_obj = match Json::from_str(json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), Ok(o) => o }; let mut decoder = Decoder::new(json_obj); let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); } #[test] fn test_hashmap_with_enum_key() { use std::collections::HashMap; use json; #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)] enum Enum { Foo, #[allow(dead_code)] Bar, } let mut map = HashMap::new(); map.insert(Enum::Foo, 0); let result = json::encode(&map).unwrap(); assert_eq!(result, r#"{"Foo":0}"#); let decoded: HashMap = json::decode(&result).unwrap(); assert_eq!(map, decoded); } #[test] fn test_hashmap_with_numeric_key_will_error_with_string_keys() { use std::collections::HashMap; use Decodable; let json_str = "{\"a\":true}"; let json_obj = match Json::from_str(json_str) { Err(_) => panic!("Unable to parse json_str: {}", json_str), Ok(o) => o }; let mut decoder = Decoder::new(json_obj); let result: Result, DecoderError> = Decodable::decode(&mut decoder); assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string()))); } fn assert_stream_equal(src: &str, expected: Vec<(JsonEvent, Vec)>) { let mut parser = Parser::new(src.chars()); let mut i = 0; loop { let evt = match parser.next() { Some(e) => e, None => { break; } }; let (ref expected_evt, ref expected_stack) = expected[i]; if !parser.stack().is_equal_to(&expected_stack) { panic!("Parser stack is not equal to {:?}", expected_stack); } assert_eq!(&evt, expected_evt); i+=1; } } #[test] #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064) fn test_streaming_parser() { assert_stream_equal( r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#, vec![ (ObjectStart, vec![]), (StringValue("bar".to_string()), vec![Key("foo")]), (ArrayStart, vec![Key("array")]), (U64Value(0), vec![Key("array"), Index(0)]), (U64Value(1), vec![Key("array"), Index(1)]), (U64Value(2), vec![Key("array"), Index(2)]), (U64Value(3), vec![Key("array"), Index(3)]), (U64Value(4), vec![Key("array"), Index(4)]), (U64Value(5), vec![Key("array"), Index(5)]), (ArrayEnd, vec![Key("array")]), (ArrayStart, vec![Key("idents")]), (NullValue, vec![Key("idents"), Index(0)]), (BooleanValue(true), vec![Key("idents"), Index(1)]), (BooleanValue(false), vec![Key("idents"), Index(2)]), (ArrayEnd, vec![Key("idents")]), (ObjectEnd, vec![]), ] ); } fn last_event(src: &str) -> JsonEvent { let mut parser = Parser::new(src.chars()); let mut evt = NullValue; loop { evt = match parser.next() { Some(e) => e, None => return evt, } } } #[test] #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064) fn test_read_object_streaming() { assert_eq!(last_event("{ "), Error(SyntaxError(EOFWhileParsingObject, 1, 3))); assert_eq!(last_event("{1"), Error(SyntaxError(KeyMustBeAString, 1, 2))); assert_eq!(last_event("{ \"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); assert_eq!(last_event("{\"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 5))); assert_eq!(last_event("{\"a\" "), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); assert_eq!(last_event("{\"a\" 1"), Error(SyntaxError(ExpectedColon, 1, 6))); assert_eq!(last_event("{\"a\":"), Error(SyntaxError(EOFWhileParsingValue, 1, 6))); assert_eq!(last_event("{\"a\":1"), Error(SyntaxError(EOFWhileParsingObject, 1, 7))); assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax, 1, 8))); assert_eq!(last_event("{\"a\":1,"), Error(SyntaxError(EOFWhileParsingObject, 1, 8))); assert_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8))); assert_stream_equal( "{}", vec![(ObjectStart, vec![]), (ObjectEnd, vec![])] ); assert_stream_equal( "{\"a\": 3}", vec![ (ObjectStart, vec![]), (U64Value(3), vec![Key("a")]), (ObjectEnd, vec![]), ] ); assert_stream_equal( "{ \"a\": null, \"b\" : true }", vec![ (ObjectStart, vec![]), (NullValue, vec![Key("a")]), (BooleanValue(true), vec![Key("b")]), (ObjectEnd, vec![]), ] ); assert_stream_equal( "{\"a\" : 1.0 ,\"b\": [ true ]}", vec![ (ObjectStart, vec![]), (F64Value(1.0), vec![Key("a")]), (ArrayStart, vec![Key("b")]), (BooleanValue(true),vec![Key("b"), Index(0)]), (ArrayEnd, vec![Key("b")]), (ObjectEnd, vec![]), ] ); assert_stream_equal( r#"{ "a": 1.0, "b": [ true, "foo\nbar", { "c": {"d": null} }, "\uD834\uDF06" ] }"#, vec![ (ObjectStart, vec![]), (F64Value(1.0), vec![Key("a")]), (ArrayStart, vec![Key("b")]), (BooleanValue(true), vec![Key("b"), Index(0)]), (StringValue("foo\nbar".to_string()), vec![Key("b"), Index(1)]), (ObjectStart, vec![Key("b"), Index(2)]), (ObjectStart, vec![Key("b"), Index(2), Key("c")]), (NullValue, vec![Key("b"), Index(2), Key("c"), Key("d")]), (ObjectEnd, vec![Key("b"), Index(2), Key("c")]), (ObjectEnd, vec![Key("b"), Index(2)]), (StringValue("\u{1D306}".to_string()), vec![Key("b"), Index(3)]), (ArrayEnd, vec![Key("b")]), (ObjectEnd, vec![]), ] ); } #[test] #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064) fn test_read_array_streaming() { assert_stream_equal( "[]", vec![ (ArrayStart, vec![]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[ ]", vec![ (ArrayStart, vec![]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[true]", vec![ (ArrayStart, vec![]), (BooleanValue(true), vec![Index(0)]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[ false ]", vec![ (ArrayStart, vec![]), (BooleanValue(false), vec![Index(0)]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[null]", vec![ (ArrayStart, vec![]), (NullValue, vec![Index(0)]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[3, 1]", vec![ (ArrayStart, vec![]), (U64Value(3), vec![Index(0)]), (U64Value(1), vec![Index(1)]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "\n[3, 2]\n", vec![ (ArrayStart, vec![]), (U64Value(3), vec![Index(0)]), (U64Value(2), vec![Index(1)]), (ArrayEnd, vec![]), ] ); assert_stream_equal( "[2, [4, 1]]", vec![ (ArrayStart, vec![]), (U64Value(2), vec![Index(0)]), (ArrayStart, vec![Index(1)]), (U64Value(4), vec![Index(1), Index(0)]), (U64Value(1), vec![Index(1), Index(1)]), (ArrayEnd, vec![Index(1)]), (ArrayEnd, vec![]), ] ); assert_eq!(last_event("["), Error(SyntaxError(EOFWhileParsingValue, 1, 2))); assert_eq!(Json::from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); assert_eq!(Json::from_str("[1"), Err(SyntaxError(EOFWhileParsingArray, 1, 3))); assert_eq!(Json::from_str("[1,"), Err(SyntaxError(EOFWhileParsingValue, 1, 4))); assert_eq!(Json::from_str("[1,]"), Err(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(Json::from_str("[6 7]"), Err(SyntaxError(InvalidSyntax, 1, 4))); } #[test] fn test_trailing_characters_streaming() { assert_eq!(last_event("nulla"), Error(SyntaxError(TrailingCharacters, 1, 5))); assert_eq!(last_event("truea"), Error(SyntaxError(TrailingCharacters, 1, 5))); assert_eq!(last_event("falsea"), Error(SyntaxError(TrailingCharacters, 1, 6))); assert_eq!(last_event("1a"), Error(SyntaxError(TrailingCharacters, 1, 2))); assert_eq!(last_event("[]a"), Error(SyntaxError(TrailingCharacters, 1, 3))); assert_eq!(last_event("{}a"), Error(SyntaxError(TrailingCharacters, 1, 3))); } #[test] fn test_read_identifiers_streaming() { assert_eq!(Parser::new("null".chars()).next(), Some(NullValue)); assert_eq!(Parser::new("true".chars()).next(), Some(BooleanValue(true))); assert_eq!(Parser::new("false".chars()).next(), Some(BooleanValue(false))); assert_eq!(last_event("n"), Error(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(last_event("nul"), Error(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(last_event("t"), Error(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(last_event("truz"), Error(SyntaxError(InvalidSyntax, 1, 4))); assert_eq!(last_event("f"), Error(SyntaxError(InvalidSyntax, 1, 2))); assert_eq!(last_event("faz"), Error(SyntaxError(InvalidSyntax, 1, 3))); } #[test] fn test_stack() { let mut stack = Stack::new(); assert!(stack.is_empty()); assert!(stack.len() == 0); assert!(!stack.last_is_index()); stack.push_index(0); stack.bump_index(); assert!(stack.len() == 1); assert!(stack.is_equal_to(&[Index(1)])); assert!(stack.starts_with(&[Index(1)])); assert!(stack.ends_with(&[Index(1)])); assert!(stack.last_is_index()); assert!(stack.get(0) == Index(1)); stack.push_key("foo".to_string()); assert!(stack.len() == 2); assert!(stack.is_equal_to(&[Index(1), Key("foo")])); assert!(stack.starts_with(&[Index(1), Key("foo")])); assert!(stack.starts_with(&[Index(1)])); assert!(stack.ends_with(&[Index(1), Key("foo")])); assert!(stack.ends_with(&[Key("foo")])); assert!(!stack.last_is_index()); assert!(stack.get(0) == Index(1)); assert!(stack.get(1) == Key("foo")); stack.push_key("bar".to_string()); assert!(stack.len() == 3); assert!(stack.is_equal_to(&[Index(1), Key("foo"), Key("bar")])); assert!(stack.starts_with(&[Index(1)])); assert!(stack.starts_with(&[Index(1), Key("foo")])); assert!(stack.starts_with(&[Index(1), Key("foo"), Key("bar")])); assert!(stack.ends_with(&[Key("bar")])); assert!(stack.ends_with(&[Key("foo"), Key("bar")])); assert!(stack.ends_with(&[Index(1), Key("foo"), Key("bar")])); assert!(!stack.last_is_index()); assert!(stack.get(0) == Index(1)); assert!(stack.get(1) == Key("foo")); assert!(stack.get(2) == Key("bar")); stack.pop(); assert!(stack.len() == 2); assert!(stack.is_equal_to(&[Index(1), Key("foo")])); assert!(stack.starts_with(&[Index(1), Key("foo")])); assert!(stack.starts_with(&[Index(1)])); assert!(stack.ends_with(&[Index(1), Key("foo")])); assert!(stack.ends_with(&[Key("foo")])); assert!(!stack.last_is_index()); assert!(stack.get(0) == Index(1)); assert!(stack.get(1) == Key("foo")); } #[test] fn test_to_json() { use std::collections::{HashMap,BTreeMap}; use super::ToJson; let array2 = Array(vec!(I64(1), I64(2))); let array3 = Array(vec!(I64(1), I64(2), I64(3))); let object = { let mut tree_map = BTreeMap::new(); tree_map.insert("a".to_string(), U64(1)); tree_map.insert("b".to_string(), U64(2)); Object(tree_map) }; assert_eq!(array2.to_json(), array2); assert_eq!(object.to_json(), object); assert_eq!(3_isize.to_json(), I64(3)); assert_eq!(4_i8.to_json(), I64(4)); assert_eq!(5_i16.to_json(), I64(5)); assert_eq!(6_i32.to_json(), I64(6)); assert_eq!(7_i64.to_json(), I64(7)); assert_eq!(8_usize.to_json(), U64(8)); assert_eq!(9_u8.to_json(), U64(9)); assert_eq!(10_u16.to_json(), U64(10)); assert_eq!(11_u32.to_json(), U64(11)); assert_eq!(12_u64.to_json(), U64(12)); assert_eq!(13.0_f32.to_json(), F64(13.0_f64)); assert_eq!(14.0_f64.to_json(), F64(14.0_f64)); assert_eq!(().to_json(), Null); assert_eq!(f32::INFINITY.to_json(), Null); assert_eq!(f64::NAN.to_json(), Null); assert_eq!(true.to_json(), Boolean(true)); assert_eq!(false.to_json(), Boolean(false)); assert_eq!("abc".to_json(), String("abc".to_string())); assert_eq!("abc".to_string().to_json(), String("abc".to_string())); assert_eq!((1, 2).to_json(), array2); assert_eq!((1, 2, 3).to_json(), array3); assert_eq!([1, 2].to_json(), array2); assert_eq!((&[1, 2, 3]).to_json(), array3); assert_eq!((vec![1, 2]).to_json(), array2); assert_eq!(vec!(1, 2, 3).to_json(), array3); let mut tree_map = BTreeMap::new(); tree_map.insert("a".to_string(), 1 as u32); tree_map.insert("b".to_string(), 2); assert_eq!(tree_map.to_json(), object); let mut hash_map = HashMap::new(); hash_map.insert("a".to_string(), 1 as u32); hash_map.insert("b".to_string(), 2); assert_eq!(hash_map.to_json(), object); assert_eq!(Some(15).to_json(), I64(15)); assert_eq!(Some(15 as u32).to_json(), U64(15)); assert_eq!(None::.to_json(), Null); } #[test] fn test_encode_hashmap_with_arbitrary_key() { use std::collections::HashMap; #[derive(PartialEq, Eq, Hash, RustcEncodable)] struct ArbitraryType(u32); let mut hm: HashMap = HashMap::new(); hm.insert(ArbitraryType(1), true); let mut mem_buf = string::String::new(); let mut encoder = Encoder::new(&mut mem_buf); let result = hm.encode(&mut encoder); match result.err().unwrap() { EncoderError::BadHashmapKey => (), _ => panic!("expected bad hash map key") } } #[test] fn test_encode_decode_phantom_data() { use std::marker::PhantomData; #[derive(Debug, RustcDecodable, RustcEncodable, Eq, PartialEq)] struct Foo

{ phantom_data: PhantomData

} let f: Foo = Foo { phantom_data: PhantomData }; let s = super::encode(&f).unwrap(); let d: Foo = super::decode(&s).unwrap(); assert_eq!(f, d); } #[test] fn test_bad_json_stack_depleted() { use json; #[derive(Debug, RustcDecodable)] enum ChatEvent { Variant(i32) } let serialized = "{\"variant\": \"Variant\", \"fields\": []}"; let r: Result = json::decode(serialized); assert!(r.unwrap_err() == EOF); } #[test] fn fixed_length_array() { #[derive(Debug, RustcDecodable, RustcEncodable, Eq, PartialEq)] struct Foo { a: [u8; 1], b: [i32; 2], c: [u64; 3], } let f = Foo { a: [0], b: [1, 2], c: [3, 4, 5], }; let s = super::encode(&f).unwrap(); let d = super::decode(&s).unwrap(); assert_eq!(f, d); } #[test] fn test_unexpected_token() { match Json::from_str("{\"\":\"\",\"\":{\"\":\"\",\"\":[{\"\":\"\",}}}") { Err(e) => assert_eq!(e, SyntaxError(InvalidSyntax, 1, 32)), _ => () }; } } rustc-serialize-0.3.24/src/lib.rs01006640001750000175000000004766130764103010015063 0ustar0000000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Support code for encoding and decoding types. //! //! > **NOTE**: This crate is deprecated in favor of [`serde`]. No new feature //! > development will happen in this crate, although bug fixes proposed through //! > PRs will still be merged. It is very highly recommended by the Rust //! > Library Team that you use [`serde`], not this crate. //! //! [`serde`]: https://serde.rs //! //! # Usage //! //! This crate is [on crates.io](https://crates.io/crates/rustc-serialize) and //! can be used by adding `rustc-serialize` to the dependencies in your //! project's `Cargo.toml`. //! //! ```toml //! [dependencies] //! rustc-serialize = "0.3" //! ``` //! //! and this to your crate root: //! //! ```rust //! extern crate rustc_serialize; //! ``` #![cfg_attr(rustbuild, feature(staged_api, rustc_private))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/rustc-serialize/")] #![cfg_attr(test, deny(warnings))] #![allow(trivial_numeric_casts)] #![cfg_attr(rust_build, feature(staged_api))] #![cfg_attr(rust_build, staged_api)] #![cfg_attr(rust_build, unstable(feature = "rustc_private", reason = "use the crates.io `rustc-serialize` library instead"))] #[cfg(test)] extern crate rand; pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, DecoderHelpers, EncoderHelpers}; // Limit collections from allocating more than // 1 MB for calls to `with_capacity`. fn cap_capacity(given_len: usize) -> usize { use std::cmp::min; use std::mem::size_of; const PRE_ALLOCATE_CAP: usize = 0x100000; match size_of::() { 0 => min(given_len, PRE_ALLOCATE_CAP), n => min(given_len, PRE_ALLOCATE_CAP / n) } } mod serialize; mod collection_impls; pub mod base64; pub mod hex; pub mod json; mod rustc_serialize { pub use serialize::*; } rustc-serialize-0.3.24/src/serialize.rs01006640001750000175000000164315130217423710016306 0ustar0000000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Support code for encoding and decoding types. //! //! In order to allow extensibility in both what types can be encoded and how //! they are encoded, encoding and decoding are split into two part each. An //! implementation of the Encodable trait knows how to turn a specific type into //! a generic form, and then uses an implementation of the Encoder trait to turn //! this into concrete output (such as a JSON string). Decoder and Decodable do //! the same for decoding. /* Core encoding and decoding interfaces. */ use std::cell::{Cell, RefCell}; use std::ffi::OsString; use std::path; use std::rc::Rc; use std::sync::Arc; use std::marker::PhantomData; use std::borrow::Cow; use cap_capacity; /// Trait for writing out an encoding when serializing. /// /// This trait provides methods to encode basic types and generic forms of /// collections. Implementations of `Encodable` use it to perform the actual /// encoding of a type. /// /// It is unspecified what is done with the encoding - it could be stored in a /// variable, or written directly to a file, for example. /// /// Encoders can expect to only have a single "root" method call made on this /// trait. Non-trivial types will call one of the collection-emitting methods, /// passing a function that may call other methods on the trait, but once the /// collection-emitting method has returned, encoding should be complete. pub trait Encoder { /// The error type for method results. type Error; // Primitive types: /// Emit a nil value. /// /// For example, this might be stored as the null keyword in JSON. fn emit_nil(&mut self) -> Result<(), Self::Error>; /// Emit a usize value. fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>; /// Emit a u64 value. fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; /// Emit a u32 value. fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; /// Emit a u16 value. fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; /// Emit a u8 value. fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; /// Emit a isize value. fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>; /// Emit a i64 value. fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; /// Emit a i32 value. fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; /// Emit a i16 value. fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; /// Emit a i8 value. fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; /// Emit a bool value. /// /// For example, this might be stored as the true and false keywords in /// JSON. fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; /// Emit a f64 value. fn emit_f64(&mut self, v: f64) -> Result<(), Self::Error>; /// Emit a f32 value. fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; /// Emit a char value. /// /// Note that strings should be emitted using `emit_str`, not as a sequence /// of `emit_char` calls. fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; /// Emit a string value. fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; // Compound types: /// Emit an enumeration value. /// /// * `name` indicates the enumeration type name. /// * `f` is a function that will call `emit_enum_variant` or /// `emit_enum_struct_variant` as appropriate to write the actual value. fn emit_enum(&mut self, name: &str, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a enumeration variant value with no or unnamed data. /// /// This should only be called from a function passed to `emit_enum`. /// Variants with named data should use `emit_enum_struct_variant`. /// /// * `v_name` is the variant name /// * `v_id` is the numeric identifier for the variant. /// * `len` is the number of data items associated with the variant. /// * `f` is a function that will call `emit_enum_variant_arg` for each data /// item. It may not be called if len is 0. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// enum Message { /// Quit, /// ChangeColor(i32, i32, i32), /// } /// /// impl Encodable for Message { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_enum("Message", |s| { /// match *self { /// Message::Quit => { /// s.emit_enum_variant("Quit", 0, 0, |s| Ok(())) /// } /// Message::ChangeColor(r, g, b) => { /// s.emit_enum_variant("ChangeColor", 1, 3, |s| { /// try!(s.emit_enum_variant_arg(0, |s| { /// s.emit_i32(r) /// })); /// try!(s.emit_enum_variant_arg(1, |s| { /// s.emit_i32(g) /// })); /// try!(s.emit_enum_variant_arg(2, |s| { /// s.emit_i32(b) /// })); /// Ok(()) /// }) /// } /// } /// }) /// } /// } /// ``` fn emit_enum_variant(&mut self, v_name: &str, v_id: usize, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit an unnamed data item for an enumeration variant. /// /// This should only be called from a function passed to /// `emit_enum_variant`. /// /// * `a_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that variant data items must be emitted in order - starting with /// index `0` and finishing with index `len-1`. fn emit_enum_variant_arg(&mut self, a_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a enumeration variant value with no or named data. /// /// This should only be called from a function passed to `emit_enum`. /// Variants with unnamed data should use `emit_enum_variant`. /// /// * `v_name` is the variant name. /// * `v_id` is the numeric identifier for the variant. /// * `len` is the number of data items associated with the variant. /// * `f` is a function that will call `emit_enum_struct_variant_field` for /// each data item. It may not be called if `len` is `0`. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// enum Message { /// Quit, /// Move { x: i32, y: i32 }, /// } /// /// impl Encodable for Message { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_enum("Message", |s| { /// match *self { /// Message::Quit => { /// s.emit_enum_struct_variant("Quit", 0, 0, |s| Ok(())) /// } /// Message::Move { x: x, y: y } => { /// s.emit_enum_struct_variant("Move", 1, 2, |s| { /// try!(s.emit_enum_struct_variant_field("x", 0, |s| { /// s.emit_i32(x) /// })); /// try!(s.emit_enum_struct_variant_field("y", 1, |s| { /// s.emit_i32(y) /// })); /// Ok(()) /// }) /// } /// } /// }) /// } /// } /// ``` fn emit_enum_struct_variant(&mut self, v_name: &str, v_id: usize, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a named data item for an enumeration variant. /// /// This should only be called from a function passed to /// `emit_enum_struct_variant`. /// /// * `f_name` is the name of the data item field. /// * `f_idx` is its (zero-based) index. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that fields must be emitted in order - starting with index `0` and /// finishing with index `len-1`. fn emit_enum_struct_variant_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a struct value. /// /// * `name` is the name of the struct. /// * `len` is the number of members. /// * `f` is a function that calls `emit_struct_field` for each member. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// struct Point { /// x: i32, /// y: i32, /// } /// /// impl Encodable for Point { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_struct("Point", 2, |s| { /// try!(s.emit_struct_field("x", 0, |s| { /// s.emit_i32(self.x) /// })); /// try!(s.emit_struct_field("y", 1, |s| { /// s.emit_i32(self.y) /// })); /// Ok(()) /// }) /// } /// } /// ``` fn emit_struct(&mut self, name: &str, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a field item for a struct. /// /// This should only be called from a function passed to `emit_struct`. /// /// * `f_name` is the name of the data item field. /// * `f_idx` is its (zero-based) index. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that fields must be emitted in order - starting with index `0` and /// finishing with index `len-1`. fn emit_struct_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a tuple value. /// /// * `len` is the number of items in the tuple. /// * `f` is a function that calls `emit_tuple_arg` for each member. /// /// Note that external `Encodable` implementations should not normally need /// to use this method directly; it is meant for the use of this module's /// own implementation of `Encodable` for tuples. fn emit_tuple(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a data item for a tuple. /// /// This should only be called from a function passed to `emit_tuple`. /// /// * `idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that tuple items must be emitted in order - starting with index `0` /// and finishing with index `len-1`. fn emit_tuple_arg(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a tuple struct value. /// /// * `name` is the name of the tuple struct. /// * `len` is the number of items in the tuple struct. /// * `f` is a function that calls `emit_tuple_struct_arg` for each member. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// struct Pair(i32,i32); /// /// impl Encodable for Pair { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// let Pair(first,second) = *self; /// s.emit_tuple_struct("Pair", 2, |s| { /// try!(s.emit_tuple_arg(0, |s| { /// s.emit_i32(first) /// })); /// try!(s.emit_tuple_arg(1, |s| { /// s.emit_i32(second) /// })); /// Ok(()) /// }) /// } /// } /// ``` fn emit_tuple_struct(&mut self, name: &str, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a data item for a tuple struct. /// /// This should only be called from a function passed to /// `emit_tuple_struct`. /// /// * `f_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that tuple items must be emitted in order - starting with index `0` /// and finishing with index `len-1`. fn emit_tuple_struct_arg(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; // Specialized types: /// Emit an optional value. /// /// `f` is a function that will call either `emit_option_none` or /// `emit_option_some` as appropriate. /// /// This method allows encoders to handle `Option` values specially, /// rather than using the generic enum methods, because many encoding /// formats have a built-in "optional" concept. /// /// Note that external `Encodable` implementations should not normally need /// to use this method directly; it is meant for the use of this module's /// own implementation of `Encodable` for `Option`. fn emit_option(&mut self, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit the `None` optional value. /// /// This should only be called from a function passed to `emit_option`. fn emit_option_none(&mut self) -> Result<(), Self::Error>; /// Emit the `Some(x)` optional value. /// /// `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// This should only be called from a function passed to `emit_option`. fn emit_option_some(&mut self, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit a sequence of values. /// /// This should be used for both array-like ordered sequences and set-like /// unordered ones. /// /// * `len` is the number of values in the sequence. /// * `f` is a function that will call `emit_seq_elt` for each value in the /// sequence. fn emit_seq(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit an element in a sequence. /// /// This should only be called from a function passed to `emit_seq`. /// /// * `idx` is the (zero-based) index of the value in the sequence. /// * `f` is a function that will call the appropriate emit method to encode /// the data object. /// /// Note that sequence elements must be emitted in order - starting with /// index `0` and finishing with index `len-1`. fn emit_seq_elt(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit an associative container (map). /// /// * `len` is the number of entries in the map. /// * `f` is a function that will call `emit_map_elt_key` and /// `emit_map_elt_val` for each entry in the map. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// struct SimpleMap { /// entries: Vec<(K,V)>, /// } /// /// impl Encodable for SimpleMap { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_map(self.entries.len(), |s| { /// for (i, e) in self.entries.iter().enumerate() { /// let (ref k, ref v) = *e; /// try!(s.emit_map_elt_key(i, |s| k.encode(s))); /// try!(s.emit_map_elt_val(i, |s| v.encode(s))); /// } /// Ok(()) /// }) /// } /// } /// ``` fn emit_map(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit the key for an entry in a map. /// /// This should only be called from a function passed to `emit_map`. /// /// * `idx` is the (zero-based) index of the entry in the map /// * `f` is a function that will call the appropriate emit method to encode /// the key. /// /// Note that map entries must be emitted in order - starting with index `0` /// and finishing with index `len-1` - and for each entry, the key should be /// emitted followed immediately by the value. fn emit_map_elt_key(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; /// Emit the value for an entry in a map. /// /// This should only be called from a function passed to `emit_map`. /// /// * `idx` is the (zero-based) index of the entry in the map /// * `f` is a function that will call the appropriate emit method to encode /// the value. /// /// Note that map entries must be emitted in order - starting with index `0` /// and finishing with index `len-1` - and for each entry, the key should be /// emitted followed immediately by the value. fn emit_map_elt_val(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; } /// Trait for reading in an encoding for deserialization. /// /// This trait provides methods to decode basic types and generic forms of /// collections. Implementations of `Decodable` use it to perform the actual /// decoding of a type. /// /// Note that, as is typical with deserialization, the design of this API /// assumes you know in advance the form of the data you are decoding (ie: what /// type is encoded). /// /// Decoders can expect to only have a single "root" method call made on this /// trait. Non-trivial types will call one of the collection-reading methods, /// passing a function that may call other methods on the trait, but once the /// collection-reading method has returned, decoding should be complete. pub trait Decoder { /// The error type for method results. type Error; // Primitive types: /// Read a nil value. fn read_nil(&mut self) -> Result<(), Self::Error>; /// Read a usize value. fn read_usize(&mut self) -> Result; /// Read a u64 value. fn read_u64(&mut self) -> Result; /// Read a u32 value. fn read_u32(&mut self) -> Result; /// Read a u16 value. fn read_u16(&mut self) -> Result; /// Read a u8 value. fn read_u8(&mut self) -> Result; /// Read a isize value. fn read_isize(&mut self) -> Result; /// Read a i64 value. fn read_i64(&mut self) -> Result; /// Read a i32 value. fn read_i32(&mut self) -> Result; /// Read a i16 value. fn read_i16(&mut self) -> Result; /// Read a i8 value. fn read_i8(&mut self) -> Result; /// Read a bool value. fn read_bool(&mut self) -> Result; /// Read a f64 value. fn read_f64(&mut self) -> Result; /// Read a f32 value. fn read_f32(&mut self) -> Result; /// Read a char value. fn read_char(&mut self) -> Result; /// Read a string value. fn read_str(&mut self) -> Result; // Compound types: /// Read an enumeration value. /// /// * `name` indicates the enumeration type name. It may be used to /// sanity-check the data being read. /// * `f` is a function that will call `read_enum_variant` (or /// `read_enum_struct_variant`) to read the actual value. fn read_enum(&mut self, name: &str, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read an enumeration value. /// /// * `names` is a list of the enumeration variant names. /// * `f` is a function that will call `read_enum_variant_arg` or /// `read_enum_struct_variant_field` as appropriate to read the /// associated values. It will be passed the index into `names` for the /// variant that is encoded. fn read_enum_variant(&mut self, names: &[&str], f: F) -> Result where F: FnMut(&mut Self, usize) -> Result; /// Read an unnamed data item for an enumeration variant. /// /// This should only be called from a function passed to `read_enum_variant` /// or `read_enum_struct_variant`, and only when the index provided to that /// function indicates that the variant has associated unnamed data. It /// should be called once for each associated data item. /// /// * `a_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate read method to deocde /// the data object. /// /// Note that variant data items must be read in order - starting with index /// `0` and finishing with index `len-1`. Implementations may use `a_idx`, /// the call order or both to select the correct data to decode. fn read_enum_variant_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read an enumeration value. /// /// This is identical to `read_enum_variant`, and is only provided for /// symmetry with the `Encoder` API. fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> Result where F: FnMut(&mut Self, usize) -> Result; /// Read a named data item for an enumeration variant. /// /// This should only be called from a function passed to `read_enum_variant` /// or `read_enum_struct_variant`, and only when the index provided to that /// function indicates that the variant has associated named data. It should /// be called once for each associated field. /// /// * `f_name` is the name of the field. /// * `f_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate read method to deocde /// the data object. /// /// Note that fields must be read in order - starting with index `0` and /// finishing with index `len-1`. Implementations may use `f_idx`, `f_name`, /// the call order or any combination to choose the correct data to decode, /// and may (but are not required to) return an error if these are /// inconsistent. fn read_enum_struct_variant_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read an struct value. /// /// * `s_name` indicates the struct type name. It may be used to /// sanity-check the data being read. /// * `len` indicates the number of fields in the struct. /// * `f` is a function that will call `read_struct_field` for each field in /// the struct. fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read a field for a struct value. /// /// This should only be called from a function passed to `read_struct`. It /// should be called once for each associated field. /// /// * `f_name` is the name of the field. /// * `f_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate read method to deocde /// the data object. /// /// Note that fields must be read in order - starting with index `0` and /// finishing with index `len-1`. Implementations may use `f_idx`, `f_name`, /// the call order or any combination to choose the correct data to decode, /// and may (but are not required to) return an error if these are /// inconsistent. fn read_struct_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read a tuple value. /// /// * `len` is the number of items in the tuple. /// * `f` is a function that will call `read_tuple_arg` for each item in the /// tuple. /// /// Note that external `Decodable` implementations should not normally need /// to use this method directly; it is meant for the use of this module's /// own implementation of `Decodable` for tuples. fn read_tuple(&mut self, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read a data item for a tuple. /// /// This should only be called from a function passed to `read_tuple`. /// /// * `a_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate read method to encode /// the data object. /// /// Note that tuple items must be read in order - starting with index `0` /// and finishing with index `len-1`. fn read_tuple_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read a tuple struct value. /// /// * `s_name` is the name of the tuple struct. /// * `len` is the number of items in the tuple struct. /// * `f` is a function that calls `read_tuple_struct_arg` for each member. fn read_tuple_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read a data item for a tuple struct. /// /// This should only be called from a function passed to /// `read_tuple_struct`. /// /// * `a_idx` is the (zero-based) index of the data item. /// * `f` is a function that will call the appropriate read method to encode /// the data object. /// /// Note that tuple struct items must be read in order - starting with index /// `0` and finishing with index `len-1`. fn read_tuple_struct_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; // Specialized types: /// Read an optional value. /// /// `f` is a function that will will be passed be passed `false` if the /// value is unset, and `true` if it is set. If the function is passed /// `true`, it will call the appropriate read methods to read the associated /// data type. /// /// This method allows decoders to handle `Option` values specially, /// rather than using the generic enum methods, because many encoding /// formats have a built-in "optional" concept. /// /// Note that external `Decodable` implementations should not normally need /// to use this method directly; it is meant for the use of this module's /// own implementation of `Decodable` for `Option`. fn read_option(&mut self, f: F) -> Result where F: FnMut(&mut Self, bool) -> Result; /// Read a sequence of values. /// /// This should be used for both array-like ordered sequences and set-like /// unordered ones. /// /// * `f` is a function that will be passed the length of the sequence, and /// will call `read_seq_elt` for each value in the sequence. fn read_seq(&mut self, f: F) -> Result where F: FnOnce(&mut Self, usize) -> Result; /// Read an element in the sequence. /// /// This should only be called from a function passed to `read_seq`. /// /// * `idx` is the (zero-based) index of the value in the sequence. /// * `f` is a function that will call the appropriate read method to decode /// the data object. /// /// Note that sequence elements must be read in order - starting with index /// `0` and finishing with index `len-1`. fn read_seq_elt(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read an associative container (map). /// /// * `f` is a function that will be passed the number of entries in the /// map, and will call `read_map_elt_key` and `read_map_elt_val` to decode /// each entry. fn read_map(&mut self, f: F) -> Result where F: FnOnce(&mut Self, usize) -> Result; /// Read the key for an entry in a map. /// /// This should only be called from a function passed to `read_map`. /// /// * `idx` is the (zero-based) index of the entry in the map /// * `f` is a function that will call the appropriate read method to decode /// the key. /// /// Note that map entries must be read in order - starting with index `0` /// and finishing with index `len-1` - and for each entry, the key should be /// read followed immediately by the value. fn read_map_elt_key(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; /// Read the value for an entry in a map. /// /// This should only be called from a function passed to `read_map`. /// /// * `idx` is the (zero-based) index of the entry in the map /// * `f` is a function that will call the appropriate read method to decode /// the value. /// /// Note that map entries must be read in order - starting with index `0` /// and finishing with index `len-1` - and for each entry, the key should be /// read followed immediately by the value. fn read_map_elt_val(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; // Failure /// Record a decoding error. /// /// This allows `Decodable` implementations to report an error using a /// `Decoder` implementation's error type when inconsistent data is read. /// For example, when reading a fixed-length array and the wrong length is /// given by `read_seq`. fn error(&mut self, err: &str) -> Self::Error; } /// Trait for serializing a type. /// /// This can be implemented for custom data types to allow them to be encoded /// with `Encoder` implementations. Most of Rust's built-in or standard data /// types (like `i32` and `Vec`) have `Encodable` implementations provided by /// this module. /// /// Note that, in general, you should let the compiler implement this for you by /// using the `derive(RustcEncodable)` attribute. /// /// # Examples /// /// ```rust /// extern crate rustc_serialize; /// /// #[derive(RustcEncodable)] /// struct Point { /// x: i32, /// y: i32, /// } /// # fn main() {} /// ``` /// /// This generates code equivalent to: /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// /// struct Point { /// x: i32, /// y: i32, /// } /// /// impl Encodable for Point { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_struct("Point", 2, |s| { /// try!(s.emit_struct_field("x", 0, |s| { /// s.emit_i32(self.x) /// })); /// try!(s.emit_struct_field("y", 1, |s| { /// s.emit_i32(self.y) /// })); /// Ok(()) /// }) /// } /// } /// # fn main() {} /// ``` pub trait Encodable { /// Serialize a value using an `Encoder`. fn encode(&self, s: &mut S) -> Result<(), S::Error>; } /// Trait for deserializing a type. /// /// This can be implemented for custom data types to allow them to be decoded /// with `Decoder` implementations. Most of Rust's built-in or standard data /// types (like `i32` and `Vec`) have `Decodable` implementations provided by /// this module. /// /// Note that, in general, you should let the compiler implement this for you by /// using the `derive(RustcDecodable)` attribute. /// /// # Examples /// /// ```rust /// extern crate rustc_serialize; /// /// #[derive(RustcDecodable)] /// struct Point { /// x: i32, /// y: i32, /// } /// # fn main() {} /// ``` /// /// This generates code equivalent to: /// /// ```rust /// extern crate rustc_serialize; /// use rustc_serialize::Decodable; /// use rustc_serialize::Decoder; /// /// struct Point { /// x: i32, /// y: i32, /// } /// /// impl Decodable for Point { /// fn decode(d: &mut D) -> Result { /// d.read_struct("Point", 2, |d| { /// let x = try!(d.read_struct_field("x", 0, |d| { d.read_i32() })); /// let y = try!(d.read_struct_field("y", 1, |d| { d.read_i32() })); /// Ok(Point{ x: x, y: y }) /// }) /// } /// } /// # fn main() {} /// ``` pub trait Decodable: Sized { /// Deserialize a value using a `Decoder`. fn decode(d: &mut D) -> Result; } impl Encodable for usize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_usize(*self) } } impl Decodable for usize { fn decode(d: &mut D) -> Result { d.read_usize() } } impl Encodable for u8 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(*self) } } impl Decodable for u8 { fn decode(d: &mut D) -> Result { d.read_u8() } } impl Encodable for u16 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u16(*self) } } impl Decodable for u16 { fn decode(d: &mut D) -> Result { d.read_u16() } } impl Encodable for u32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(*self) } } impl Decodable for u32 { fn decode(d: &mut D) -> Result { d.read_u32() } } impl Encodable for u64 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u64(*self) } } impl Decodable for u64 { fn decode(d: &mut D) -> Result { d.read_u64() } } impl Encodable for isize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_isize(*self) } } impl Decodable for isize { fn decode(d: &mut D) -> Result { d.read_isize() } } impl Encodable for i8 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i8(*self) } } impl Decodable for i8 { fn decode(d: &mut D) -> Result { d.read_i8() } } impl Encodable for i16 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i16(*self) } } impl Decodable for i16 { fn decode(d: &mut D) -> Result { d.read_i16() } } impl Encodable for i32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i32(*self) } } impl Decodable for i32 { fn decode(d: &mut D) -> Result { d.read_i32() } } impl Encodable for i64 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i64(*self) } } impl Decodable for i64 { fn decode(d: &mut D) -> Result { d.read_i64() } } impl Encodable for str { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_str(self) } } impl Encodable for String { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_str(self) } } impl Decodable for String { fn decode(d: &mut D) -> Result { d.read_str() } } impl Encodable for f32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_f32(*self) } } impl Decodable for f32 { fn decode(d: &mut D) -> Result { d.read_f32() } } impl Encodable for f64 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_f64(*self) } } impl Decodable for f64 { fn decode(d: &mut D) -> Result { d.read_f64() } } impl Encodable for bool { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_bool(*self) } } impl Decodable for bool { fn decode(d: &mut D) -> Result { d.read_bool() } } impl Encodable for char { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_char(*self) } } impl Decodable for char { fn decode(d: &mut D) -> Result { d.read_char() } } impl Encodable for () { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_nil() } } impl Decodable for () { fn decode(d: &mut D) -> Result<(), D::Error> { d.read_nil() } } impl<'a, T: ?Sized + Encodable> Encodable for &'a T { fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } impl Encodable for Box { fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } impl< T: Decodable> Decodable for Box { fn decode(d: &mut D) -> Result, D::Error> { Ok(Box::new(try!(Decodable::decode(d)))) } } impl< T: Decodable> Decodable for Box<[T]> { fn decode(d: &mut D) -> Result, D::Error> { let v: Vec = try!(Decodable::decode(d)); Ok(v.into_boxed_slice()) } } impl Encodable for Rc { #[inline] fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } impl Decodable for Rc { #[inline] fn decode(d: &mut D) -> Result, D::Error> { Ok(Rc::new(try!(Decodable::decode(d)))) } } impl<'a, T:Encodable + ToOwned + ?Sized> Encodable for Cow<'a, T> { #[inline] fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } impl<'a, T: ?Sized> Decodable for Cow<'a, T> where T: ToOwned, T::Owned: Decodable { #[inline] fn decode(d: &mut D) -> Result, D::Error> { Ok(Cow::Owned(try!(Decodable::decode(d)))) } } impl Encodable for [T] { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { try!(s.emit_seq_elt(i, |s| e.encode(s))) } Ok(()) }) } } impl Encodable for Vec { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { try!(s.emit_seq_elt(i, |s| e.encode(s))) } Ok(()) }) } } impl Decodable for Vec { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut v = Vec::with_capacity(cap_capacity::(len)); for i in 0..len { v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } Ok(v) }) } } impl Encodable for Option { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_option(|s| { match *self { None => s.emit_option_none(), Some(ref v) => s.emit_option_some(|s| v.encode(s)), } }) } } impl Decodable for Option { fn decode(d: &mut D) -> Result, D::Error> { d.read_option(|d, b| { if b { Ok(Some(try!(Decodable::decode(d)))) } else { Ok(None) } }) } } impl Encodable for Result { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_enum("Result", |s| { match *self { Ok(ref v) => { s.emit_enum_variant("Ok", 0, 1, |s| { try!(s.emit_enum_variant_arg(0, |s| { v.encode(s) })); Ok(()) }) } Err(ref v) => { s.emit_enum_variant("Err", 1, 1, |s| { try!(s.emit_enum_variant_arg(0, |s| { v.encode(s) })); Ok(()) }) } } }) } } impl Decodable for Result { fn decode(d: &mut D) -> Result, D::Error> { d.read_enum("Result", |d| { d.read_enum_variant(&["Ok", "Err"], |d, idx| { match idx { 0 => { d.read_enum_variant_arg(0, |d| { T::decode(d) }).map(|v| Ok(v)) } 1 => { d.read_enum_variant_arg(0, |d| { E::decode(d) }).map(|v| Err(v)) } _ => panic!("Internal error"), } }) }) } } impl Encodable for PhantomData { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_nil() } } impl Decodable for PhantomData { fn decode(_d: &mut D) -> Result, D::Error> { Ok(PhantomData) } } macro_rules! peel { ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) } /// Evaluates to the number of identifiers passed to it, for example: /// `count_idents!(a, b, c) == 3 macro_rules! count_idents { () => { 0 }; ($_i:ident, $($rest:ident,)*) => { 1 + count_idents!($($rest,)*) } } macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( impl<$($name:Decodable),*> Decodable for ($($name,)*) { fn decode(d: &mut D) -> Result<($($name,)*), D::Error> { let len: usize = count_idents!($($name,)*); d.read_tuple(len, |d| { let mut i = 0; let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,D::Error> { Decodable::decode(d) })),)*); return Ok(ret); }) } } impl<$($name:Encodable),*> Encodable for ($($name,)*) { #[allow(non_snake_case)] fn encode(&self, s: &mut S) -> Result<(), S::Error> { let ($(ref $name,)*) = *self; let mut n = 0; $(let $name = $name; n += 1;)* s.emit_tuple(n, |s| { let mut i = 0; $(try!(s.emit_tuple_arg({ i+=1; i-1 }, |s| $name.encode(s)));)* Ok(()) }) } } peel! { $($name,)* } ) } tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } macro_rules! array { () => (); ($len:expr, $($idx:expr,)*) => { impl Decodable for [T; $len] { fn decode(d: &mut D) -> Result<[T; $len], D::Error> { d.read_seq(|d, len| { if len != $len { return Err(d.error("wrong array length")); } Ok([$( try!(d.read_seq_elt($len - $idx - 1, |d| Decodable::decode(d))) ),*]) }) } } impl Encodable for [T; $len] { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq($len, |s| { for i in 0..$len { try!(s.emit_seq_elt(i, |s| self[i].encode(s))); } Ok(()) }) } } array! { $($idx,)* } } } array! { 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, } impl Encodable for path::Path { #[cfg(target_os = "redox")] fn encode(&self, e: &mut S) -> Result<(), S::Error> { self.as_os_str().to_str().unwrap().encode(e) } #[cfg(unix)] fn encode(&self, e: &mut S) -> Result<(), S::Error> { use std::os::unix::prelude::*; self.as_os_str().as_bytes().encode(e) } #[cfg(windows)] fn encode(&self, e: &mut S) -> Result<(), S::Error> { use std::os::windows::prelude::*; let v = self.as_os_str().encode_wide().collect::>(); v.encode(e) } } impl Encodable for path::PathBuf { fn encode(&self, e: &mut S) -> Result<(), S::Error> { (**self).encode(e) } } impl Decodable for path::PathBuf { #[cfg(target_os = "redox")] fn decode(d: &mut D) -> Result { let string: String = try!(Decodable::decode(d)); let s: OsString = OsString::from(string); let mut p = path::PathBuf::new(); p.push(s); Ok(p) } #[cfg(unix)] fn decode(d: &mut D) -> Result { use std::os::unix::prelude::*; let bytes: Vec = try!(Decodable::decode(d)); let s: OsString = OsStringExt::from_vec(bytes); let mut p = path::PathBuf::new(); p.push(s); Ok(p) } #[cfg(windows)] fn decode(d: &mut D) -> Result { use std::os::windows::prelude::*; let bytes: Vec = try!(Decodable::decode(d)); let s: OsString = OsStringExt::from_wide(&bytes); let mut p = path::PathBuf::new(); p.push(s); Ok(p) } } impl Encodable for Cell { fn encode(&self, s: &mut S) -> Result<(), S::Error> { self.get().encode(s) } } impl Decodable for Cell { fn decode(d: &mut D) -> Result, D::Error> { Ok(Cell::new(try!(Decodable::decode(d)))) } } // FIXME: #15036 // Should use `try_borrow`, returning a // `encoder.error("attempting to Encode borrowed RefCell")` // from `encode` when `try_borrow` returns `None`. impl Encodable for RefCell { fn encode(&self, s: &mut S) -> Result<(), S::Error> { self.borrow().encode(s) } } impl Decodable for RefCell { fn decode(d: &mut D) -> Result, D::Error> { Ok(RefCell::new(try!(Decodable::decode(d)))) } } impl Encodable for Arc { fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } impl Decodable for Arc { fn decode(d: &mut D) -> Result, D::Error> { Ok(Arc::new(try!(Decodable::decode(d)))) } } // ___________________________________________________________________________ // Helper routines /// Trait with helper functions for implementing `Encodable`. /// /// This trait is implemented for everything that implements `Encoder`. /// `Encodable` implementations can make use of it to make their implementations /// easier. pub trait EncoderHelpers: Encoder { /// Emit a vector as a sequence. /// /// Storing sequences as vectors is a common pattern. This method makes /// encoding such sequences easier by wrapping the calls to /// `Encoder::emit_seq` and `Encoder::emit_seq_elt`. /// /// # Examples /// /// ``` /// use rustc_serialize::Encodable; /// use rustc_serialize::Encoder; /// use rustc_serialize::EncoderHelpers; /// /// struct NumberSequence { /// elements: Vec, /// } /// /// impl Encodable for NumberSequence { /// fn encode(&self, s: &mut S) -> Result<(), S::Error> { /// s.emit_struct("NumberSequence", 1, |s| { /// s.emit_struct_field("elements", 0, |s| { /// s.emit_from_vec(&self.elements, |s,e| { /// s.emit_i32(*e) /// }) /// }) /// }) /// } /// } /// ``` fn emit_from_vec(&mut self, v: &[T], f: F) -> Result<(), ::Error> where F: FnMut(&mut Self, &T) -> Result<(), ::Error>; } impl EncoderHelpers for S { fn emit_from_vec(&mut self, v: &[T], mut f: F) -> Result<(), S::Error> where F: FnMut(&mut S, &T) -> Result<(), S::Error>, { self.emit_seq(v.len(), |this| { for (i, e) in v.iter().enumerate() { try!(this.emit_seq_elt(i, |this| { f(this, e) })); } Ok(()) }) } } /// Trait with helper functions for implementing `Decodable`. /// /// This trait is implemented for everything that implements `Decoder`. /// `Decodable` implementations can make use of it to make their implementations /// easier. pub trait DecoderHelpers: Decoder { /// Read a sequence into a vector. /// /// Storing sequences as vectors is a common pattern. This method makes /// deserializing such sequences easier by wrapping the calls to /// `Decoder::read_seq` and `Decoder::read_seq_elt`. /// /// # Examples /// /// ``` /// use rustc_serialize::Decodable; /// use rustc_serialize::Decoder; /// use rustc_serialize::DecoderHelpers; /// /// struct NumberSequence { /// elements: Vec, /// } /// /// impl Decodable for NumberSequence { /// fn decode(d: &mut D) -> Result { /// d.read_struct("NumberSequence", 2, |d| { /// Ok(NumberSequence{ /// elements: try!(d.read_struct_field("elements", 0, |d| { /// d.read_to_vec(|d| { d.read_i32() }) /// })) /// }) /// }) /// } /// } /// ``` fn read_to_vec(&mut self, f: F) -> Result, ::Error> where F: FnMut(&mut Self) -> Result::Error>; } impl DecoderHelpers for D { fn read_to_vec(&mut self, mut f: F) -> Result, D::Error> where F: FnMut(&mut D) -> Result, { self.read_seq(|this, len| { let mut v = Vec::with_capacity(cap_capacity::(len)); for i in 0..len { v.push(try!(this.read_seq_elt(i, |this| f(this)))); } Ok(v) }) } } #[test] #[allow(unused_variables)] fn capacity_rules() { use std::usize::MAX; use std::collections::{HashMap, HashSet}; struct MyDecoder; impl Decoder for MyDecoder { type Error = (); // Primitive types: fn read_nil(&mut self) -> Result<(), Self::Error> { Err(()) } fn read_usize(&mut self) -> Result { Err(()) } fn read_u64(&mut self) -> Result { Err(()) } fn read_u32(&mut self) -> Result { Err(()) } fn read_u16(&mut self) -> Result { Err(()) } fn read_u8(&mut self) -> Result { Err(()) } fn read_isize(&mut self) -> Result { Err(()) } fn read_i64(&mut self) -> Result { Err(()) } fn read_i32(&mut self) -> Result { Err(()) } fn read_i16(&mut self) -> Result { Err(()) } fn read_i8(&mut self) -> Result { Err(()) } fn read_bool(&mut self) -> Result { Err(()) } fn read_f64(&mut self) -> Result { Err(()) } fn read_f32(&mut self) -> Result { Err(()) } fn read_char(&mut self) -> Result { Err(()) } fn read_str(&mut self) -> Result { Err(()) } // Compound types: fn read_enum(&mut self, name: &str, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_enum_variant(&mut self, names: &[&str], f: F) -> Result where F: FnMut(&mut Self, usize) -> Result { Err(()) } fn read_enum_variant_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> Result where F: FnMut(&mut Self, usize) -> Result { Err(()) } fn read_enum_struct_variant_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_struct_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_tuple(&mut self, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_tuple_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_tuple_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_tuple_struct_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } // Specialized types: fn read_option(&mut self, f: F) -> Result where F: FnMut(&mut Self, bool) -> Result { Err(()) } fn read_seq(&mut self, f: F) -> Result where F: FnOnce(&mut Self, usize) -> Result { f(self, MAX) } fn read_seq_elt(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_map(&mut self, f: F) -> Result where F: FnOnce(&mut Self, usize) -> Result { f(self, MAX) } fn read_map_elt_key(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } fn read_map_elt_val(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result { Err(()) } // Failure fn error(&mut self, err: &str) -> Self::Error { () } } let mut dummy = MyDecoder; let vec_result: Result, ()> = Decodable::decode(&mut dummy); assert!(vec_result.is_err()); let map_result: Result, ()> = Decodable::decode(&mut dummy); assert!(map_result.is_err()); let set_result: Result, ()> = Decodable::decode(&mut dummy); assert!(set_result.is_err()); }