json-0.12.0/.gitignore010064400017500001750000000000221347550352200127540ustar0000000000000000target Cargo.lock json-0.12.0/.travis.yml010064400017500001750000000002411347550352200131000ustar0000000000000000language: rust rust: - stable - beta - nightly branches: except: - dev - benches matrix: allow_failures: - rust: nightly os: - linux json-0.12.0/Cargo.toml.orig010064400017500001750000000004231353450056600136610ustar0000000000000000[package] name = "json" version = "0.12.0" authors = ["Maciej Hirsz "] description = "JSON implementation in Rust" repository = "https://github.com/maciejhirsz/json-rust" documentation = "https://docs.rs/json/" license = "MIT/Apache-2.0" edition = "2018" json-0.12.0/Cargo.toml0000644000000014400000000000000101210ustar00# 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] edition = "2018" name = "json" version = "0.12.0" authors = ["Maciej Hirsz "] description = "JSON implementation in Rust" documentation = "https://docs.rs/json/" license = "MIT/Apache-2.0" repository = "https://github.com/maciejhirsz/json-rust" json-0.12.0/LICENSE-APACHE010064400017500001750000000251541347550352200127250ustar0000000000000000 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 2016 Maciej Hirsz 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. json-0.12.0/LICENSE-MIT010064400017500001750000000021201347550352200124210ustar0000000000000000Copyright (c) 2016 Maciej Hirsz The MIT License (MIT) 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. json-0.12.0/README.md010064400017500001750000000072521347550376200122650ustar0000000000000000# json-rust [![Travis shield](https://travis-ci.org/maciejhirsz/json-rust.svg)](https://travis-ci.org/maciejhirsz/json-rust) [![Crates.io version shield](https://img.shields.io/crates/v/json.svg)](https://crates.io/crates/json) [![Crates.io license shield](https://img.shields.io/crates/l/json.svg)](https://crates.io/crates/json) Parse and serialize [JSON](http://json.org/) with ease. **[Changelog](https://github.com/maciejhirsz/json-rust/releases) -** **[Complete Documentation](https://docs.rs/json/) -** **[Cargo](https://crates.io/crates/json) -** **[Repository](https://github.com/maciejhirsz/json-rust)** ## Why? JSON is a very loose format where anything goes - arrays can hold mixed types, object keys can change types between API calls or not include some keys under some conditions. Mapping that to idiomatic Rust structs introduces friction. This crate intends to avoid that friction. ```rust let parsed = json::parse(r#" { "code": 200, "success": true, "payload": { "features": [ "awesome", "easyAPI", "lowLearningCurve" ] } } "#).unwrap(); let instantiated = object!{ "code" => 200, "success" => true, "payload" => object!{ "features" => array![ "awesome", "easyAPI", "lowLearningCurve" ] } }; assert_eq!(parsed, instantiated); ``` ## First class citizen Using macros and indexing, it's easy to work with the data. ```rust let mut data = object!{ "foo" => false, "bar" => json::Null, "answer" => 42, "list" => array![json::Null, "world", true] }; // Partial equality is implemented for most raw types: assert!(data["foo"] == false); // And it's type aware, `null` and `false` are different values: assert!(data["bar"] != false); // But you can use any Rust number types: assert!(data["answer"] == 42); assert!(data["answer"] == 42.0); assert!(data["answer"] == 42isize); // Access nested structures, arrays and objects: assert!(data["list"][0].is_null()); assert!(data["list"][1] == "world"); assert!(data["list"][2] == true); // Error resilient - accessing properties that don't exist yield null: assert!(data["this"]["does"]["not"]["exist"].is_null()); // Mutate by assigning: data["list"][0] = "Hello".into(); // Use the `dump` method to serialize the data: assert_eq!(data.dump(), r#"{"foo":false,"bar":null,"answer":42,"list":["Hello","world",true]}"#); // Or pretty print it out: println!("{:#}", data); ``` ## Installation Just add it to your `Cargo.toml` file: ```toml [dependencies] json = "*" ``` Then import it in your `main.rs` / `lib.rs` file: ```rust #[macro_use] extern crate json; ``` ## Performance and Conformance There used to be a statement here saying that performance is not the main goal of this crate. It is definitely one of them now. While this crate doesn't provide a way to parse JSON to native Rust structs, it does a lot to optimize its performance for DOM parsing, stringifying and manipulation. It does [very well in benchmarks](https://github.com/serde-rs/json-benchmark), in some cases it can even outperform parsing to structs. This crate implements the standard according to the [ RFC 7159](https://tools.ietf.org/html/rfc7159) and [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) documents. For the best interoperability numbers are treated stored as 64bit precision mantissa with 16 bit decimal exponent for floating point representation. ## License This crate is distributed under the terms of both the MIT license and the Apache License (Version 2.0). Choose whichever one works best for you. See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details. json-0.12.0/benches/log.rs010064400017500001750000000206531347550352200135360ustar0000000000000000// #![feature(custom_derive)] // #![feature(custom_attribute)] #![feature(test)] // #![feature(plugin)] // #![plugin(serde_macros)] // for the Country enum // #![recursion_limit="259"] extern crate json; extern crate test; // extern crate serde; // extern crate serde_json; // extern crate rustc_serialize; // extern crate num_traits; #[macro_use] // mod macros; use test::Bencher; // #[derive(Debug, PartialEq, RustcEncodable, RustcDecodable, Serialize, Deserialize)] // struct Http { // protocol: HttpProtocol, // status: u32, // host_status: u32, // up_status: u32, // method: HttpMethod, // content_type: String, // user_agent: String, // referer: String, // request_uri: String, // } // c_enum!(HttpProtocol { // HTTP_PROTOCOL_UNKNOWN, // HTTP10, // HTTP11, // }); // c_enum!(HttpMethod { // METHOD_UNKNOWN, // GET, // POST, // DELETE, // PUT, // HEAD, // PURGE, // OPTIONS, // PROPFIND, // MKCOL, // PATCH, // }); // c_enum!(CacheStatus { // CACHESTATUS_UNKNOWN, // Miss, // Expired, // Hit, // }); // #[derive(Debug, PartialEq, RustcEncodable, RustcDecodable, Serialize, Deserialize)] // struct Origin { // ip: String, // port: u32, // hostname: String, // protocol: OriginProtocol, // } // c_enum!(OriginProtocol { // ORIGIN_PROTOCOL_UNKNOWN, // HTTP, // HTTPS, // }); // c_enum!(ZonePlan { // ZONEPLAN_UNKNOWN, // FREE, // PRO, // BIZ, // ENT, // }); // c_enum!(Country { // UNKNOWN, // A1, A2, O1, AD, AE, AF, AG, AI, AL, AM, AO, AP, AQ, AR, AS, AT, AU, AW, AX, // AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, // BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, // CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, EU, FI, FJ, // FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, // GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, // IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, // LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML, MM, MN, // MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, // NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, // PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, // SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, // TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, // WF, WS, XX, YE, YT, ZA, ZM, ZW, // }); // #[derive(Debug, PartialEq, RustcEncodable, RustcDecodable, Serialize, Deserialize)] // struct Log { // timestamp: i64, // zone_id: u32, // zone_plan: ZonePlan, // http: Http, // origin: Origin, // country: Country, // cache_status: CacheStatus, // server_ip: String, // server_name: String, // remote_ip: String, // bytes_dlv: u64, // ray_id: String, // } const JSON_STR: &'static str = r#"{"timestamp":2837513946597,"zone_id":123456,"zone_plan":1,"http":{"protocol":2,"status":200,"host_status":503,"up_status":520,"method":1,"content_type":"text/html","user_agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36","referer":"https://www.cloudflare.com/","request_uri":"/cdn-cgi/trace"},"origin":{"ip":"1.2.3.4","port":8000,"hostname":"www.example.com","protocol":2},"country":238,"cache_status":3,"server_ip":"192.168.1.1","server_name":"metal.cloudflare.com","remote_ip":"10.1.2.3","bytes_dlv":123456,"ray_id":"10c73629cce30078-LAX"}"#; const JSON_FLOAT_STR: &'static str = r#"[[-65.613616999999977,43.420273000000009],[-65.619720000000029,43.418052999999986],[-65.625,43.421379000000059],[-65.636123999999882,43.449714999999969],[-65.633056999999951,43.474709000000132],[-65.611389000000031,43.513054000000068],[-65.605835000000013,43.516105999999979],[-65.598343,43.515830999999935],[-65.566101000000003,43.508331000000055],[-65.561935000000005,43.504439999999988],[-65.55999799999995,43.499718000000087],[-65.573333999999988,43.476379000000065],[-65.593612999999948,43.444153000000028],[-65.613616999999977,43.420273000000009],[-59.816947999999911,43.928328999999962],[-59.841667000000029,43.918602000000021],[-59.866393999999957,43.909987999999998],[-59.879722999999956,43.906654000000003],[-59.895835999999974,43.904160000000047]]"#; // #[bench] // fn rustc_serialize_parse(b: &mut Bencher) { // b.bytes = JSON_STR.len() as u64; // b.iter(|| { // rustc_serialize::json::Json::from_str(JSON_STR).unwrap() // }); // } // #[bench] // fn rustc_serialize_stringify(b: &mut Bencher) { // let data = rustc_serialize::json::Json::from_str(JSON_STR).unwrap(); // b.bytes = rustc_serialize::json::encode(&data).unwrap().len() as u64; // b.iter(|| { // rustc_serialize::json::encode(&data).unwrap(); // }) // } // #[bench] // fn rustc_serialize_struct_parse(b: &mut Bencher) { // use rustc_serialize::json::Json; // b.bytes = JSON_STR.len() as u64; // b.iter(|| { // let json = Json::from_str(JSON_STR).unwrap(); // let mut decoder = rustc_serialize::json::Decoder::new(json); // let log: Log = rustc_serialize::Decodable::decode(&mut decoder).unwrap(); // log // }); // } // #[bench] // fn rustc_serialize_struct_stringify(b: &mut Bencher) { // use rustc_serialize::json::Json; // b.bytes = JSON_STR.len() as u64; // let json = Json::from_str(JSON_STR).unwrap(); // let mut decoder = rustc_serialize::json::Decoder::new(json); // let log: Log = rustc_serialize::Decodable::decode(&mut decoder).unwrap(); // b.iter(|| { // rustc_serialize::json::encode(&log).unwrap(); // }) // } // #[bench] // fn serde_json_parse(b: &mut Bencher) { // b.bytes = JSON_STR.len() as u64; // b.iter(|| { // serde_json::from_str::(JSON_STR).unwrap(); // }); // } // #[bench] // fn serde_json_stringify(b: &mut Bencher) { // let data = serde_json::from_str::(JSON_STR).unwrap(); // b.bytes = serde_json::to_string(&data).unwrap().len() as u64; // b.iter(|| { // serde_json::to_string(&data).unwrap(); // }) // } // #[bench] // fn serde_json_floats_parse(b: &mut Bencher) { // b.bytes = JSON_FLOAT_STR.len() as u64; // b.iter(|| { // serde_json::from_str::(JSON_FLOAT_STR).unwrap(); // }); // } // #[bench] // fn serde_json_floats_stringify(b: &mut Bencher) { // let data = serde_json::from_str::(JSON_FLOAT_STR).unwrap(); // b.bytes = serde_json::to_string(&data).unwrap().len() as u64; // b.iter(|| { // serde_json::to_string(&data).unwrap(); // }) // } // #[bench] // fn serde_json_struct_parse(b: &mut Bencher) { // b.bytes = JSON_STR.len() as u64; // b.iter(|| { // serde_json::from_str::(JSON_STR).unwrap(); // }); // } // #[bench] // fn serde_json_struct_stringify(b: &mut Bencher) { // b.bytes = JSON_STR.len() as u64; // let data = serde_json::from_str::(JSON_STR).unwrap(); // b.iter(|| { // serde_json::to_string(&data).unwrap(); // }); // } #[bench] fn json_rust_parse(b: &mut Bencher) { b.bytes = JSON_STR.len() as u64; b.iter(|| { json::parse(JSON_STR).unwrap(); }); } #[bench] fn json_rust_parse_floats(b: &mut Bencher) { b.bytes = JSON_FLOAT_STR.len() as u64; b.iter(|| { json::parse(JSON_FLOAT_STR).unwrap(); }); } #[bench] fn json_rust_stringify(b: &mut Bencher) { let data = json::parse(JSON_STR).unwrap(); b.bytes = data.dump().len() as u64; b.iter(|| { data.dump(); }) } #[bench] fn json_rust_stringify_io_write(b: &mut Bencher) { let data = json::parse(JSON_STR).unwrap(); b.bytes = data.dump().len() as u64; let mut target = Vec::new(); b.iter(|| { data.to_writer(&mut target); }) } #[bench] fn json_rust_stringify_floats(b: &mut Bencher) { let data = json::parse(JSON_FLOAT_STR).unwrap(); b.bytes = data.dump().len() as u64; b.iter(|| { data.dump(); }) } #[bench] fn json_rust_stringify_floats_io_write(b: &mut Bencher) { let data = json::parse(JSON_FLOAT_STR).unwrap(); b.bytes = data.dump().len() as u64; let mut target = Vec::new(); b.iter(|| { data.to_writer(&mut target); }) } json-0.12.0/src/codegen.rs010064400017500001750000000241231353446224000135320ustar0000000000000000use std::ptr; use std::io::Write; use std::io; use crate::JsonValue; use crate::number::Number; use crate::object::Object; use crate::util::print_dec; const QU: u8 = b'"'; const BS: u8 = b'\\'; const BB: u8 = b'b'; const TT: u8 = b't'; const NN: u8 = b'n'; const FF: u8 = b'f'; const RR: u8 = b'r'; const UU: u8 = b'u'; const __: u8 = 0; // Look up table for characters that need escaping in a product string static ESCAPED: [u8; 256] = [ // 0 1 2 3 4 5 6 7 8 9 A B C D E F UU, UU, UU, UU, UU, UU, UU, UU, BB, TT, NN, UU, FF, RR, UU, UU, // 0 UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, // 1 __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4 __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F ]; pub trait Generator { type T: Write; fn get_writer(&mut self) -> &mut Self::T; #[inline(always)] fn write(&mut self, slice: &[u8]) -> io::Result<()> { self.get_writer().write_all(slice) } #[inline(always)] fn write_char(&mut self, ch: u8) -> io::Result<()> { self.get_writer().write_all(&[ch]) } fn write_min(&mut self, slice: &[u8], min: u8) -> io::Result<()>; #[inline(always)] fn new_line(&mut self) -> io::Result<()> { Ok(()) } #[inline(always)] fn indent(&mut self) {} #[inline(always)] fn dedent(&mut self) {} #[inline(never)] fn write_string_complex(&mut self, string: &str, mut start: usize) -> io::Result<()> { self.write(string[ .. start].as_bytes())?; for (index, ch) in string.bytes().enumerate().skip(start) { let escape = ESCAPED[ch as usize]; if escape > 0 { self.write(string[start .. index].as_bytes())?; self.write(&[b'\\', escape])?; start = index + 1; } if escape == b'u' { write!(self.get_writer(), "{:04x}", ch)?; } } self.write(string[start ..].as_bytes())?; self.write_char(b'"') } #[inline(always)] fn write_string(&mut self, string: &str) -> io::Result<()> { self.write_char(b'"')?; for (index, ch) in string.bytes().enumerate() { if ESCAPED[ch as usize] > 0 { return self.write_string_complex(string, index) } } self.write(string.as_bytes())?; self.write_char(b'"') } #[inline(always)] fn write_number(&mut self, num: &Number) -> io::Result<()> { if num.is_nan() { return self.write(b"null"); } let (positive, mantissa, exponent) = num.as_parts(); unsafe { print_dec::write( self.get_writer(), positive, mantissa, exponent ) } } #[inline(always)] fn write_object(&mut self, object: &Object) -> io::Result<()> { self.write_char(b'{')?; let mut iter = object.iter(); if let Some((key, value)) = iter.next() { self.indent(); self.new_line()?; self.write_string(key)?; self.write_min(b": ", b':')?; self.write_json(value)?; } else { self.write_char(b'}')?; return Ok(()); } for (key, value) in iter { self.write_char(b',')?; self.new_line()?; self.write_string(key)?; self.write_min(b": ", b':')?; self.write_json(value)?; } self.dedent(); self.new_line()?; self.write_char(b'}') } fn write_json(&mut self, json: &JsonValue) -> io::Result<()> { match *json { JsonValue::Null => self.write(b"null"), JsonValue::Short(ref short) => self.write_string(short.as_str()), JsonValue::String(ref string) => self.write_string(string), JsonValue::Number(ref number) => self.write_number(number), JsonValue::Boolean(true) => self.write(b"true"), JsonValue::Boolean(false) => self.write(b"false"), JsonValue::Array(ref array) => { self.write_char(b'[')?; let mut iter = array.iter(); if let Some(item) = iter.next() { self.indent(); self.new_line()?; self.write_json(item)?; } else { self.write_char(b']')?; return Ok(()); } for item in iter { self.write_char(b',')?; self.new_line()?; self.write_json(item)?; } self.dedent(); self.new_line()?; self.write_char(b']') }, JsonValue::Object(ref object) => { self.write_object(object) } } } } pub struct DumpGenerator { code: Vec, } impl DumpGenerator { pub fn new() -> Self { DumpGenerator { code: Vec::with_capacity(1024), } } pub fn consume(self) -> String { // Original strings were unicode, numbers are all ASCII, // therefore this is safe. unsafe { String::from_utf8_unchecked(self.code) } } } impl Generator for DumpGenerator { type T = Vec; fn write(&mut self, slice: &[u8]) -> io::Result<()> { extend_from_slice(&mut self.code, slice); Ok(()) } #[inline(always)] fn write_char(&mut self, ch: u8) -> io::Result<()> { self.code.push(ch); Ok(()) } #[inline(always)] fn get_writer(&mut self) -> &mut Vec { &mut self.code } #[inline(always)] fn write_min(&mut self, _: &[u8], min: u8) -> io::Result<()> { self.code.push(min); Ok(()) } } pub struct PrettyGenerator { code: Vec, dent: u16, spaces_per_indent: u16, } impl PrettyGenerator { pub fn new(spaces: u16) -> Self { PrettyGenerator { code: Vec::with_capacity(1024), dent: 0, spaces_per_indent: spaces } } pub fn consume(self) -> String { unsafe { String::from_utf8_unchecked(self.code) } } } impl Generator for PrettyGenerator { type T = Vec; #[inline(always)] fn write(&mut self, slice: &[u8]) -> io::Result<()> { extend_from_slice(&mut self.code, slice); Ok(()) } #[inline(always)] fn write_char(&mut self, ch: u8) -> io::Result<()> { self.code.push(ch); Ok(()) } #[inline(always)] fn get_writer(&mut self) -> &mut Vec { &mut self.code } #[inline(always)] fn write_min(&mut self, slice: &[u8], _: u8) -> io::Result<()> { extend_from_slice(&mut self.code, slice); Ok(()) } fn new_line(&mut self) -> io::Result<()> { self.code.push(b'\n'); for _ in 0..(self.dent * self.spaces_per_indent) { self.code.push(b' '); } Ok(()) } fn indent(&mut self) { self.dent += 1; } fn dedent(&mut self) { self.dent -= 1; } } pub struct WriterGenerator<'a, W: 'a + Write> { writer: &'a mut W } impl<'a, W> WriterGenerator<'a, W> where W: 'a + Write { pub fn new(writer: &'a mut W) -> Self { WriterGenerator { writer: writer } } } impl<'a, W> Generator for WriterGenerator<'a, W> where W: Write { type T = W; #[inline(always)] fn get_writer(&mut self) -> &mut W { &mut self.writer } #[inline(always)] fn write_min(&mut self, _: &[u8], min: u8) -> io::Result<()> { self.writer.write_all(&[min]) } } pub struct PrettyWriterGenerator<'a, W: 'a + Write> { writer: &'a mut W, dent: u16, spaces_per_indent: u16, } impl<'a, W> PrettyWriterGenerator<'a, W> where W: 'a + Write { pub fn new(writer: &'a mut W, spaces: u16) -> Self { PrettyWriterGenerator { writer: writer, dent: 0, spaces_per_indent: spaces, } } } impl<'a, W> Generator for PrettyWriterGenerator<'a, W> where W: Write { type T = W; #[inline(always)] fn get_writer(&mut self) -> &mut W { &mut self.writer } #[inline(always)] fn write_min(&mut self, slice: &[u8], _: u8) -> io::Result<()> { self.writer.write_all(slice) } fn new_line(&mut self) -> io::Result<()> { self.write_char(b'\n')?; for _ in 0..(self.dent * self.spaces_per_indent) { self.write_char(b' ')?; } Ok(()) } fn indent(&mut self) { self.dent += 1; } fn dedent(&mut self) { self.dent -= 1; } } // From: https://github.com/dtolnay/fastwrite/blob/master/src/lib.rs#L68 // // LLVM is not able to lower `Vec::extend_from_slice` into a memcpy, so this // helps eke out that last bit of performance. #[inline] fn extend_from_slice(dst: &mut Vec, src: &[u8]) { let dst_len = dst.len(); let src_len = src.len(); dst.reserve(src_len); unsafe { // We would have failed if `reserve` overflowed dst.set_len(dst_len + src_len); ptr::copy_nonoverlapping( src.as_ptr(), dst.as_mut_ptr().offset(dst_len as isize), src_len); } } json-0.12.0/src/error.rs010064400017500001750000000031561347550352200132650ustar0000000000000000use std::{ char, error, fmt }; /// Error type of this crate. /// /// /// *Note:* Since `0.9.0` using `JsonError` is deprecated. Always use /// `json::Error` instead! #[derive(Debug, PartialEq, Eq)] pub enum Error { UnexpectedCharacter { ch: char, line: usize, column: usize, }, UnexpectedEndOfJson, ExceededDepthLimit, FailedUtf8Parsing, WrongType(String), } impl Error { pub fn wrong_type(expected: &str) -> Self { Error::WrongType(expected.into()) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; match *self { UnexpectedCharacter { ref ch, ref line, ref column, } => write!(f, "Unexpected character: {} at ({}:{})", ch, line, column), UnexpectedEndOfJson => write!(f, "Unexpected end of JSON"), ExceededDepthLimit => write!(f, "Exceeded depth limit"), FailedUtf8Parsing => write!(f, "Failed to parse UTF-8 bytes"), WrongType(ref s) => write!(f, "Wrong type, expected: {}", s), } } } impl error::Error for Error { fn description(&self) -> &str { use Error::*; match *self { UnexpectedCharacter { .. } => "Unexpected character", UnexpectedEndOfJson => "Unexpected end of JSON", ExceededDepthLimit => "Exceeded depth limit", FailedUtf8Parsing => "Failed to read bytes as UTF-8 from JSON", WrongType(_) => "Wrong type", } } } json-0.12.0/src/lib.rs010064400017500001750000000202651353450047500127020ustar0000000000000000//! ![](http://terhix.com/doc/json-rust-logo-small.png) //! //! # json-rust //! //! Parse and serialize [JSON](http://json.org/) with ease. //! //! **[Changelog](https://github.com/maciejhirsz/json-rust/releases) -** //! **[Complete Documentation](http://terhix.com/doc/json/) -** //! **[Cargo](https://crates.io/crates/json) -** //! **[Repository](https://github.com/maciejhirsz/json-rust)** //! //! ## Why? //! //! JSON is a very loose format where anything goes - arrays can hold mixed //! types, object keys can change types between API calls or not include //! some keys under some conditions. Mapping that to idiomatic Rust structs //! introduces friction. //! //! This crate intends to avoid that friction. //! //! ```rust //! # #[macro_use] extern crate json; //! # fn main() { //! let parsed = json::parse(r#" //! //! { //! "code": 200, //! "success": true, //! "payload": { //! "features": [ //! "awesome", //! "easyAPI", //! "lowLearningCurve" //! ] //! } //! } //! //! "#).unwrap(); //! //! let instantiated = object!{ //! "code" => 200, //! "success" => true, //! "payload" => object!{ //! "features" => array![ //! "awesome", //! "easyAPI", //! "lowLearningCurve" //! ] //! } //! }; //! //! assert_eq!(parsed, instantiated); //! # } //! ``` //! //! ## First class citizen //! //! Using macros and indexing, it's easy to work with the data. //! //! ```rust //! # #[macro_use] extern crate json; //! # fn main() { //! let mut data = object!{ //! "foo" => false, //! "bar" => json::Null, //! "answer" => 42, //! "list" => array![json::Null, "world", true] //! }; //! //! // Partial equality is implemented for most raw types: //! assert!(data["foo"] == false); //! //! // And it's type aware, `null` and `false` are different values: //! assert!(data["bar"] != false); //! //! // But you can use any Rust number types: //! assert!(data["answer"] == 42); //! assert!(data["answer"] == 42.0); //! assert!(data["answer"] == 42isize); //! //! // Access nested structures, arrays and objects: //! assert!(data["list"][0].is_null()); //! assert!(data["list"][1] == "world"); //! assert!(data["list"][2] == true); //! //! // Error resilient - accessing properties that don't exist yield null: //! assert!(data["this"]["does"]["not"]["exist"].is_null()); //! //! // Mutate by assigning: //! data["list"][0] = "Hello".into(); //! //! // Use the `dump` method to serialize the data: //! assert_eq!(data.dump(), r#"{"foo":false,"bar":null,"answer":42,"list":["Hello","world",true]}"#); //! //! // Or pretty print it out: //! println!("{:#}", data); //! # } //! ``` //! //! ## Serialize with `json::stringify(value)` //! //! Primitives: //! //! ``` //! // str slices //! assert_eq!(json::stringify("foobar"), "\"foobar\""); //! //! // Owned strings //! assert_eq!(json::stringify("foobar".to_string()), "\"foobar\""); //! //! // Any number types //! assert_eq!(json::stringify(42), "42"); //! //! // Booleans //! assert_eq!(json::stringify(true), "true"); //! assert_eq!(json::stringify(false), "false"); //! ``` //! //! Explicit `null` type `json::Null`: //! //! ``` //! assert_eq!(json::stringify(json::Null), "null"); //! ``` //! //! Optional types: //! //! ``` //! let value: Option = Some("foo".to_string()); //! assert_eq!(json::stringify(value), "\"foo\""); //! //! let no_value: Option = None; //! assert_eq!(json::stringify(no_value), "null"); //! ``` //! //! Vector: //! //! ``` //! let data = vec![1,2,3]; //! assert_eq!(json::stringify(data), "[1,2,3]"); //! ``` //! //! Vector with optional values: //! //! ``` //! let data = vec![Some(1), None, Some(2), None, Some(3)]; //! assert_eq!(json::stringify(data), "[1,null,2,null,3]"); //! ``` //! //! Pushing to arrays: //! //! ``` //! let mut data = json::JsonValue::new_array(); //! //! data.push(10); //! data.push("foo"); //! data.push(false); //! //! assert_eq!(data.dump(), r#"[10,"foo",false]"#); //! ``` //! //! Putting fields on objects: //! //! ``` //! let mut data = json::JsonValue::new_object(); //! //! data["answer"] = 42.into(); //! data["foo"] = "bar".into(); //! //! assert_eq!(data.dump(), r#"{"answer":42,"foo":"bar"}"#); //! ``` //! //! `array!` macro: //! //! ``` //! # #[macro_use] extern crate json; //! # fn main() { //! let data = array!["foo", "bar", 100, true, json::Null]; //! assert_eq!(data.dump(), r#"["foo","bar",100,true,null]"#); //! # } //! ``` //! //! `object!` macro: //! //! ``` //! # #[macro_use] extern crate json; //! # fn main() { //! let data = object!{ //! "name" => "John Doe", //! "age" => 30, //! "canJSON" => true //! }; //! assert_eq!( //! data.dump(), //! r#"{"name":"John Doe","age":30,"canJSON":true}"# //! ); //! # } //! ``` use std::result; mod codegen; mod parser; mod value; mod error; mod util; pub mod short; pub mod object; pub mod number; pub use error::Error; pub use value::JsonValue; pub use value::JsonValue::Null; /// Result type used by this crate. /// /// /// *Note:* Since 0.9.0 the old `JsonResult` type is deprecated. Always use /// `json::Result` instead. pub type Result = result::Result; pub mod iterators { /// Iterator over members of `JsonValue::Array`. pub type Members<'a> = ::std::slice::Iter<'a, super::JsonValue>; /// Mutable iterator over members of `JsonValue::Array`. pub type MembersMut<'a> = ::std::slice::IterMut<'a, super::JsonValue>; /// Iterator over key value pairs of `JsonValue::Object`. pub type Entries<'a> = super::object::Iter<'a>; /// Mutable iterator over key value pairs of `JsonValue::Object`. pub type EntriesMut<'a> = super::object::IterMut<'a>; } #[deprecated(since="0.9.0", note="use `json::Error` instead")] pub use Error as JsonError; #[deprecated(since="0.9.0", note="use `json::Result` instead")] pub use crate::Result as JsonResult; pub use parser::parse; pub type Array = Vec; /// Convenience for `JsonValue::from(value)` pub fn from(value: T) -> JsonValue where T: Into { value.into() } /// Pretty prints out the value as JSON string. pub fn stringify(root: T) -> String where T: Into { let root: JsonValue = root.into(); root.dump() } /// Pretty prints out the value as JSON string. Second argument is a /// number of spaces to indent new blocks with. pub fn stringify_pretty(root: T, spaces: u16) -> String where T: Into { let root: JsonValue = root.into(); root.pretty(spaces) } /// Helper macro for creating instances of `JsonValue::Array`. /// /// ``` /// # #[macro_use] extern crate json; /// # fn main() { /// let data = array!["foo", 42, false]; /// /// assert_eq!(data[0], "foo"); /// assert_eq!(data[1], 42); /// assert_eq!(data[2], false); /// /// assert_eq!(data.dump(), r#"["foo",42,false]"#); /// # } /// ``` #[macro_export] macro_rules! array { [] => ($crate::JsonValue::new_array()); [ $( $item:expr ),* ] => ({ let size = 0 $( + {let _ = $item; 1} )*; let mut array = Vec::with_capacity(size); $( array.push($item.into()); )* $crate::JsonValue::Array(array) }) } /// Helper macro for creating instances of `JsonValue::Object`. /// /// ``` /// # #[macro_use] extern crate json; /// # fn main() { /// let data = object!{ /// "foo" => 42, /// "bar" => false /// }; /// /// assert_eq!(data["foo"], 42); /// assert_eq!(data["bar"], false); /// /// assert_eq!(data.dump(), r#"{"foo":42,"bar":false}"#); /// # } /// ``` #[macro_export] macro_rules! object { // Empty object. {} => ($crate::JsonValue::new_object()); // Non-empty object, no trailing comma. // // In this implementation, key/value pairs separated by commas. { $( $key:expr => $value:expr ),* } => { $crate::object!( $( $key => $value, )* ) }; // Non-empty object, trailing comma. // // In this implementation, the comma is part of the value. { $( $key:expr => $value:expr, )* } => ({ use $crate::object::Object; let size = 0 $( + {let _ = $key; 1} )*; let mut object = Object::with_capacity(size); $( object.insert($key, $value.into()); )* $crate::JsonValue::Object(object) }) } json-0.12.0/src/number.rs010064400017500001750000000352171353446153400134310ustar0000000000000000use std::{ ops, fmt, f32, f64 }; use std::num::FpCategory; use crate::util::grisu2; use crate::util::print_dec; /// NaN value represented in `Number` type. NaN is equal to itself. pub const NAN: Number = Number { category: NAN_MASK, mantissa: 0, exponent: 0 }; const NEGATIVE: u8 = 0; const POSITIVE: u8 = 1; const NAN_MASK: u8 = !1; /// Number representation used inside `JsonValue`. You can easily convert /// the `Number` type into native Rust number types and back, or use the /// equality operator with another number type. /// /// ``` /// # use json::number::Number; /// let foo: Number = 3.14.into(); /// let bar: f64 = foo.into(); /// /// assert_eq!(foo, 3.14); /// assert_eq!(bar, 3.14); /// ``` /// /// More often than not you will deal with `JsonValue::Number` variant that /// wraps around this type, instead of using the methods here directly. #[derive(Copy, Clone, Debug)] pub struct Number { // A byte describing the sign and NaN-ness of the number. // // category == 0 (NEGATIVE constant) -> negative sign // category == 1 (POSITIVE constant) -> positive sign // category > 1 (matches NAN_MASK constant) -> NaN category: u8, // Decimal exponent, analog to `e` notation in string form. exponent: i16, // Integer base before sing and exponent applied. mantissa: u64, } impl Number { /// Construct a new `Number` from parts. This can't create a NaN value. /// /// ``` /// # use json::number::Number; /// let pi = unsafe { Number::from_parts_unchecked(true, 3141592653589793, -15) }; /// /// assert_eq!(pi, 3.141592653589793); /// ``` /// /// While this method is marked unsafe, it doesn't actually perform any unsafe operations. /// THe goal of the 'unsafe' is to deter from using this method in favor of its safe equivalent /// `from_parts`, at least in context when the associated performance cost is negligible. #[inline] pub unsafe fn from_parts_unchecked(positive: bool, mantissa: u64, exponent: i16) -> Self { Number { category: positive as u8, exponent: exponent, mantissa: mantissa, } } /// Construct a new `Number` from parts, stripping unnecessary trailing zeroes. /// This can't create a NaN value. /// /// ``` /// # use json::number::Number; /// let one = Number::from_parts(true, 1000, -3); /// let (positive, mantissa, exponent) = one.as_parts(); /// /// assert_eq!(true, positive); /// assert_eq!(1, mantissa); /// assert_eq!(0, exponent); /// ``` #[inline] pub fn from_parts(positive: bool, mut mantissa: u64, mut exponent: i16) -> Self { while exponent < 0 && mantissa % 10 == 0 { exponent += 1; mantissa /= 10; } unsafe { Number::from_parts_unchecked(positive, mantissa, exponent) } } /// Reverse to `from_parts` - obtain parts from an existing `Number`. /// /// ``` /// # use json::number::Number; /// let pi = Number::from(3.141592653589793); /// let (positive, mantissa, exponent) = pi.as_parts(); /// /// assert_eq!(positive, true); /// assert_eq!(mantissa, 3141592653589793); /// assert_eq!(exponent, -15); /// ``` #[inline] pub fn as_parts(&self) -> (bool, u64, i16) { (self.category == POSITIVE, self.mantissa, self.exponent) } #[inline] pub fn is_sign_positive(&self) -> bool { self.category == POSITIVE } #[inline] pub fn is_zero(&self) -> bool { self.mantissa == 0 && !self.is_nan() } #[inline] pub fn is_nan(&self) -> bool { self.category & NAN_MASK != 0 } /// Test if the number is NaN or has a zero value. #[inline] pub fn is_empty(&self) -> bool { self.mantissa == 0 || self.is_nan() } /// Obtain an integer at a fixed decimal point. This is useful for /// converting monetary values and doing arithmetic on them without /// rounding errors introduced by floating point operations. /// /// Will return `None` if `Number` is negative or a NaN. /// /// ``` /// # use json::number::Number; /// let price_a = Number::from(5.99); /// let price_b = Number::from(7); /// let price_c = Number::from(10.2); /// /// assert_eq!(price_a.as_fixed_point_u64(2), Some(599)); /// assert_eq!(price_b.as_fixed_point_u64(2), Some(700)); /// assert_eq!(price_c.as_fixed_point_u64(2), Some(1020)); /// ``` pub fn as_fixed_point_u64(&self, point: u16) -> Option { if self.category != POSITIVE { return None; } let e_diff = point as i16 + self.exponent; Some(if e_diff == 0 { self.mantissa } else if e_diff < 0 { self.mantissa.wrapping_div(decimal_power(-e_diff as u16)) } else { self.mantissa.wrapping_mul(decimal_power(e_diff as u16)) }) } /// Analog to `as_fixed_point_u64`, except returning a signed /// `i64`, properly handling negative numbers. /// /// ``` /// # use json::number::Number; /// let balance_a = Number::from(-1.49); /// let balance_b = Number::from(42); /// /// assert_eq!(balance_a.as_fixed_point_i64(2), Some(-149)); /// assert_eq!(balance_b.as_fixed_point_i64(2), Some(4200)); /// ``` pub fn as_fixed_point_i64(&self, point: u16) -> Option { if self.is_nan() { return None; } let num = if self.is_sign_positive() { self.mantissa as i64 } else { -(self.mantissa as i64) }; let e_diff = point as i16 + self.exponent; Some(if e_diff == 0 { num } else if e_diff < 0 { num.wrapping_div(decimal_power(-e_diff as u16) as i64) } else { num.wrapping_mul(decimal_power(e_diff as u16) as i64) }) } } impl PartialEq for Number { #[inline] fn eq(&self, other: &Number) -> bool { if self.is_zero() && other.is_zero() || self.is_nan() && other.is_nan() { return true; } if self.category != other.category { return false; } let e_diff = self.exponent - other.exponent; if e_diff == 0 { return self.mantissa == other.mantissa; } else if e_diff > 0 { let power = decimal_power(e_diff as u16); self.mantissa.wrapping_mul(power) == other.mantissa } else { let power = decimal_power(-e_diff as u16); self.mantissa == other.mantissa.wrapping_mul(power) } } } impl fmt::Display for Number { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { unsafe { if self.is_nan() { return f.write_str("nan") } let (positive, mantissa, exponent) = self.as_parts(); let mut buf = Vec::new(); print_dec::write(&mut buf, positive, mantissa, exponent).unwrap(); f.write_str(&String::from_utf8_unchecked(buf)) } } } fn exponentiate_f64(n: f64, e: i16) -> f64 { static CACHE_POWERS: [f64; 23] = [ 1.0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 ]; if e >= 0 { let index = e as usize; n * if index < 23 { CACHE_POWERS[index] } else { 10f64.powf(index as f64) } } else { let index = -e as usize; n / if index < 23 { CACHE_POWERS[index] } else { 10f64.powf(index as f64) } } } fn exponentiate_f32(n: f32, e: i16) -> f32 { static CACHE_POWERS: [f32; 23] = [ 1.0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 ]; if e >= 0 { let index = e as usize; n * if index < 23 { CACHE_POWERS[index] } else { 10f32.powf(index as f32) } } else { let index = -e as usize; n / if index < 23 { CACHE_POWERS[index] } else { 10f32.powf(index as f32) } } } impl From for f64 { fn from(num: Number) -> f64 { if num.is_nan() { return f64::NAN; } let mut n = num.mantissa as f64; let mut e = num.exponent; if e < -308 { n = exponentiate_f64(n, e + 308); e = -308; } let f = exponentiate_f64(n, e); if num.is_sign_positive() { f } else { -f } } } impl From for f32 { fn from(num: Number) -> f32 { if num.is_nan() { return f32::NAN; } let mut n = num.mantissa as f32; let mut e = num.exponent; if e < -127 { n = exponentiate_f32(n, e + 127); e = -127; } let f = exponentiate_f32(n, e); if num.is_sign_positive() { f } else { -f } } } impl From for Number { fn from(float: f64) -> Number { match float.classify() { FpCategory::Infinite | FpCategory::Nan => return NAN, _ => {} } if !float.is_sign_positive() { let (mantissa, exponent) = grisu2::convert(-float); Number::from_parts(false, mantissa, exponent) } else { let (mantissa, exponent) = grisu2::convert(float); Number::from_parts(true, mantissa, exponent) } } } impl From for Number { fn from(float: f32) -> Number { match float.classify() { FpCategory::Infinite | FpCategory::Nan => return NAN, _ => {} } if !float.is_sign_positive() { let (mantissa, exponent) = grisu2::convert(-float as f64); Number::from_parts(false, mantissa, exponent) } else { let (mantissa, exponent) = grisu2::convert(float as f64); Number::from_parts(true, mantissa, exponent) } } } impl PartialEq for Number { fn eq(&self, other: &f64) -> bool { f64::from(*self) == *other } } impl PartialEq for Number { fn eq(&self, other: &f32) -> bool { f32::from(*self) == *other } } impl PartialEq for f64 { fn eq(&self, other: &Number) -> bool { f64::from(*other) == *self } } impl PartialEq for f32 { fn eq(&self, other: &Number) -> bool { f32::from(*other) == *self } } macro_rules! impl_unsigned { ($( $t:ty ),*) => ($( impl From<$t> for Number { #[inline] fn from(num: $t) -> Number { Number { category: POSITIVE, exponent: 0, mantissa: num as u64, } } } impl_integer!($t); )*) } macro_rules! impl_signed { ($( $t:ty ),*) => ($( impl From<$t> for Number { fn from(num: $t) -> Number { if num < 0 { Number { category: NEGATIVE, exponent: 0, mantissa: -num as u64, } } else { Number { category: POSITIVE, exponent: 0, mantissa: num as u64, } } } } impl_integer!($t); )*) } macro_rules! impl_integer { ($t:ty) => { impl From for $t { fn from(num: Number) -> $t { let (positive, mantissa, exponent) = num.as_parts(); if exponent <= 0 { if positive { mantissa as $t } else { -(mantissa as i64) as $t } } else { // This may overflow, which is fine if positive { (mantissa * 10u64.pow(exponent as u32)) as $t } else { (-(mantissa as i64) * 10i64.pow(exponent as u32)) as $t } } } } impl PartialEq<$t> for Number { fn eq(&self, other: &$t) -> bool { *self == Number::from(*other) } } impl PartialEq for $t { fn eq(&self, other: &Number) -> bool { Number::from(*self) == *other } } } } impl_signed!(isize, i8, i16, i32, i64); impl_unsigned!(usize, u8, u16, u32, u64); impl ops::Neg for Number { type Output = Number; #[inline] fn neg(self) -> Number { Number { category: self.category ^ POSITIVE, exponent: self.exponent, mantissa: self.mantissa, } } } // Commented out for now - not doing math ops for 0.10.0 // ----------------------------------------------------- // // impl ops::Mul for Number { // type Output = Number; // #[inline] // fn mul(self, other: Number) -> Number { // // If either is a NaN, return a NaN // if (self.category | other.category) & NAN_MASK != 0 { // NAN // } else { // Number { // // If both signs are the same, xoring will produce 0. // // If they are different, xoring will produce 1. // // Xor again with 1 to get a proper proper sign! // // Xor all the things! ^ _ ^ // category: self.category ^ other.category ^ POSITIVE, // exponent: self.exponent + other.exponent, // mantissa: self.mantissa * other.mantissa, // } // } // } // } // impl ops::MulAssign for Number { // #[inline] // fn mul_assign(&mut self, other: Number) { // *self = *self * other; // } // } #[inline] fn decimal_power(mut e: u16) -> u64 { static CACHED: [u64; 20] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000, ]; if e < 20 { CACHED[e as usize] } else { let mut pow = 1u64; while e >= 20 { pow = pow.saturating_mul(CACHED[(e % 20) as usize]); e /= 20; } pow } } json-0.12.0/src/object.rs010064400017500001750000000507421353447772300134160ustar0000000000000000use std::{ ptr, mem, str, slice, fmt }; use std::ops::{ Index, IndexMut, Deref }; use std::iter::FromIterator; use crate::codegen::{ DumpGenerator, Generator, PrettyGenerator }; use crate::value::JsonValue; const KEY_BUF_LEN: usize = 32; static NULL: JsonValue = JsonValue::Null; // FNV-1a implementation // // While the `Object` is implemented as a binary tree, not a hash table, the // order in which the tree is balanced makes absolutely no difference as long // as there is a deterministic left / right ordering with good spread. // Comparing a hashed `u64` is faster than comparing `&str` or even `&[u8]`, // for larger objects this yields non-trivial performance benefits. // // Additionally this "randomizes" the keys a bit. Should the keys in an object // be inserted in alphabetical order (an example of such a use case would be // using an object as a store for entries by ids, where ids are sorted), this // will prevent the tree from being constructed in a way where the same branch // of each node is always used, effectively producing linear lookup times. Bad! // // Example: // // ``` // println!("{}", hash_key(b"10000056")); // println!("{}", hash_key(b"10000057")); // println!("{}", hash_key(b"10000058")); // println!("{}", hash_key(b"10000059")); // ``` // // Produces: // // ``` // 15043794053238616431 <-- 2nd // 15043792953726988220 <-- 1st // 15043800650308385697 <-- 4th // 15043799550796757486 <-- 3rd // ``` #[inline] fn hash_key(key: &[u8]) -> u64 { let mut hash: u64 = 0xcbf29ce484222325; for byte in key { hash ^= *byte as u64; hash = hash.wrapping_mul(0x100000001b3); } hash } struct Key { // Internal buffer to store keys that fit within `KEY_BUF_LEN`, // otherwise this field will contain garbage. pub buf: [u8; KEY_BUF_LEN], // Length of the key in bytes. pub len: usize, // Cached raw pointer to the key, so that we can cheaply construct // a `&str` slice from the `Node` without checking if the key is // allocated separately on the heap, or in the `key_buf`. pub ptr: *mut u8, // A hash of the key, explanation below. pub hash: u64, } impl Key { #[inline] fn new(hash: u64, len: usize) -> Self { Key { buf: [0; KEY_BUF_LEN], len: len, ptr: ptr::null_mut(), hash: hash } } #[inline] fn as_bytes(&self) -> &[u8] { unsafe { slice::from_raw_parts(self.ptr, self.len) } } #[inline] fn as_str(&self) -> &str { unsafe { str::from_utf8_unchecked(self.as_bytes()) } } // The `buf` on the `Key` can only be filled after the struct // is already on the `Vec`'s heap (along with the `Node`). // For that reason it's not set in `Key::new` but only after // the `Node` is created and allocated. #[inline] fn attach(&mut self, key: &[u8]) { if self.len <= KEY_BUF_LEN { unsafe { ptr::copy_nonoverlapping( key.as_ptr(), self.buf.as_mut_ptr(), self.len ); } self.ptr = self.buf.as_mut_ptr(); } else { let mut heap = key.to_vec(); self.ptr = heap.as_mut_ptr(); mem::forget(heap); } } // Since we store `Node`s on a vector, it will suffer from reallocation. // Whenever that happens, `key.ptr` for short keys will turn into dangling // pointers and will need to be re-cached. #[inline] fn fix_ptr(&mut self) { if self.len <= KEY_BUF_LEN { self.ptr = self.buf.as_mut_ptr(); } } } // Implement `Sync` and `Send` for `Key` despite the use of raw pointers. The struct // itself should be memory safe. unsafe impl Sync for Key {} unsafe impl Send for Key {} // Because long keys _can_ be stored separately from the `Key` on heap, // it's essential to clean up the heap allocation when the `Key` is dropped. impl Drop for Key { fn drop(&mut self) { unsafe { if self.len > KEY_BUF_LEN { // Construct a `Vec` out of the `key_ptr`. Since the key is // always allocated from a slice, the capacity is equal to length. let heap = Vec::from_raw_parts( self.ptr, self.len, self.len ); // Now that we have an owned `Vec`, drop it. drop(heap); } } } } // Just like with `Drop`, `Clone` needs a custom implementation that accounts // for the fact that key _can_ be separately heap allocated. impl Clone for Key { fn clone(&self) -> Self { if self.len > KEY_BUF_LEN { let mut heap = self.as_bytes().to_vec(); let ptr = heap.as_mut_ptr(); mem::forget(heap); Key { buf: [0; KEY_BUF_LEN], len: self.len, ptr: ptr, hash: self.hash, } } else { Key { buf: self.buf, len: self.len, ptr: ptr::null_mut(), // requires a `fix_ptr` call after `Node` is on the heap hash: self.hash, } } } } #[derive(Clone)] struct Node { // String-esque key abstraction pub key: Key, // Value stored. pub value: JsonValue, // Store vector index pointing to the `Node` for which `key_hash` is smaller // than that of this `Node`. // Will default to 0 as root node can't be referenced anywhere else. pub left: usize, // Same as above but for `Node`s with hash larger than this one. If the // hash is the same, but keys are different, the lookup will default // to the right branch as well. pub right: usize, } impl fmt::Debug for Node { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&(self.key.as_str(), &self.value, self.left, self.right), f) } } impl PartialEq for Node { fn eq(&self, other: &Node) -> bool { self.key.hash == other.key.hash && self.key.as_bytes() == other.key.as_bytes() && self.value == other.value } } impl Node { #[inline] fn new(value: JsonValue, hash: u64, len: usize) -> Node { Node { key: Key::new(hash, len), value: value, left: 0, right: 0, } } } /// A binary tree implementation of a string -> `JsonValue` map. You normally don't /// have to interact with instances of `Object`, much more likely you will be /// using the `JsonValue::Object` variant, which wraps around this struct. #[derive(Debug)] pub struct Object { store: Vec } impl Object { /// Create a new, empty instance of `Object`. Empty `Object` performs no /// allocation until a value is inserted into it. #[inline(always)] pub fn new() -> Self { Object { store: Vec::new() } } /// Create a new `Object` with memory preallocated for `capacity` number /// of entries. #[inline(always)] pub fn with_capacity(capacity: usize) -> Self { Object { store: Vec::with_capacity(capacity) } } #[inline] fn node_at_index_mut(&mut self, index: usize) -> *mut Node { unsafe { self.store.as_mut_ptr().offset(index as isize) } } #[inline(always)] fn add_node(&mut self, key: &[u8], value: JsonValue, hash: u64) -> usize { let index = self.store.len(); if index < self.store.capacity() { // Because we've just checked the capacity, we can avoid // using `push`, and instead do unsafe magic to memcpy // the new node at the correct index without additional // capacity or bound checks. unsafe { let node = Node::new(value, hash, key.len()); self.store.set_len(index + 1); // To whomever gets concerned: I got better results with // copy than write. Difference in benchmarks wasn't big though. ptr::copy_nonoverlapping( &node as *const Node, self.store.as_mut_ptr().offset(index as isize), 1, ); // Since the Node has been copied, we need to forget about // the owned value, else we may run into use after free. mem::forget(node); } unsafe { self.store.get_unchecked_mut(index).key.attach(key) }; } else { self.store.push(Node::new(value, hash, key.len())); unsafe { self.store.get_unchecked_mut(index).key.attach(key) }; // Index up to the index (old length), we don't need to fix // anything on the Node that just got pushed. for node in self.store.iter_mut().take(index) { node.key.fix_ptr(); } } index } /// Insert a new entry, or override an existing one. Note that `key` has /// to be a `&str` slice and not an owned `String`. The internals of /// `Object` will handle the heap allocation of the key if needed for /// better performance. #[inline] pub fn insert(&mut self, key: &str, value: JsonValue) { self.insert_index(key, value); } pub(crate) fn insert_index(&mut self, key: &str, value: JsonValue) -> usize { let key = key.as_bytes(); let hash = hash_key(key); if self.store.len() == 0 { self.store.push(Node::new(value, hash, key.len())); self.store[0].key.attach(key); return 0; } let mut node = unsafe { &mut *self.node_at_index_mut(0) }; let mut parent = 0; loop { if hash == node.key.hash && key == node.key.as_bytes() { node.value = value; return parent; } else if hash < node.key.hash { if node.left != 0 { parent = node.left; node = unsafe { &mut *self.node_at_index_mut(node.left) }; continue; } let index = self.add_node(key, value, hash); self.store[parent].left = index; return index; } else { if node.right != 0 { parent = node.right; node = unsafe { &mut *self.node_at_index_mut(node.right) }; continue; } let index = self.add_node(key, value, hash); self.store[parent].right = index; return index; } } } #[inline] pub(crate) fn override_at(&mut self, index: usize, value: JsonValue) { self.store[index].value = value; } #[inline] #[deprecated(since="0.11.11", note="Was only meant for internal use")] pub fn override_last(&mut self, value: JsonValue) { if let Some(node) = self.store.last_mut() { node.value = value; } } pub fn get(&self, key: &str) -> Option<&JsonValue> { if self.store.len() == 0 { return None; } let key = key.as_bytes(); let hash = hash_key(key); let mut node = unsafe { self.store.get_unchecked(0) }; loop { if hash == node.key.hash && key == node.key.as_bytes() { return Some(&node.value); } else if hash < node.key.hash { if node.left == 0 { return None; } node = unsafe { self.store.get_unchecked(node.left) }; } else { if node.right == 0 { return None; } node = unsafe { self.store.get_unchecked(node.right) }; } } } pub fn get_mut(&mut self, key: &str) -> Option<&mut JsonValue> { if self.store.len() == 0 { return None; } let key = key.as_bytes(); let hash = hash_key(key); let mut index = 0; { let mut node = unsafe { self.store.get_unchecked(0) }; loop { if hash == node.key.hash && key == node.key.as_bytes() { break; } else if hash < node.key.hash { if node.left == 0 { return None; } index = node.left; node = unsafe { self.store.get_unchecked(node.left) }; } else { if node.right == 0 { return None; } index = node.right; node = unsafe { self.store.get_unchecked(node.right) }; } } } let node = unsafe { self.store.get_unchecked_mut(index) }; Some(&mut node.value) } /// Attempts to remove the value behind `key`, if successful /// will return the `JsonValue` stored behind the `key`. pub fn remove(&mut self, key: &str) -> Option { if self.store.len() == 0 { return None; } let key = key.as_bytes(); let hash = hash_key(key); let mut index = 0; { let mut node = unsafe { self.store.get_unchecked(0) }; // Try to find the node loop { if hash == node.key.hash && key == node.key.as_bytes() { break; } else if hash < node.key.hash { if node.left == 0 { return None; } index = node.left; node = unsafe { self.store.get_unchecked(node.left) }; } else { if node.right == 0 { return None; } index = node.right; node = unsafe { self.store.get_unchecked(node.right) }; } } } // Removing a node would screw the tree badly, it's easier to just // recreate it. This is a very costly operation, but removing nodes // in JSON shouldn't happen very often if at all. Optimizing this // can wait for better times. let mut new_object = Object::with_capacity(self.store.len() - 1); let mut removed = None; for (i, node) in self.store.iter_mut().enumerate() { if i == index { // Rust doesn't like us moving things from `node`, even if // it is owned. Replace fixes that. removed = Some(mem::replace(&mut node.value, JsonValue::Null)); } else { let value = mem::replace(&mut node.value, JsonValue::Null); new_object.insert(node.key.as_str(), value); } } mem::swap(self, &mut new_object); removed } #[inline(always)] pub fn len(&self) -> usize { self.store.len() } #[inline(always)] pub fn is_empty(&self) -> bool { self.store.is_empty() } /// Wipe the `Object` clear. The capacity will remain untouched. pub fn clear(&mut self) { self.store.clear(); } #[inline(always)] pub fn iter(&self) -> Iter { Iter { inner: self.store.iter() } } #[inline(always)] pub fn iter_mut(&mut self) -> IterMut { IterMut { inner: self.store.iter_mut() } } /// Prints out the value as JSON string. pub fn dump(&self) -> String { let mut gen = DumpGenerator::new(); gen.write_object(self).expect("Can't fail"); gen.consume() } /// Pretty prints out the value as JSON string. Takes an argument that's /// number of spaces to indent new blocks with. pub fn pretty(&self, spaces: u16) -> String { let mut gen = PrettyGenerator::new(spaces); gen.write_object(self).expect("Can't fail"); gen.consume() } } // Custom implementation of `Clone`, as new heap allocation means // we have to fix key pointers everywhere! impl Clone for Object { fn clone(&self) -> Self { let mut store = self.store.clone(); for node in store.iter_mut() { node.key.fix_ptr(); } Object { store: store } } } impl, V: Into> FromIterator<(K, V)> for Object { fn from_iter>(iter: I) -> Self { let iter = iter.into_iter(); let mut object = Object::with_capacity(iter.size_hint().0); for (key, value) in iter { object.insert(key.as_ref(), value.into()); } object } } // Because keys can inserted in different order, the safe way to // compare `Object`s is to iterate over one and check if the other // has all the same keys. impl PartialEq for Object { fn eq(&self, other: &Object) -> bool { if self.len() != other.len() { return false; } for (key, value) in self.iter() { match other.get(key) { Some(ref other_val) => if *other_val != value { return false; }, None => return false } } true } } pub struct Iter<'a> { inner: slice::Iter<'a, Node> } impl<'a> Iter<'a> { /// Create an empty iterator that always returns `None` pub fn empty() -> Self { Iter { inner: [].iter() } } } impl<'a> Iterator for Iter<'a> { type Item = (&'a str, &'a JsonValue); #[inline(always)] fn next(&mut self) -> Option { self.inner.next().map(|node| (node.key.as_str(), &node.value)) } } impl<'a> DoubleEndedIterator for Iter<'a> { #[inline(always)] fn next_back(&mut self) -> Option { self.inner.next_back().map(|node| (node.key.as_str(), &node.value)) } } impl<'a> ExactSizeIterator for Iter<'a> { fn len(&self) -> usize { self.inner.len() } } pub struct IterMut<'a> { inner: slice::IterMut<'a, Node> } impl<'a> IterMut<'a> { /// Create an empty iterator that always returns `None` pub fn empty() -> Self { IterMut { inner: [].iter_mut() } } } impl<'a> Iterator for IterMut<'a> { type Item = (&'a str, &'a mut JsonValue); #[inline(always)] fn next(&mut self) -> Option { self.inner.next().map(|node| (node.key.as_str(), &mut node.value)) } } impl<'a> DoubleEndedIterator for IterMut<'a> { #[inline(always)] fn next_back(&mut self) -> Option { self.inner.next_back().map(|node| (node.key.as_str(), &mut node.value)) } } impl<'a> ExactSizeIterator for IterMut<'a> { fn len(&self) -> usize { self.inner.len() } } /// Implements indexing by `&str` to easily access object members: /// /// ## Example /// /// ``` /// # #[macro_use] /// # extern crate json; /// # use json::JsonValue; /// # /// # fn main() { /// let value = object!{ /// "foo" => "bar" /// }; /// /// if let JsonValue::Object(object) = value { /// assert!(object["foo"] == "bar"); /// } /// # } /// ``` // TODO: doc impl<'a> Index<&'a str> for Object { type Output = JsonValue; fn index(&self, index: &str) -> &JsonValue { match self.get(index) { Some(value) => value, _ => &NULL } } } impl Index for Object { type Output = JsonValue; fn index(&self, index: String) -> &JsonValue { self.index(index.deref()) } } impl<'a> Index<&'a String> for Object { type Output = JsonValue; fn index(&self, index: &String) -> &JsonValue { self.index(index.deref()) } } /// Implements mutable indexing by `&str` to easily modify object members: /// /// ## Example /// /// ``` /// # #[macro_use] /// # extern crate json; /// # use json::JsonValue; /// # /// # fn main() { /// let value = object!{}; /// /// if let JsonValue::Object(mut object) = value { /// object["foo"] = 42.into(); /// /// assert!(object["foo"] == 42); /// } /// # } /// ``` impl<'a> IndexMut<&'a str> for Object { fn index_mut(&mut self, index: &str) -> &mut JsonValue { if self.get(index).is_none() { self.insert(index, JsonValue::Null); } self.get_mut(index).unwrap() } } impl IndexMut for Object { fn index_mut(&mut self, index: String) -> &mut JsonValue { self.index_mut(index.deref()) } } impl<'a> IndexMut<&'a String> for Object { fn index_mut(&mut self, index: &String) -> &mut JsonValue { self.index_mut(index.deref()) } } json-0.12.0/src/parser.rs010064400017500001750000000615651353447543500134470ustar0000000000000000// HERE BE DRAGONS! // ================ // // Making a fast parser is hard. This is a _not so naive_ implementation of // recursive descent that does almost nothing. _There is no backtracking_, the // whole parsing is 100% predictive, even though it's not BNF, and will have // linear performance based on the length of the source! // // There is a lot of macros here! Like, woah! This is mostly due to the fact // that Rust isn't very cool about optimizing inlined functions that return // a `Result` type. Since different functions will have different `Result` // signatures, the `try!` macro will always have to repackage our results. // With macros those issues don't exist, the macro will return an unpackaged // result - whatever it is - and if we ever stumble upon the error, we can // return an `Err` without worrying about the exact signature of `Result`. // // This makes for some ugly code, but it is faster. Hopefully in the future // with MIR support the compiler will get smarter about this. use std::{str, slice}; use std::char::decode_utf16; use std::convert::TryFrom; use crate::object::Object; use crate::number::Number; use crate::{JsonValue, Error, Result}; // This is not actual max precision, but a threshold at which number parsing // kicks into checked math. const MAX_PRECISION: u64 = 576460752303423500; // How many nested Objects/Arrays are allowed to be parsed const DEPTH_LIMIT: usize = 512; // The `Parser` struct keeps track of indexing over our buffer. All niceness // has been abandoned in favor of raw pointer magic. Does that make you feel // dirty? _Good._ struct Parser<'a> { // Helper buffer for parsing strings that can't be just memcopied from // the original source (escaped characters) buffer: Vec, // String slice to parse source: &'a str, // Byte pointer to the slice above byte_ptr: *const u8, // Current index index: usize, // Length of the source length: usize, } // Read a byte from the source. // Will return an error if there are no more bytes. macro_rules! expect_byte { ($parser:ident) => ({ if $parser.is_eof() { return Err(Error::UnexpectedEndOfJson); } let ch = $parser.read_byte(); $parser.bump(); ch }) } // Expect a sequence of specific bytes in specific order, error otherwise. // This is useful for reading the 3 JSON identifiers: // // - "t" has to be followed by "rue" // - "f" has to be followed by "alse" // - "n" has to be followed by "ull" // // Anything else is an error. macro_rules! expect_sequence { ($parser:ident, $( $ch:pat ),*) => { $( match expect_byte!($parser) { $ch => {}, _ => return $parser.unexpected_character(), } )* } } // A drop in macro for when we expect to read a byte, but we don't care // about any whitespace characters that might occur before it. macro_rules! expect_byte_ignore_whitespace { ($parser:ident) => ({ let mut ch = expect_byte!($parser); // Don't go straight for the loop, assume we are in the clear first. match ch { // whitespace 9 ..= 13 | 32 => { loop { match expect_byte!($parser) { 9 ..= 13 | 32 => {}, next => { ch = next; break; } } } }, _ => {} } ch }) } // Expect to find EOF or just whitespaces leading to EOF after a JSON value macro_rules! expect_eof { ($parser:ident) => ({ while !$parser.is_eof() { match $parser.read_byte() { 9 ..= 13 | 32 => $parser.bump(), _ => { $parser.bump(); return $parser.unexpected_character(); } } } }) } // Expect a particular byte to be next. Also available with a variant // creates a `match` expression just to ease some pain. macro_rules! expect { ($parser:ident, $byte:expr) => ({ let ch = expect_byte_ignore_whitespace!($parser); if ch != $byte { return $parser.unexpected_character() } }); {$parser:ident $(, $byte:pat => $then:expr )*} => ({ let ch = expect_byte_ignore_whitespace!($parser); match ch { $( $byte => $then, )* _ => return $parser.unexpected_character() } }) } // Look up table that marks which characters are allowed in their raw // form in a string. const QU: bool = false; // double quote 0x22 const BS: bool = false; // backslash 0x5C const CT: bool = false; // control character 0x00 ..= 0x1F const __: bool = true; static ALLOWED: [bool; 256] = [ // 0 1 2 3 4 5 6 7 8 9 A B C D E F CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0 CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1 __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4 __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F ]; // Expect a string. This is called after encountering, and consuming, a // double quote character. This macro has a happy path variant where it // does almost nothing as long as all characters are allowed (as described // in the look up table above). If it encounters a closing quote without // any escapes, it will use a slice straight from the source, avoiding // unnecessary buffering. macro_rules! expect_string { ($parser:ident) => ({ let result: &str; let start = $parser.index; loop { let ch = expect_byte!($parser); if ALLOWED[ch as usize] { continue; } if ch == b'"' { unsafe { let ptr = $parser.byte_ptr.offset(start as isize); let len = $parser.index - 1 - start; result = str::from_utf8_unchecked(slice::from_raw_parts(ptr, len)); } break; } if ch == b'\\' { result = $parser.read_complex_string(start)?; break; } return $parser.unexpected_character(); } result }) } // Expect a number. Of some kind. macro_rules! expect_number { ($parser:ident, $first:ident) => ({ let mut num = ($first - b'0') as u64; let result: Number; // Cap on how many iterations we do while reading to u64 // in order to avoid an overflow. loop { if num >= MAX_PRECISION { result = $parser.read_big_number(num)?; break; } if $parser.is_eof() { result = num.into(); break; } let ch = $parser.read_byte(); match ch { b'0' ..= b'9' => { $parser.bump(); num = num * 10 + (ch - b'0') as u64; }, _ => { let mut e = 0; result = allow_number_extensions!($parser, num, e, ch); break; } } } result }) } // Invoked after parsing an integer, this will account for fractions and/or // `e` notation. macro_rules! allow_number_extensions { ($parser:ident, $num:ident, $e:ident, $ch:ident) => ({ match $ch { b'.' => { $parser.bump(); expect_fraction!($parser, $num, $e) }, b'e' | b'E' => { $parser.bump(); $parser.expect_exponent($num, $e)? }, _ => $num.into() } }); // Alternative variant that defaults everything to 0. This is actually // quite handy as the only number that can begin with zero, has to have // a zero mantissa. Leading zeroes are illegal in JSON! ($parser:ident) => ({ if $parser.is_eof() { 0.into() } else { let mut num = 0; let mut e = 0; let ch = $parser.read_byte(); allow_number_extensions!($parser, num, e, ch) } }) } // If a dot `b"."` byte has been read, start reading the decimal fraction // of the number. macro_rules! expect_fraction { ($parser:ident, $num:ident, $e:ident) => ({ let result: Number; let ch = expect_byte!($parser); match ch { b'0' ..= b'9' => { if $num < MAX_PRECISION { $num = $num * 10 + (ch - b'0') as u64; $e -= 1; } else { match $num.checked_mul(10).and_then(|num| { num.checked_add((ch - b'0') as u64) }) { Some(result) => { $num = result; $e -= 1; }, None => {} } } }, _ => return $parser.unexpected_character() } loop { if $parser.is_eof() { result = unsafe { Number::from_parts_unchecked(true, $num, $e) }; break; } let ch = $parser.read_byte(); match ch { b'0' ..= b'9' => { $parser.bump(); if $num < MAX_PRECISION { $num = $num * 10 + (ch - b'0') as u64; $e -= 1; } else { match $num.checked_mul(10).and_then(|num| { num.checked_add((ch - b'0') as u64) }) { Some(result) => { $num = result; $e -= 1; }, None => {} } } }, b'e' | b'E' => { $parser.bump(); result = $parser.expect_exponent($num, $e)?; break; } _ => { result = unsafe { Number::from_parts_unchecked(true, $num, $e) }; break; } } } result }) } impl<'a> Parser<'a> { pub fn new(source: &'a str) -> Self { Parser { buffer: Vec::with_capacity(30), source: source, byte_ptr: source.as_ptr(), index: 0, length: source.len(), } } // Check if we are at the end of the source. #[inline(always)] fn is_eof(&mut self) -> bool { self.index == self.length } // Read a byte from the source. Note that this does not increment // the index. In few cases (all of them related to number parsing) // we want to peek at the byte before doing anything. This will, // very very rarely, lead to a situation where the same byte is read // twice, but since this operation is using a raw pointer, the cost // is virtually irrelevant. #[inline(always)] fn read_byte(&mut self) -> u8 { debug_assert!(self.index < self.length, "Reading out of bounds"); unsafe { *self.byte_ptr.offset(self.index as isize) } } // Manually increment the index. Calling `read_byte` and then `bump` // is equivalent to consuming a byte on an iterator. #[inline(always)] fn bump(&mut self) { self.index = self.index.wrapping_add(1); } // So we got an unexpected character, now what? Well, figure out where // it is, and throw an error! fn unexpected_character(&mut self) -> Result { let at = self.index - 1; let ch = self.source[at..] .chars() .next() .expect("Must have a character"); let (lineno, col) = self.source[..at] .lines() .enumerate() .last() .unwrap_or((0, "")); let colno = col.chars().count(); Err(Error::UnexpectedCharacter { ch: ch, line: lineno + 1, column: colno + 1, }) } // Boring fn read_hexdec_digit(&mut self) -> Result { let ch = expect_byte!(self); Ok(match ch { b'0' ..= b'9' => (ch - b'0'), b'a' ..= b'f' => (ch + 10 - b'a'), b'A' ..= b'F' => (ch + 10 - b'A'), _ => return self.unexpected_character(), } as u16) } // Boring fn read_hexdec_codepoint(&mut self) -> Result { Ok( self.read_hexdec_digit()? << 12 | self.read_hexdec_digit()? << 8 | self.read_hexdec_digit()? << 4 | self.read_hexdec_digit()? ) } // Oh look, some action. This method reads an escaped unicode // sequence such as `\uDEAD` from the string. Except `DEAD` is // not a valid codepoint, so it also needs to handle errors... fn read_codepoint(&mut self) -> Result<()> { let mut buf = [0; 4]; let codepoint = self.read_hexdec_codepoint()?; let unicode = match char::try_from(codepoint as u32) { Ok(code) => code, // Handle surrogate pairs Err(_) => { expect_sequence!(self, b'\\', b'u'); match decode_utf16( [codepoint, self.read_hexdec_codepoint()?].iter().copied() ).next() { Some(Ok(code)) => code, _ => return Err(Error::FailedUtf8Parsing), } } }; self.buffer.extend_from_slice(unicode.encode_utf8(&mut buf).as_bytes()); Ok(()) } // What's so complex about strings you may ask? Not that much really. // This method is called if the `expect_string!` macro encounters an // escape. The added complexity is that it will have to use an internal // buffer to read all the escaped characters into, before finally // producing a usable slice. What it means it that parsing "foo\bar" // is whole lot slower than parsing "foobar", as the former suffers from // having to be read from source to a buffer and then from a buffer to // our target string. Nothing to be done about this, really. fn read_complex_string<'b>(&mut self, start: usize) -> Result<&'b str> { self.buffer.clear(); let mut ch = b'\\'; // TODO: Use fastwrite here as well self.buffer.extend_from_slice(self.source[start .. self.index - 1].as_bytes()); loop { if ALLOWED[ch as usize] { self.buffer.push(ch); ch = expect_byte!(self); continue; } match ch { b'"' => break, b'\\' => { let escaped = expect_byte!(self); let escaped = match escaped { b'u' => { self.read_codepoint()?; ch = expect_byte!(self); continue; }, b'"' | b'\\' | b'/' => escaped, b'b' => 0x8, b'f' => 0xC, b't' => b'\t', b'r' => b'\r', b'n' => b'\n', _ => return self.unexpected_character() }; self.buffer.push(escaped); }, _ => return self.unexpected_character() } ch = expect_byte!(self); } // Since the original source is already valid UTF-8, and `\` // cannot occur in front of a codepoint > 127, this is safe. Ok(unsafe { str::from_utf8_unchecked( // Because the buffer is stored on the parser, returning it // as a slice here freaks out the borrow checker. The compiler // can't know that the buffer isn't used till the result // of this function is long used and irrelevant. To avoid // issues here, we construct a new slice from raw parts, which // then has lifetime bound to the outer function scope instead // of the parser itself. slice::from_raw_parts(self.buffer.as_ptr(), self.buffer.len()) ) }) } // Big numbers! If the `expect_number!` reaches a point where the decimal // mantissa could have overflown the size of u64, it will switch to this // control path instead. This method will pick up where the macro started, // but instead of continuing to read into the mantissa, it will increment // the exponent. Note that no digits are actually read here, as we already // exceeded the precision range of f64 anyway. fn read_big_number(&mut self, mut num: u64) -> Result { let mut e = 0i16; loop { if self.is_eof() { return Ok(unsafe { Number::from_parts_unchecked(true, num, e) }); } let ch = self.read_byte(); match ch { b'0' ..= b'9' => { self.bump(); match num.checked_mul(10).and_then(|num| { num.checked_add((ch - b'0') as u64) }) { Some(result) => num = result, None => e = e.checked_add(1).ok_or_else(|| Error::ExceededDepthLimit)?, } }, b'.' => { self.bump(); return Ok(expect_fraction!(self, num, e)); }, b'e' | b'E' => { self.bump(); return self.expect_exponent(num, e); } _ => break } } Ok(unsafe { Number::from_parts_unchecked(true, num, e) }) } // Called in the rare case that a number with `e` notation has been // encountered. This is pretty straight forward, I guess. fn expect_exponent(&mut self, num: u64, big_e: i16) -> Result { let mut ch = expect_byte!(self); let sign = match ch { b'-' => { ch = expect_byte!(self); -1 }, b'+' => { ch = expect_byte!(self); 1 }, _ => 1 }; let mut e = match ch { b'0' ..= b'9' => (ch - b'0') as i16, _ => return self.unexpected_character(), }; loop { if self.is_eof() { break; } let ch = self.read_byte(); match ch { b'0' ..= b'9' => { self.bump(); e = e.saturating_mul(10).saturating_add((ch - b'0') as i16); }, _ => break } } Ok(unsafe { Number::from_parts_unchecked(true, num, big_e.saturating_add(e * sign)) }) } // Parse away! fn parse(&mut self) -> Result { let mut stack = Vec::with_capacity(3); let mut ch = expect_byte_ignore_whitespace!(self); 'parsing: loop { let mut value = match ch { b'[' => { ch = expect_byte_ignore_whitespace!(self); if ch != b']' { if stack.len() == DEPTH_LIMIT { return Err(Error::ExceededDepthLimit); } stack.push(StackBlock(JsonValue::Array(Vec::with_capacity(2)), 0)); continue 'parsing; } JsonValue::Array(Vec::new()) }, b'{' => { ch = expect_byte_ignore_whitespace!(self); if ch != b'}' { if stack.len() == DEPTH_LIMIT { return Err(Error::ExceededDepthLimit); } let mut object = Object::with_capacity(3); if ch != b'"' { return self.unexpected_character() } let index = object.insert_index(expect_string!(self), JsonValue::Null); expect!(self, b':'); stack.push(StackBlock(JsonValue::Object(object), index)); ch = expect_byte_ignore_whitespace!(self); continue 'parsing; } JsonValue::Object(Object::new()) }, b'"' => expect_string!(self).into(), b'0' => JsonValue::Number(allow_number_extensions!(self)), b'1' ..= b'9' => { JsonValue::Number(expect_number!(self, ch)) }, b'-' => { let ch = expect_byte!(self); JsonValue::Number(- match ch { b'0' => allow_number_extensions!(self), b'1' ..= b'9' => expect_number!(self, ch), _ => return self.unexpected_character() }) } b't' => { expect_sequence!(self, b'r', b'u', b'e'); JsonValue::Boolean(true) }, b'f' => { expect_sequence!(self, b'a', b'l', b's', b'e'); JsonValue::Boolean(false) }, b'n' => { expect_sequence!(self, b'u', b'l', b'l'); JsonValue::Null }, _ => return self.unexpected_character() }; 'popping: loop { match stack.last_mut() { None => { expect_eof!(self); return Ok(value); }, Some(&mut StackBlock(JsonValue::Array(ref mut array), _)) => { array.push(value); ch = expect_byte_ignore_whitespace!(self); match ch { b',' => { ch = expect_byte_ignore_whitespace!(self); continue 'parsing; }, b']' => {}, _ => return self.unexpected_character() } }, Some(&mut StackBlock(JsonValue::Object(ref mut object), ref mut index )) => { object.override_at(*index, value); ch = expect_byte_ignore_whitespace!(self); match ch { b',' => { expect!(self, b'"'); *index = object.insert_index(expect_string!(self), JsonValue::Null); expect!(self, b':'); ch = expect_byte_ignore_whitespace!(self); continue 'parsing; }, b'}' => {}, _ => return self.unexpected_character() } }, _ => unreachable!(), } value = match stack.pop() { Some(StackBlock(value, _)) => value, None => break 'popping } } } } } struct StackBlock(JsonValue, usize); // All that hard work, and in the end it's just a single function in the API. #[inline] pub fn parse(source: &str) -> Result { Parser::new(source).parse() } json-0.12.0/src/short.rs010064400017500001750000000053041347550352200132700ustar0000000000000000use std::{ ptr, str, slice, fmt }; use std::ops::Deref; pub const MAX_LEN: usize = 30; #[derive(Clone, Copy)] pub struct Short { len: u8, value: [u8; MAX_LEN], } /// A `Short` is a small string, up to `MAX_LEN` bytes, that can be managed without /// the expensive heap allocation performed for the regular `String` type. impl Short { /// Creates a `Short` from a `&str` slice. This method can cause buffer /// overflow if the length of the slice is larger than `MAX_LEN`, which is why /// it is marked as `unsafe`. /// /// /// Typically you should avoid creating your own `Short`s, instead create a /// `JsonValue` (either using `"foo".into()` or `JsonValue::from("foo")`) out /// of a slice. This will automatically decide on `String` or `Short` for you. #[inline(always)] pub unsafe fn from_slice(slice: &str) -> Self { let mut short = Short { value: [0; MAX_LEN], len: slice.len() as u8, }; ptr::copy_nonoverlapping(slice.as_ptr(), short.value.as_mut_ptr(), slice.len()); short } /// Cheaply obtain a `&str` slice out of the `Short`. #[inline] pub fn as_str(&self) -> &str { unsafe { str::from_utf8_unchecked( slice::from_raw_parts(self.value.as_ptr(), self.len as usize) ) } } } impl PartialEq for Short { #[inline] fn eq(&self, other: &Short) -> bool { self.as_str() == other.as_str() } } impl fmt::Debug for Short { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_str(), f) } } impl fmt::Display for Short { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_str(), f) } } /// Implements `Deref` for `Short` means that, just like `String`, you can /// pass `&Short` to functions that expect `&str` and have the conversion happen /// automagically. On top of that, all methods present on `&str` can be called on /// an instance of `Short`. impl Deref for Short { type Target = str; #[inline(always)] fn deref(&self) -> &str { self.as_str() } } impl From for String { fn from(short: Short) -> String { String::from(short.as_str()) } } impl PartialEq for Short { fn eq(&self, other: &str) -> bool { self.as_str().eq(other) } } impl PartialEq for str { fn eq(&self, other: &Short) -> bool { other.as_str().eq(self) } } impl PartialEq for Short { fn eq(&self, other: &String) -> bool { self.as_str().eq(other) } } impl PartialEq for String { fn eq(&self, other: &Short) -> bool { other.as_str().eq(self) } } json-0.12.0/src/util/diyfp.rs010064400017500001750000000205311347550352200142200ustar0000000000000000// This file comes from the `dtoa` port by David Tolnay: // https://github.com/dtolnay/dtoa // // Copyright 2016 Dtoa Developers // // 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. use std::{mem, ops}; const DIY_SIGNIFICAND_SIZE: isize = 64; const DP_SIGNIFICAND_SIZE: isize = 52; const DP_EXPONENT_BIAS: isize = 0x3FF + DP_SIGNIFICAND_SIZE; const DP_MIN_EXPONENT: isize = -DP_EXPONENT_BIAS; const DP_EXPONENT_MASK: u64 = 0x7FF0000000000000; const DP_SIGNIFICAND_MASK: u64 = 0x000FFFFFFFFFFFFF; const DP_HIDDEN_BIT: u64 = 0x0010000000000000; #[derive(Copy, Clone, Debug)] pub struct DiyFp { pub f: u64, pub e: isize, } impl DiyFp { pub fn new(f: u64, e: isize) -> Self { DiyFp { f: f, e: e } } /* explicit DiyFp(double d) { union { double d; uint64_t u64; } u = { d }; int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); uint64_t significand = (u.u64 & kDpSignificandMask); if (biased_e != 0) { f = significand + kDpHiddenBit; e = biased_e - kDpExponentBias; } else { f = significand; e = kDpMinExponent + 1; } } */ pub unsafe fn from_f64(d: f64) -> Self { let u: u64 = mem::transmute(d); let biased_e = ((u & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE) as isize; let significand = u & DP_SIGNIFICAND_MASK; if biased_e != 0 { DiyFp { f: significand + DP_HIDDEN_BIT, e: biased_e - DP_EXPONENT_BIAS, } } else { DiyFp { f: significand, e: DP_MIN_EXPONENT + 1, } } } /* DiyFp Normalize() const { DiyFp res = *this; while (!(res.f & (static_cast(1) << 63))) { res.f <<= 1; res.e--; } return res; } */ pub fn normalize(self) -> DiyFp { let mut res = self; while (res.f & (1u64 << 63)) == 0 { res.f <<= 1; res.e -= 1; } res } /* DiyFp NormalizeBoundary() const { DiyFp res = *this; while (!(res.f & (kDpHiddenBit << 1))) { res.f <<= 1; res.e--; } res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); return res; } */ pub fn normalize_boundary(self) -> DiyFp { let mut res = self; while (res.f & DP_HIDDEN_BIT << 1) == 0 { res.f <<= 1; res.e -= 1; } res.f <<= DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2; res.e -= DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2; res } /* void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); mi.f <<= mi.e - pl.e; mi.e = pl.e; *plus = pl; *minus = mi; } */ pub fn normalized_boundaries(self) -> (DiyFp, DiyFp) { let pl = DiyFp::new((self.f << 1) + 1, self.e - 1).normalize_boundary(); let mut mi = if self.f == DP_HIDDEN_BIT { DiyFp::new((self.f << 2) - 1, self.e - 2) } else { DiyFp::new((self.f << 1) - 1, self.e - 1) }; mi.f <<= mi.e - pl.e; mi.e = pl.e; (mi, pl) } } impl ops::Sub for DiyFp { type Output = DiyFp; fn sub(self, rhs: DiyFp) -> DiyFp { DiyFp { f: self.f - rhs.f, e: self.e, } } } impl ops::Mul for DiyFp { type Output = DiyFp; fn mul(self, rhs: DiyFp) -> DiyFp { let m32 = 0xFFFFFFFFu64; let a = self.f >> 32; let b = self.f & m32; let c = rhs.f >> 32; let d = rhs.f & m32; let ac = a * c; let bc = b * c; let ad = a * d; let bd = b * d; let mut tmp = (bd >> 32) + (ad & m32) + (bc & m32); tmp += 1u64 << 31; // mult_round DiyFp { f: ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e: self.e + rhs.e + 64, } } } fn get_cached_power_by_index(index: usize) -> DiyFp { // 10^-348, 10^-340, ..., 10^340 static CACHED_POWERS_F: [u64; 87] = [ 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, ]; static CACHED_POWERS_E: [i16; 87] = [ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066, ]; DiyFp::new(CACHED_POWERS_F[index], CACHED_POWERS_E[index] as isize) } /* inline DiyFp GetCachedPower(int e, int* K) { //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive int k = static_cast(dk); if (dk - k > 0.0) k++; unsigned index = static_cast((k >> 3) + 1); *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table return GetCachedPowerByIndex(index); } */ #[inline] pub fn get_cached_power(e: isize) -> (DiyFp, isize) { let dk = (-61 - e) as f64 * 0.30102999566398114f64 + 347f64; // dk must be positive, so can do ceiling in positive let mut k = dk as isize; if dk - k as f64 > 0.0 { k += 1; } let index = ((k >> 3) + 1) as usize; let k = -(-348 + (index << 3) as isize); // decimal exponent no need lookup table (get_cached_power_by_index(index), k) } json-0.12.0/src/util/grisu2.rs010064400017500001750000000070351353446171300143250ustar0000000000000000// This file comes from the `dtoa` port by David Tolnay: // https://github.com/dtolnay/dtoa // // It's an implementation of a Grisu2 algorithm by Florian Loitsch: // http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf // // The algorithm here has been modified to produce a `u64` mantisa and // a decimal exponent instead of writing to a string. // // Copyright 2016 Dtoa Developers // // 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. use crate::util::diyfp::{ self, DiyFp }; #[inline] unsafe fn grisu_round(buffer: &mut u64, delta: u64, mut rest: u64, ten_kappa: u64, wp_w: u64) { while rest < wp_w && delta - rest >= ten_kappa && (rest + ten_kappa < wp_w || // closer wp_w - rest > rest + ten_kappa - wp_w) { *buffer -= 1; rest += ten_kappa; } } #[inline] fn count_decimal_digit32(n: u32) -> i16 { if n < 10 { 1 } else if n < 100 { 2 } else if n < 1000 { 3 } else if n < 10000 { 4 } else if n < 100000 { 5 } else if n < 1000000 { 6 } else if n < 10000000 { 7 } else if n < 100000000 { 8 } // Will not reach 10 digits in digit_gen() else { 9 } } #[inline] unsafe fn digit_gen(w: DiyFp, mp: DiyFp, mut delta: u64, mut k: i16) -> (u64, i16) { static POW10: [u32; 10] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ]; let one = DiyFp::new(1u64 << -mp.e, mp.e); let wp_w = mp - w; let mut p1 = (mp.f >> -one.e) as u32; let mut p2 = mp.f & (one.f - 1); let mut kappa = count_decimal_digit32(p1); // kappa in [0, 9] let mut buffer = p1 as u64; while kappa > 0 { match kappa { 9 => { p1 %= 100000000; } 8 => { p1 %= 10000000; } 7 => { p1 %= 1000000; } 6 => { p1 %= 100000; } 5 => { p1 %= 10000; } 4 => { p1 %= 1000; } 3 => { p1 %= 100; } 2 => { p1 %= 10; } 1 => { p1 = 0; } _ => {} } kappa = kappa.wrapping_sub(1); let tmp = ((p1 as u64) << -one.e) + p2; if tmp <= delta { k += kappa; let pow10 = POW10[kappa as usize] as u64; buffer /= pow10; grisu_round(&mut buffer, delta, tmp, pow10 << -one.e, wp_w.f); return (buffer, k); } } loop { p2 *= 10; delta *= 10; let d = (p2 >> -one.e) as u8; if d != 0 || buffer != 0 { buffer = buffer * 10 + d as u64; } p2 &= one.f - 1; kappa = kappa.wrapping_sub(1); if p2 < delta { k += kappa; let index = -(kappa as isize); grisu_round(&mut buffer, delta, p2, one.f, wp_w.f * if index < 9 { POW10[-(kappa as isize) as usize] as u64 } else { 0 }); return (buffer, k); } } } #[inline] pub fn convert(float: f64) -> (u64, i16) { if float == 0.0 { return (0, 0); } unsafe { let v = DiyFp::from_f64(float); let (w_m, w_p) = v.normalized_boundaries(); let (c_mk, k) = diyfp::get_cached_power(w_p.e); let w = v.normalize() * c_mk; let mut wp = w_p * c_mk; let mut wm = w_m * c_mk; wm.f += 1; wp.f -= 1; digit_gen(w, wp, wp.f - wm.f, k as i16) } } json-0.12.0/src/util/mod.rs010064400017500001750000000000621347550352200136610ustar0000000000000000pub mod diyfp; pub mod grisu2; pub mod print_dec; json-0.12.0/src/util/print_dec.rs010064400017500001750000000166631353446234600150730ustar0000000000000000// This is a modified version of the `itoa` crate by David Tolnay: // https://github.com/dtolnay/itoa // // The crate itself borrows code from the stdlib of Rust. // // The algorithm here was modified from being able to just writing integers, // to printing decimal floating points. use std::{io, mem, ptr, slice}; const DEC_DIGITS_LUT: &'static[u8] = b"0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; const ZEROFILL: &'static [u8] = &[b'0'; 20]; #[inline(always)] unsafe fn write_num(n: &mut u64, curr: &mut isize, buf_ptr: *mut u8, lut_ptr: *const u8) { // eagerly decode 4 digits at a time while *n >= 10000 { let rem = (*n % 10000) as isize; *n /= 10000; let d1 = (rem / 100) << 1; let d2 = (rem % 100) << 1; *curr -= 4; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2); ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(*curr + 2), 2); } // decode 2 more digits if *n >= 100 { let d1 = ((*n % 100) << 1) as isize; *n /= 100; *curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2); } // decode last 1 or 2 digits if *n < 10 { *curr -= 1; *buf_ptr.offset(*curr) = (*n as u8) + b'0'; } else { let d1 = (*n << 1) as isize; *curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(*curr), 2); } } pub unsafe fn write(wr: &mut W, positive: bool, mut n: u64, exponent: i16) -> io::Result<()> { if !positive { wr.write_all(b"-")?; } if n == 0 { return wr.write_all(b"0"); } let mut buf: [u8; 30] = mem::uninitialized(); let mut curr = buf.len() as isize; let buf_ptr = buf.as_mut_ptr(); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); if exponent == 0 { write_num(&mut n, &mut curr, buf_ptr, lut_ptr); return wr.write_all( slice::from_raw_parts( buf_ptr.offset(curr), buf.len() - curr as usize ) ); } else if exponent < 0 { let mut e = safe_abs(exponent); // Decimal number with a fraction that's fully printable if e < 18 { // eagerly decode 4 digits at a time for _ in 0 .. e >> 2 { let rem = (n % 10000) as isize; n /= 10000; let d1 = (rem / 100) << 1; let d2 = (rem % 100) << 1; curr -= 4; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); } e &= 3; // write the remaining 3, 2 or 1 digits if e & 2 == 2 { let d1 = ((n % 100) << 1) as isize; n /= 100; curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); } if e & 1 == 1 { curr -= 1; *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0'; n /= 10; } curr -= 1; *buf_ptr.offset(curr) = b'.'; write_num(&mut n, &mut curr, buf_ptr, lut_ptr); return wr.write_all( slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize) ); } // Not easily printable, write down fraction, then full number, then exponent // Since we move the decimal point right after the first digit, we have to adjust the // exponent part. If the number is long enough, this may result in the exponent switching // sign from negative to positive - we have to handle this case separately. let mut exponent_positive = false; if n < 10 { // Single digit, no fraction curr -= 1; *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0'; } else { // eagerly decode 4 digits at a time while n >= 100000 { let rem = (n % 10000) as isize; n /= 10000; let d1 = (rem / 100) << 1; let d2 = (rem % 100) << 1; curr -= 4; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); } // decode 2 more digits if n >= 1000 { let d1 = ((n % 100) << 1) as isize; n /= 100; curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); } // decode last 1 or 2 digits if n < 100 { curr -= 1; *buf_ptr.offset(curr) = ((n % 10) as u8) + b'0'; n /= 10; } else { let d1 = ((n % 100) << 1) as isize; n /= 100; curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); } let printed_so_far = buf.len() as u16 - curr as u16; if printed_so_far <= e { // Subtract the amount of digits printed in the fraction // from the exponent that we still need to print using // the `e` notation e -= printed_so_far; } else { // Same as e = |e - printed_so_far|. e = printed_so_far - e; exponent_positive = true; } curr -= 1; *buf_ptr.offset(curr) = b'.'; write_num(&mut n, &mut curr, buf_ptr, lut_ptr); } // Write out the number with a fraction wr.write_all( slice::from_raw_parts( buf_ptr.offset(curr), buf.len() - curr as usize ) )?; // Omit the 'e' notation for e == 0 if e == 0 { return Ok(()); } // Write the remaining `e` notation, with proper sign if exponent_positive { wr.write_all(b"e+")?; } else { wr.write_all(b"e-")?; } return write(wr, true, e as u64, 0); } // Exponent greater than 0 write_num(&mut n, &mut curr, buf_ptr, lut_ptr); let printed = buf.len() - curr as usize; // No need for `e` notation, just print out zeroes if (printed + exponent as usize) <= 20 { wr.write_all( slice::from_raw_parts( buf_ptr.offset(curr), buf.len() - curr as usize ) )?; return wr.write_all(&ZEROFILL[ .. exponent as usize]); } let mut e = exponent as u64; // More than one digit, turn into a fraction if printed != 1 { *buf_ptr.offset(curr - 1) = *buf_ptr.offset(curr); *buf_ptr.offset(curr) = b'.'; curr -= 1; e += (printed as u64) - 1; } wr.write_all( slice::from_raw_parts( buf_ptr.offset(curr), buf.len() - curr as usize ) )?; wr.write_all(b"e")?; write(wr, true, e, 0) } fn safe_abs(x : i16) -> u16 { if let Some(y) = x.checked_abs() { y as u16 } else { i16::max_value() as u16 + 1u16 } } json-0.12.0/src/value/implements.rs010064400017500001750000000105561353450002200154130ustar0000000000000000// This is a private module that contains `PartialEq` and `From` trait // implementations for `JsonValue`. use std::collections::{BTreeMap, HashMap}; use crate::short::{self, Short}; use crate::number::Number; use crate::object::Object; use crate::value::JsonValue; macro_rules! implement_eq { ($to:ident, $from:ty) => { impl PartialEq<$from> for JsonValue { fn eq(&self, other: &$from) -> bool { match *self { JsonValue::$to(ref value) => value == other, _ => false } } } impl<'a> PartialEq<$from> for &'a JsonValue { fn eq(&self, other: &$from) -> bool { match **self { JsonValue::$to(ref value) => value == other, _ => false } } } impl PartialEq for $from { fn eq(&self, other: &JsonValue) -> bool { match *other { JsonValue::$to(ref value) => value == self, _ => false } } } } } macro_rules! implement { ($to:ident, $from:ty as num) => { impl From<$from> for JsonValue { fn from(val: $from) -> JsonValue { JsonValue::$to(val.into()) } } implement_eq!($to, $from); }; ($to:ident, $from:ty) => { impl From<$from> for JsonValue { fn from(val: $from) -> JsonValue { JsonValue::$to(val) } } implement_eq!($to, $from); } } impl<'a> From<&'a str> for JsonValue { fn from(val: &'a str) -> JsonValue { if val.len() <= short::MAX_LEN { JsonValue::Short(unsafe { Short::from_slice(val) }) } else { JsonValue::String(val.into()) } } } impl> From> for JsonValue { fn from(val: Option) -> JsonValue { match val { Some(val) => val.into(), None => JsonValue::Null, } } } impl> From> for JsonValue { fn from(val: Vec) -> JsonValue { JsonValue::Array(val.into_iter().map(Into::into).collect()) } } impl<'a, T: Into + Clone> From<&'a [T]> for JsonValue { fn from(val: &'a [T]) -> JsonValue { JsonValue::Array(val.iter().cloned().map(Into::into).collect()) } } impl, V: Into> From> for JsonValue { fn from(val: HashMap) -> JsonValue { JsonValue::Object(val.into_iter().collect()) } } impl, V: Into> From> for JsonValue { fn from(val: BTreeMap) -> JsonValue { JsonValue::Object(val.into_iter().collect()) } } impl<'a> PartialEq<&'a str> for JsonValue { fn eq(&self, other: &&str) -> bool { match *self { JsonValue::Short(ref value) => value == *other, JsonValue::String(ref value) => value == *other, _ => false } } } impl<'a> PartialEq for &'a str { fn eq(&self, other: &JsonValue) -> bool { match *other { JsonValue::Short(ref value) => value == *self, JsonValue::String(ref value) => value == *self, _ => false } } } impl PartialEq for JsonValue { fn eq(&self, other: &str) -> bool { match *self { JsonValue::Short(ref value) => value == other, JsonValue::String(ref value) => value == other, _ => false } } } impl<'a> PartialEq for str { fn eq(&self, other: &JsonValue) -> bool { match *other { JsonValue::Short(ref value) => value == self, JsonValue::String(ref value) => value == self, _ => false } } } implement!(String, String); implement!(Number, isize as num); implement!(Number, usize as num); implement!(Number, i8 as num); implement!(Number, i16 as num); implement!(Number, i32 as num); implement!(Number, i64 as num); implement!(Number, u8 as num); implement!(Number, u16 as num); implement!(Number, u32 as num); implement!(Number, u64 as num); implement!(Number, f32 as num); implement!(Number, f64 as num); implement!(Number, Number); implement!(Object, Object); implement!(Boolean, bool); json-0.12.0/src/value/mod.rs010064400017500001750000000477361353446202600140420ustar0000000000000000use std::ops::{Index, IndexMut, Deref}; use std::{fmt, mem, usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32}; use std::io::{self, Write}; use crate::{Result, Error}; use crate::short::Short; use crate::number::Number; use crate::object::Object; use crate::iterators::{ Members, MembersMut, Entries, EntriesMut }; use crate::codegen::{ Generator, PrettyGenerator, DumpGenerator, WriterGenerator, PrettyWriterGenerator }; mod implements; // These are convenience macros for converting `f64` to the `$unsigned` type. // The macros check that the numbers are representable the target type. macro_rules! number_to_unsigned { ($unsigned:ident, $value:expr, $high:ty) => { if $value > $unsigned::MAX as $high { None } else { Some($value as $unsigned) } } } macro_rules! number_to_signed { ($signed:ident, $value:expr, $high:ty) => { if $value < $signed::MIN as $high || $value > $signed::MAX as $high { None } else { Some($value as $signed) } } } #[derive(Debug, Clone)] pub enum JsonValue { Null, Short(Short), String(String), Number(Number), Boolean(bool), Object(Object), Array(Vec), } impl PartialEq for JsonValue { fn eq(&self, other: &Self) -> bool { use self::JsonValue::*; match (self, other) { (&Null, &Null) => true, (&Short(ref a), &Short(ref b)) => a == b, (&String(ref a), &String(ref b)) => a == b, (&Short(ref a), &String(ref b)) | (&String(ref b), &Short(ref a)) => a.as_str() == b.as_str(), (&Number(ref a), &Number(ref b)) => a == b, (&Boolean(ref a), &Boolean(ref b)) => a == b, (&Object(ref a), &Object(ref b)) => a == b, (&Array(ref a), &Array(ref b)) => a == b, _ => false, } } } impl Eq for JsonValue {} /// Implements formatting /// /// ``` /// # use json; /// let data = json::parse(r#"{"url":"https://github.com/"}"#).unwrap(); /// println!("{}", data); /// println!("{:#}", data); /// ``` impl fmt::Display for JsonValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if f.alternate() { f.write_str(&self.pretty(4)) } else { match *self { JsonValue::Short(ref value) => value.fmt(f), JsonValue::String(ref value) => value.fmt(f), JsonValue::Number(ref value) => value.fmt(f), JsonValue::Boolean(ref value) => value.fmt(f), JsonValue::Null => f.write_str("null"), _ => f.write_str(&self.dump()) } } } } static NULL: JsonValue = JsonValue::Null; impl JsonValue { /// Create an empty `JsonValue::Object` instance. /// When creating an object with data, consider using the `object!` macro. pub fn new_object() -> JsonValue { JsonValue::Object(Object::new()) } /// Create an empty `JsonValue::Array` instance. /// When creating array with data, consider using the `array!` macro. pub fn new_array() -> JsonValue { JsonValue::Array(Vec::new()) } /// Prints out the value as JSON string. pub fn dump(&self) -> String { let mut gen = DumpGenerator::new(); gen.write_json(self).expect("Can't fail"); gen.consume() } /// Pretty prints out the value as JSON string. Takes an argument that's /// number of spaces to indent new blocks with. pub fn pretty(&self, spaces: u16) -> String { let mut gen = PrettyGenerator::new(spaces); gen.write_json(self).expect("Can't fail"); gen.consume() } /// Writes the JSON as byte stream into an implementor of `std::io::Write`. /// /// This method is deprecated as it will panic on io errors, use `write` instead. #[deprecated(since="0.10.2", note="use `JsonValue::write` instead")] pub fn to_writer(&self, writer: &mut W) { let mut gen = WriterGenerator::new(writer); gen.write_json(self).expect("Deprecated"); } /// Writes the JSON as byte stream into an implementor of `std::io::Write`. pub fn write(&self, writer: &mut W) -> io::Result<()> { let mut gen = WriterGenerator::new(writer); gen.write_json(self) } /// Writes the JSON as byte stream into an implementor of `std::io::Write`. pub fn write_pretty(&self, writer: &mut W, spaces: u16) -> io::Result<()> { let mut gen = PrettyWriterGenerator::new(writer, spaces); gen.write_json(self) } pub fn is_string(&self) -> bool { match *self { JsonValue::Short(_) => true, JsonValue::String(_) => true, _ => false, } } pub fn is_number(&self) -> bool { match *self { JsonValue::Number(_) => true, _ => false, } } pub fn is_boolean(&self) -> bool { match *self { JsonValue::Boolean(_) => true, _ => false } } pub fn is_null(&self) -> bool { match *self { JsonValue::Null => true, _ => false, } } pub fn is_object(&self) -> bool { match *self { JsonValue::Object(_) => true, _ => false, } } pub fn is_array(&self) -> bool { match *self { JsonValue::Array(_) => true, _ => false, } } /// Checks whether the value is empty. Returns true for: /// /// - empty string (`""`) /// - number `0` /// - boolean `false` /// - null /// - empty array (`array![]`) /// - empty object (`object!{}`) pub fn is_empty(&self) -> bool { match *self { JsonValue::Null => true, JsonValue::Short(ref value) => value.is_empty(), JsonValue::String(ref value) => value.is_empty(), JsonValue::Number(ref value) => value.is_empty(), JsonValue::Boolean(ref value) => !value, JsonValue::Array(ref value) => value.is_empty(), JsonValue::Object(ref value) => value.is_empty(), } } pub fn as_str(&self) -> Option<&str> { match *self { JsonValue::Short(ref value) => Some(value), JsonValue::String(ref value) => Some(value), _ => None } } pub fn as_number(&self) -> Option { match *self { JsonValue::Number(value) => Some(value), _ => None } } pub fn as_f64(&self) -> Option { self.as_number().map(|value| value.into()) } pub fn as_f32(&self) -> Option { self.as_number().map(|value| value.into()) } pub fn as_u64(&self) -> Option { self.as_number().and_then(|value| { if value.is_sign_positive() { Some(value.into()) } else { None } }) } pub fn as_u32(&self) -> Option { self.as_u64().and_then(|value| number_to_unsigned!(u32, value, u64)) } pub fn as_u16(&self) -> Option { self.as_u64().and_then(|value| number_to_unsigned!(u16, value, u64)) } pub fn as_u8(&self) -> Option { self.as_u64().and_then(|value| number_to_unsigned!(u8, value, u64)) } pub fn as_usize(&self) -> Option { self.as_u64().and_then(|value| number_to_unsigned!(usize, value, u64)) } pub fn as_i64(&self) -> Option { self.as_number().map(|value| value.into()) } pub fn as_i32(&self) -> Option { self.as_i64().and_then(|value| number_to_signed!(i32, value, i64)) } pub fn as_i16(&self) -> Option { self.as_i64().and_then(|value| number_to_signed!(i16, value, i64)) } pub fn as_i8(&self) -> Option { self.as_i64().and_then(|value| number_to_signed!(i8, value, i64)) } pub fn as_isize(&self) -> Option { self.as_i64().and_then(|value| number_to_signed!(isize, value, i64)) } pub fn as_bool(&self) -> Option { match *self { JsonValue::Boolean(ref value) => Some(*value), _ => None } } /// Obtain an integer at a fixed decimal point. This is useful for /// converting monetary values and doing arithmetic on them without /// rounding errors introduced by floating point operations. /// /// Will return `None` if `Number` called on a value that's not a number, /// or if the number is negative or a NaN. /// /// ``` /// # use json::JsonValue; /// let price_a = JsonValue::from(5.99); /// let price_b = JsonValue::from(7); /// let price_c = JsonValue::from(10.2); /// /// assert_eq!(price_a.as_fixed_point_u64(2), Some(599)); /// assert_eq!(price_b.as_fixed_point_u64(2), Some(700)); /// assert_eq!(price_c.as_fixed_point_u64(2), Some(1020)); /// ``` pub fn as_fixed_point_u64(&self, point: u16) -> Option { match *self { JsonValue::Number(ref value) => value.as_fixed_point_u64(point), _ => None } } /// Analog to `as_fixed_point_u64`, except returning a signed /// `i64`, properly handling negative numbers. /// /// ``` /// # use json::JsonValue; /// let balance_a = JsonValue::from(-1.49); /// let balance_b = JsonValue::from(42); /// /// assert_eq!(balance_a.as_fixed_point_i64(2), Some(-149)); /// assert_eq!(balance_b.as_fixed_point_i64(2), Some(4200)); /// ``` pub fn as_fixed_point_i64(&self, point: u16) -> Option { match *self { JsonValue::Number(ref value) => value.as_fixed_point_i64(point), _ => None } } /// Take over the ownership of the value, leaving `Null` in it's place. /// /// ## Example /// /// ``` /// # #[macro_use] extern crate json; /// # fn main() { /// let mut data = array!["Foo", 42]; /// /// let first = data[0].take(); /// let second = data[1].take(); /// /// assert!(first == "Foo"); /// assert!(second == 42); /// /// assert!(data[0].is_null()); /// assert!(data[1].is_null()); /// # } /// ``` pub fn take(&mut self) -> JsonValue { mem::replace(self, JsonValue::Null) } /// Checks that self is a string, returns an owned Rust `String`, leaving /// `Null` in it's place. /// /// - If the contained string is already a heap allocated `String`, then /// the ownership is moved without any heap allocation. /// /// - If the contained string is a `Short`, this will perform a heap /// allocation to convert the types for you. /// /// ## Example /// /// ``` /// # #[macro_use] extern crate json; /// # fn main() { /// let mut data = array!["Hello", "World"]; /// /// let owned = data[0].take_string().expect("Should be a string"); /// /// assert_eq!(owned, "Hello"); /// assert!(data[0].is_null()); /// # } /// ``` pub fn take_string(&mut self) -> Option { let mut placeholder = JsonValue::Null; mem::swap(self, &mut placeholder); match placeholder { JsonValue::Short(short) => return Some(short.into()), JsonValue::String(string) => return Some(string), // Not a string? Swap the original value back in place! _ => mem::swap(self, &mut placeholder) } None } /// Works on `JsonValue::Array` - pushes a new value to the array. pub fn push(&mut self, value: T) -> Result<()> where T: Into { match *self { JsonValue::Array(ref mut vec) => { vec.push(value.into()); Ok(()) }, _ => Err(Error::wrong_type("Array")) } } /// Works on `JsonValue::Array` - remove and return last element from /// an array. On failure returns a null. pub fn pop(&mut self) -> JsonValue { match *self { JsonValue::Array(ref mut vec) => { vec.pop().unwrap_or(JsonValue::Null) }, _ => JsonValue::Null } } /// Works on `JsonValue::Array` - checks if the array contains a value pub fn contains(&self, item: T) -> bool where T: PartialEq { match *self { JsonValue::Array(ref vec) => vec.iter().any(|member| item == *member), _ => false } } /// Works on `JsonValue::Object` - checks if the object has a key pub fn has_key(&self, key: &str) -> bool { match *self { JsonValue::Object(ref object) => object.get(key).is_some(), _ => false } } /// Returns length of array or object (number of keys), defaults to `0` for /// other types. pub fn len(&self) -> usize { match *self { JsonValue::Array(ref vec) => { vec.len() }, JsonValue::Object(ref object) => { object.len() }, _ => 0 } } /// Works on `JsonValue::Array` - returns an iterator over members. /// Will return an empty iterator if called on non-array types. pub fn members(&self) -> Members { match *self { JsonValue::Array(ref vec) => { vec.iter() }, _ => [].iter() } } /// Works on `JsonValue::Array` - returns a mutable iterator over members. /// Will return an empty iterator if called on non-array types. pub fn members_mut(&mut self) -> MembersMut { match *self { JsonValue::Array(ref mut vec) => { vec.iter_mut() }, _ => [].iter_mut() } } /// Works on `JsonValue::Object` - returns an iterator over key value pairs. /// Will return an empty iterator if called on non-object types. pub fn entries(&self) -> Entries { match *self { JsonValue::Object(ref object) => { object.iter() }, _ => Entries::empty() } } /// Works on `JsonValue::Object` - returns a mutable iterator over /// key value pairs. /// Will return an empty iterator if called on non-object types. pub fn entries_mut(&mut self) -> EntriesMut { match *self { JsonValue::Object(ref mut object) => { object.iter_mut() }, _ => EntriesMut::empty() } } /// Works on `JsonValue::Object` - inserts a new entry, or override an existing /// one into the object. Note that `key` has to be a `&str` slice and not an owned /// `String`. The internals of `Object` will handle the heap allocation of the key /// if needed for better performance. pub fn insert(&mut self, key: &str, value: T) -> Result<()> where T: Into { match *self { JsonValue::Object(ref mut object) => { object.insert(key, value.into()); Ok(()) }, _ => Err(Error::wrong_type("Object")) } } /// Works on `JsonValue::Object` - remove a key and return the value it held. /// If the key was not present, the method is called on anything but an /// object, it will return a null. pub fn remove(&mut self, key: &str) -> JsonValue { match *self { JsonValue::Object(ref mut object) => { object.remove(key).unwrap_or(JsonValue::Null) }, _ => JsonValue::Null } } /// Works on `JsonValue::Array` - remove an entry and return the value it held. /// If the method is called on anything but an object or if the index is out of bounds, it /// will return `JsonValue::Null`. pub fn array_remove(&mut self, index: usize) -> JsonValue { match *self { JsonValue::Array(ref mut vec) => { if index < vec.len() { vec.remove(index) } else { JsonValue::Null } }, _ => JsonValue::Null } } /// When called on an array or an object, will wipe them clean. When called /// on a string will clear the string. Numbers and booleans become null. pub fn clear(&mut self) { match *self { JsonValue::String(ref mut string) => string.clear(), JsonValue::Object(ref mut object) => object.clear(), JsonValue::Array(ref mut vec) => vec.clear(), _ => *self = JsonValue::Null, } } } /// Implements indexing by `usize` to easily access array members: /// /// ## Example /// /// ``` /// # use json::JsonValue; /// let mut array = JsonValue::new_array(); /// /// array.push("foo"); /// /// assert!(array[0] == "foo"); /// ``` impl Index for JsonValue { type Output = JsonValue; fn index(&self, index: usize) -> &JsonValue { match *self { JsonValue::Array(ref vec) => vec.get(index).unwrap_or(&NULL), _ => &NULL } } } /// Implements mutable indexing by `usize` to easily modify array members: /// /// ## Example /// /// ``` /// # #[macro_use] /// # extern crate json; /// # /// # fn main() { /// let mut array = array!["foo", 3.14]; /// /// array[1] = "bar".into(); /// /// assert!(array[1] == "bar"); /// # } /// ``` impl IndexMut for JsonValue { fn index_mut(&mut self, index: usize) -> &mut JsonValue { match *self { JsonValue::Array(ref mut vec) => { let in_bounds = index < vec.len(); if in_bounds { &mut vec[index] } else { vec.push(JsonValue::Null); vec.last_mut().unwrap() } } _ => { *self = JsonValue::new_array(); self.push(JsonValue::Null).unwrap(); self.index_mut(index) } } } } /// Implements indexing by `&str` to easily access object members: /// /// ## Example /// /// ``` /// # #[macro_use] /// # extern crate json; /// # /// # fn main() { /// let object = object!{ /// "foo" => "bar" /// }; /// /// assert!(object["foo"] == "bar"); /// # } /// ``` impl<'a> Index<&'a str> for JsonValue { type Output = JsonValue; fn index(&self, index: &str) -> &JsonValue { match *self { JsonValue::Object(ref object) => &object[index], _ => &NULL } } } impl Index for JsonValue { type Output = JsonValue; fn index(&self, index: String) -> &JsonValue { self.index(index.deref()) } } impl<'a> Index<&'a String> for JsonValue { type Output = JsonValue; fn index(&self, index: &String) -> &JsonValue { self.index(index.deref()) } } /// Implements mutable indexing by `&str` to easily modify object members: /// /// ## Example /// /// ``` /// # #[macro_use] /// # extern crate json; /// # /// # fn main() { /// let mut object = object!{}; /// /// object["foo"] = 42.into(); /// /// assert!(object["foo"] == 42); /// # } /// ``` impl<'a> IndexMut<&'a str> for JsonValue { fn index_mut(&mut self, index: &str) -> &mut JsonValue { match *self { JsonValue::Object(ref mut object) => { &mut object[index] }, _ => { *self = JsonValue::new_object(); self.index_mut(index) } } } } impl IndexMut for JsonValue { fn index_mut(&mut self, index: String) -> &mut JsonValue { self.index_mut(index.deref()) } } impl<'a> IndexMut<&'a String> for JsonValue { fn index_mut(&mut self, index: &String) -> &mut JsonValue { self.index_mut(index.deref()) } } json-0.12.0/tests/json_checker.rs010064400017500001750000000136611347550365100151510ustar0000000000000000extern crate json; mod json_checker_fail { use super::json::parse; #[test] fn unclosed_array() { assert!(parse(r#"["Unclosed array""#).is_err()); } #[test] fn unquoted_key() { assert!(parse(r#"{unquoted_key: "keys must be quoted"}"#).is_err()); } #[test] fn extra_comma_arr() { assert!(parse(r#"["extra comma",]"#).is_err()); } #[test] fn double_extra_comma() { assert!(parse(r#"["double extra comma",,]"#).is_err()); } #[test] fn missing_value() { assert!(parse(r#"[ , "<-- missing value"]"#).is_err()); } #[test] fn comma_after_close() { assert!(parse(r#"["Comma after the close"],"#).is_err()); } #[test] fn extra_close() { assert!(parse(r#"["Extra close"]]"#).is_err()); } #[test] fn extra_comma_obj() { assert!(parse(r#"{"Extra comma": true,}"#).is_err()); } #[test] fn extra_value_after_close() { assert!(parse(r#"{"Extra value after close": true} "misplaced quoted value""#).is_err()); } #[test] fn illegal_expression() { assert!(parse(r#"{"Illegal expression": 1 + 2}"#).is_err()); } #[test] fn illegal_invocation() { assert!(parse(r#"{"Illegal invocation": alert()}"#).is_err()); } #[test] fn numbers_cannot_have_leading_zeroes() { assert!(parse(r#"{"Numbers cannot have leading zeroes": 013}"#).is_err()); } #[test] fn numbers_cannot_be_hex() { assert!(parse(r#"{"Numbers cannot be hex": 0x14}"#).is_err()); } #[test] fn illegal_backslash_escape() { assert!(parse(r#"["Illegal backslash escape: \x15"]"#).is_err()); } #[test] fn naked() { assert!(parse(r#"[\naked]"#).is_err()); } #[test] fn illegal_backslash_escape_2() { assert!(parse(r#"["Illegal backslash escape: \017"]"#).is_err()); } #[test] fn missing_colon() { assert!(parse(r#"{"Missing colon" null}"#).is_err()); } #[test] fn double_colon() { assert!(parse(r#"{"Double colon":: null}"#).is_err()); } #[test] fn comma_instead_of_colon() { assert!(parse(r#"{"Comma instead of colon", null}"#).is_err()); } #[test] fn colon_instead_of_comma() { assert!(parse(r#"["Colon instead of comma": false]"#).is_err()); } #[test] fn bad_value() { assert!(parse(r#"["Bad value", truth]"#).is_err()); } #[test] fn single_quote() { assert!(parse(r#"['single quote']"#).is_err()); } #[test] fn tab_character_in_string() { assert!(parse("[\"\ttab\tcharacter\tin\tstring\t\"]").is_err()); } #[test] fn tab_character_in_string_esc() { assert!(parse("[\"tab\\\tcharacter\\\tin\\\tstring\\\t\"]").is_err()); } #[test] fn line_break() { assert!(parse("[\"line\nbreak\"]").is_err()); } #[test] fn line_break_escaped() { assert!(parse("[\"line\\\nbreak\"]").is_err()); } #[test] fn no_exponent() { assert!(parse(r#"[0e]"#).is_err()); } #[test] fn no_exponent_plus() { assert!(parse(r#"[0e+]"#).is_err()); } #[test] fn exponent_both_signs() { assert!(parse(r#"[0e+-1]"#).is_err()); } #[test] fn comma_instead_of_closing_brace() { assert!(parse(r#"{"Comma instead if closing brace": true,"#).is_err()); } #[test] fn missmatch() { assert!(parse(r#"["mismatch"}"#).is_err()); } } mod json_checker_pass { use super::json::parse; #[test] fn pass_1() { parse(r##" [ "JSON Test Pattern pass1", {"object with 1 member":["array with 1 element"]}, {}, [], -42, true, false, null, { "integer": 1234567890, "real": -9876.543210, "e": 0.123456789e-12, "E": 1.234567890E+34, "": 23456789012E66, "zero": 0, "one": 1, "space": " ", "quote": "\"", "backslash": "\\", "controls": "\b\f\n\r\t", "slash": "/ & \/", "alpha": "abcdefghijklmnopqrstuvwyz", "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", "digit": "0123456789", "0123456789": "digit", "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", "true": true, "false": false, "null": null, "array":[ ], "object":{ }, "address": "50 St. James Street", "url": "http://www.JSON.org/", "comment": "// /* */": " ", " s p a c e d " :[1,2 , 3 , 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", "quotes": "" \u0022 %22 0x22 034 "", "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" : "A key can be any string" }, 0.5 ,98.6 , 99.44 , 1066, 1e1, 0.1e1, 1e-1, 1e00,2e+00,2e-00 ,"rosebud"] "##).unwrap(); assert!(true); } #[test] fn pass_2() { parse(r#"[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]"#).unwrap(); assert!(true); } #[test] fn pass_3() { parse(r#" { "JSON Test Pattern pass3": { "The outermost value": "must be an object or array.", "In this test": "It is an object." } } "#).unwrap(); assert!(true); } } json-0.12.0/tests/number.rs010064400017500001750000000073641347550364700140140ustar0000000000000000extern crate json; use json::number::Number; use std::f64; #[test] fn is_nan() { assert!(Number::from(f64::NAN).is_nan()); } #[test] fn is_zero() { assert!(Number::from(0).is_zero()); assert!(unsafe { Number::from_parts_unchecked(true, 0, 0).is_zero() }); assert!(unsafe { Number::from_parts_unchecked(true, 0, 100).is_zero() }); assert!(unsafe { Number::from_parts_unchecked(true, 0, -100).is_zero() }); assert!(unsafe { Number::from_parts_unchecked(false, 0, 0).is_zero() }); assert!(unsafe { Number::from_parts_unchecked(false, 0, 100).is_zero() }); assert!(unsafe { Number::from_parts_unchecked(false, 0, -100).is_zero() }); assert!(!Number::from(f64::NAN).is_zero()); } #[test] fn is_empty() { assert!(Number::from(0).is_empty()); assert!(Number::from(f64::NAN).is_empty()); } #[test] fn eq() { assert_eq!( unsafe { Number::from_parts_unchecked(true, 500, 0) }, unsafe { Number::from_parts_unchecked(true, 500, 0) } ); } #[test] fn eq_normalize_left_positive() { assert_eq!( unsafe { Number::from_parts_unchecked(true, 5, 2) }, unsafe { Number::from_parts_unchecked(true, 500, 0) } ); } #[test] fn eq_normalize_left_negative() { assert_eq!( unsafe { Number::from_parts_unchecked(true, 5, -2) }, unsafe { Number::from_parts_unchecked(true, 500, -4) } ); } #[test] fn eq_normalize_right_positive() { assert_eq!( unsafe { Number::from_parts_unchecked(true, 500, 0) }, unsafe { Number::from_parts_unchecked(true, 5, 2) } ); } #[test] fn eq_normalize_right_negative() { assert_eq!( unsafe { Number::from_parts_unchecked(true, 500, -4) }, unsafe { Number::from_parts_unchecked(true, 5, -2) } ); } #[test] fn from_small_float() { assert_eq!(Number::from(0.05), unsafe { Number::from_parts_unchecked(true, 5, -2) }); } #[test] fn from_very_small_float() { assert_eq!(Number::from(5e-50), unsafe { Number::from_parts_unchecked(true, 5, -50) }); } #[test] fn from_big_float() { assert_eq!(Number::from(500), unsafe { Number::from_parts_unchecked(true, 500, 0) }); } #[test] fn from_very_big_float() { assert_eq!(Number::from(5e50), unsafe { Number::from_parts_unchecked(true, 5, 50) }); } #[test] fn into_very_small_float() { let number = unsafe { Number::from_parts_unchecked(true, 2225073858507201136, -326) }; assert_eq!(f64::from(number), 2.225073858507201e-308); } #[test] fn as_fixed_point_u64() { assert_eq!(Number::from(1.2345).as_fixed_point_u64(4).unwrap(), 12345); assert_eq!(Number::from(1.2345).as_fixed_point_u64(2).unwrap(), 123); assert_eq!(Number::from(1.2345).as_fixed_point_u64(0).unwrap(), 1); assert_eq!(Number::from(5).as_fixed_point_u64(0).unwrap(), 5); assert_eq!(Number::from(5).as_fixed_point_u64(2).unwrap(), 500); assert_eq!(Number::from(5).as_fixed_point_u64(4).unwrap(), 50000); assert_eq!(Number::from(-1).as_fixed_point_u64(0), None); assert_eq!(Number::from(f64::NAN).as_fixed_point_u64(0), None); } #[test] fn as_fixed_point_i64() { assert_eq!(Number::from(-1.2345).as_fixed_point_i64(4).unwrap(), -12345); assert_eq!(Number::from(-1.2345).as_fixed_point_i64(2).unwrap(), -123); assert_eq!(Number::from(-1.2345).as_fixed_point_i64(0).unwrap(), -1); assert_eq!(Number::from(-5).as_fixed_point_i64(0).unwrap(), -5); assert_eq!(Number::from(-5).as_fixed_point_i64(2).unwrap(), -500); assert_eq!(Number::from(-5).as_fixed_point_i64(4).unwrap(), -50000); assert_eq!(Number::from(-1).as_fixed_point_i64(0), Some(-1)); assert_eq!(Number::from(f64::NAN).as_fixed_point_i64(0), None); } #[test] fn convert_f64_precision() { assert_eq!(unsafe { Number::from_parts_unchecked(true, 4750000000000001, -18) }, 0.004750000000000001); } json-0.12.0/tests/parse.rs010064400017500001750000000155331347550352200136230ustar0000000000000000#[macro_use] extern crate json; use json::number::Number; use json::{ parse, JsonValue, Null }; #[test] fn parse_true() { assert_eq!(parse("true").unwrap(), true); } #[test] fn parse_false() { assert_eq!(parse("false").unwrap(), false); } #[test] fn parse_null() { assert!(parse("null").unwrap().is_null()); } #[test] fn parse_number() { assert_eq!(parse("3.141592653589793").unwrap(), 3.141592653589793); } #[test] fn uncode_identifier() { assert!(parse("[C3A9] <=> [é]").is_err()); } #[test] fn parse_period_requires_digit() { assert!(parse("[1.]").is_err()); } #[test] fn parse_small_number() { assert_eq!(parse("0.05").unwrap(), 0.05); } #[test] fn parse_very_long_float() { let parsed = parse("2.22507385850720113605740979670913197593481954635164564e-308").unwrap(); // Handles convertion correctly assert_eq!(parsed.as_f64().unwrap(), 2.225073858507201e-308); // Exhausts u64 assert_eq!(parsed, unsafe { Number::from_parts_unchecked(true, 2225073858507201136, -326) }); } #[test] fn parse_very_long_exponent() { let parsed = parse("1e999999999999999999999999999999999999999999999999999999999999").unwrap(); assert_eq!(parsed, unsafe { Number::from_parts_unchecked(true, 1, 32767) }); } #[test] fn parse_integer() { assert_eq!(parse("42").unwrap(), 42); } #[test] fn parse_negative_zero() { assert_eq!(parse("-0").unwrap(), JsonValue::from(-0f64)); } #[test] fn parse_negative_integer() { assert_eq!(parse("-42").unwrap(), -42); } #[test] fn parse_number_with_leading_zero() { assert!(parse("01").is_err()); } #[test] fn parse_negative_number_with_leading_zero() { assert!(parse("-01").is_err()); } #[test] fn parse_number_with_e() { assert_eq!(parse("5e2").unwrap(), 500); assert_eq!(parse("5E2").unwrap(), 500); } #[test] fn parse_number_with_positive_e() { assert_eq!(parse("5e+2").unwrap(), 500); assert_eq!(parse("5E+2").unwrap(), 500); } #[test] fn parse_number_with_negative_e() { assert_eq!(parse("5e-2").unwrap(), 0.05); assert_eq!(parse("5E-2").unwrap(), 0.05); } #[test] fn parse_number_with_invalid_e() { assert!(parse("0e").is_err()); } #[test] fn parse_large_number() { assert_eq!(parse("18446744073709551616").unwrap(), 18446744073709552000f64); } #[test] fn parse_array() { assert_eq!(parse(r#"[10, "foo", true, null]"#).unwrap(), array![ 10, "foo", true, Null ]); assert_eq!(parse("[]").unwrap(), array![]); assert_eq!(parse("[[]]").unwrap(), array![array![]]); } #[test] fn parse_object() { // Without trailing comma assert_eq!(parse(r#" { "foo": "bar", "num": 10 } "#).unwrap(), object!{ "foo" => "bar", "num" => 10 }); // Trailing comma in macro assert_eq!(parse(r#" { "foo": "bar", "num": 10 } "#).unwrap(), object!{ "foo" => "bar", "num" => 10, }); } #[test] fn parse_object_duplicate_fields() { assert_eq!(parse(r#" { "foo": 0, "bar": 1, "foo": 2 } "#).unwrap(), object!{ "foo" => 2, "bar" => 1 }); } #[test] fn parse_object_with_array(){ assert_eq!(parse(r#" { "foo": [1, 2, 3] } "#).unwrap(), object!{ "foo" => array![1, 2, 3] }); } #[test] fn parse_nested_object() { assert_eq!(parse(r#" { "l10n": [ { "product": { "inStock": { "DE": "Lieferung innerhalb von 1-3 Werktagen" } } } ] } "#).unwrap(), object!{ "l10n" => array![ object!{ "product" => object!{ "inStock" => object!{ "DE" => "Lieferung innerhalb von 1-3 Werktagen" } } } ] }); } #[test] fn parse_and_index_from_object() { let data = parse("{ \"pi\": 3.14 }").unwrap(); let ref pi = data["pi"]; assert_eq!(pi, 3.14); } #[test] fn parse_and_index_mut_from_object() { let mut data = parse(r#" { "foo": 100 } "#).unwrap(); assert_eq!(data["foo"], 100); data["foo"] = 200.into(); assert_eq!(data["foo"], 200); } #[test] fn parse_and_index_mut_from_null() { let mut data = parse("null").unwrap(); assert!(data["foo"]["bar"].is_null()); // test that data didn't coerece to object assert!(data.is_null()); data["foo"]["bar"] = 100.into(); assert!(data.is_object()); assert_eq!(data["foo"]["bar"], 100); assert_eq!(data.dump(), r#"{"foo":{"bar":100}}"#); } #[test] fn parse_and_index_from_array() { let data = parse(r#"[100, 200, false, null, "foo"]"#).unwrap(); assert_eq!(data[0], Number::from(100)); assert_eq!(data[1], 200); assert_eq!(data[2], false); assert_eq!(data[3], Null); assert_eq!(data[4], "foo"); assert_eq!(data[5], Null); } #[test] fn parse_and_index_mut_from_array() { let mut data = parse(r#"[100, 200, false, null, "foo"]"#).unwrap(); assert!(data[3].is_null()); assert!(data[5].is_null()); data[3] = "modified".into(); data[5] = "implicid push".into(); assert_eq!(data[3], "modified"); assert_eq!(data[5], "implicid push"); } #[test] fn parse_escaped_characters() { let data = parse(r#" "\r\n\t\b\f\\\/\"" "#).unwrap(); assert!(data.is_string()); assert_eq!(data, "\r\n\t\u{8}\u{c}\\/\""); } #[test] fn parse_escaped_unicode() { let data = parse(r#" "\u2764\ufe0f" "#).unwrap(); assert_eq!(data, "❤️"); } #[test] fn parse_escaped_unicode_surrogate() { let data = parse(r#" "\uD834\uDD1E" "#).unwrap(); assert_eq!(data, "𝄞"); } #[test] fn parse_escaped_unicode_surrogate_fail() { let err = parse(r#" "\uD834 \uDD1E" "#); assert!(err.is_err()); } #[test] fn parse_deeply_nested_arrays_and_objects() { let depth = 256; let mut text = String::new(); for _ in 0..depth { text.push_str("[{\"a\":"); } text.push_str("null"); for _ in 0..depth { text.push_str("}]"); } parse(&text).unwrap(); assert!(true); } #[test] fn parse_error_after_depth_limit() { let depth = 5000; let mut text = String::new(); for _ in 0..depth { text.push_str("[{\"a\":"); } text.push_str("null"); for _ in 0..depth { text.push_str("}]"); } assert_eq!(parse(&text), Err(json::Error::ExceededDepthLimit)); } #[test] fn does_not_panic_on_single_unicode_char() { let bytes = vec![0xC3, 0xA5]; let string = String::from_utf8(bytes).unwrap(); assert!(parse(&string).is_err()); } #[test] fn does_not_panic_on_single_zero() { let source = "0"; parse(source).unwrap(); } #[test] fn does_not_panic_on_huge_numbers() { let mut string = String::from("8"); for _ in 1..32787 { string.push('0'); } let _ = json::parse(&string); } json-0.12.0/tests/print_dec.rs010064400017500001750000000017061347550352200144550ustar0000000000000000extern crate json; use json::number::Number; #[test] fn issue_107() { let n = unsafe { Number::from_parts_unchecked(true, 1, -32768) }; assert_eq!(format!("{}", n), "1e-32768"); } #[test] fn issue_108_exponent_positive() { let n = unsafe { Number::from_parts_unchecked(true, 10_000_000_000_000_000_001, -18) }; assert_eq!(format!("{}", n), "1.0000000000000000001e+1"); } #[test] fn issue_108_exponent_0() { let n = unsafe { Number::from_parts_unchecked(true, 10_000_000_000_000_000_001, -19) }; assert_eq!(format!("{}", n), "1.0000000000000000001"); } #[test] fn trailing_zeroes_int() { let n = Number::from_parts(true, 100, -1); assert_eq!(format!("{}", n), "10"); } #[test] fn trailing_zeroes_fp() { let n = Number::from_parts(true, 100, -3); assert_eq!(format!("{}", n), "0.1"); } #[test] fn trailing_zeroes_small_fp() { let n = Number::from_parts(true, 100, -302); assert_eq!(format!("{}", n), "1e-300"); } json-0.12.0/tests/stringify.rs010064400017500001750000000130541353447706100145270ustar0000000000000000#[macro_use] extern crate json; use std::collections::{ HashMap, BTreeMap }; use std::f64; use json::{ parse, stringify, stringify_pretty, JsonValue, Null }; #[test] fn stringify_null() { assert_eq!(stringify(Null), "null"); } #[test] fn stringify_option_none() { let foo: Option = None; assert_eq!(stringify(foo), "null"); } #[test] fn stringify_option_integer() { let foo = Some(100); assert_eq!(stringify(foo), "100"); } #[test] fn stringify_str_slice() { assert_eq!(stringify("Foo"), "\"Foo\""); } #[test] fn stringify_string() { assert_eq!(stringify("Foo".to_string()), "\"Foo\""); } #[test] fn stringify_number() { assert_eq!(stringify(3.141592653589793), "3.141592653589793"); } #[test] fn stringify_precise_positive_number() { assert_eq!(JsonValue::from(1.2345f64).dump(), "1.2345"); } #[test] fn stringify_precise_negative_number() { assert_eq!(JsonValue::from(-1.2345f64).dump(), "-1.2345"); } #[test] fn stringify_zero() { assert_eq!(JsonValue::from(0.0).dump(), "0"); } #[test] fn stringify_nan() { assert_eq!(JsonValue::from(f64::NAN).dump(), "null"); } #[test] fn stringify_infinity() { assert_eq!(JsonValue::from(f64::INFINITY).dump(), "null"); assert_eq!(JsonValue::from(f64::NEG_INFINITY).dump(), "null"); } #[test] fn stringify_negative_zero() { assert_eq!(JsonValue::from(-0f64).dump(), "-0"); } #[test] fn stringify_integer() { assert_eq!(stringify(42), "42"); } #[test] fn stringify_small_number() { assert_eq!(stringify(0.0001), "0.0001"); } #[test] fn stringify_large_number() { assert_eq!(stringify(1e19), "10000000000000000000"); } #[test] fn stringify_very_large_number() { assert_eq!(stringify(3.141592653589793e50), "3.141592653589793e50"); } #[test] fn stringify_very_large_number_no_fraction() { assert_eq!(stringify(7e70), "7e70"); } #[test] fn stringify_very_small_number() { assert_eq!(stringify(3.141592653589793e-16), "3.141592653589793e-16"); } #[test] fn stringify_true() { assert_eq!(stringify(true), "true"); } #[test] fn stringify_false() { assert_eq!(stringify(false), "false"); } #[test] fn stringify_array() { assert_eq!(stringify(array![10, false, Null]), "[10,false,null]"); } #[test] fn stringify_vec() { let mut array: Vec = Vec::new(); array.push(10.into()); array.push("Foo".into()); assert_eq!(stringify(array), r#"[10,"Foo"]"#); } #[test] fn stringify_typed_vec() { let array = vec![1, 2, 3]; assert_eq!(stringify(array), "[1,2,3]"); } #[test] fn stringify_typed_opt_vec() { let array = vec![Some(1), None, Some(2), None, Some(3)]; assert_eq!(stringify(array), "[1,null,2,null,3]"); } #[test] fn stringify_object() { let object = object!{ "name" => "Maciej", "age" => 30 }; assert_eq!(object.dump(), r#"{"name":"Maciej","age":30}"#); assert_eq!(stringify(object), r#"{"name":"Maciej","age":30}"#); } #[test] fn stringify_raw_object() { let mut object = json::object::Object::new(); object.insert("name", "Maciej".into()); object.insert("age", 30.into()); assert_eq!(object.dump(), r#"{"name":"Maciej","age":30}"#); assert_eq!(stringify(object), r#"{"name":"Maciej","age":30}"#); } #[test] fn stringify_btree_map() { let mut map = BTreeMap::new(); map.insert("name", JsonValue::from("Maciej")); map.insert("age", JsonValue::from(30)); // BTreeMap will sort keys assert_eq!(stringify(map), r#"{"age":30,"name":"Maciej"}"#); } #[test] fn stringify_hash_map() { let mut map = HashMap::new(); map.insert("name", JsonValue::from("Maciej")); map.insert("age", JsonValue::from(30)); // HashMap does not sort keys, but depending on hashing used the // order can be different. Safe bet is to parse the result and // compare parsed objects. let parsed = parse(&stringify(map)).unwrap(); assert_eq!(parsed, object!{ "name" => "Maciej", "age" => 30 }); } #[test] fn stringify_object_with_put() { let mut object = JsonValue::new_object(); object["a"] = 100.into(); object["b"] = false.into(); assert_eq!(object.dump(), r#"{"a":100,"b":false}"#); assert_eq!(stringify(object), r#"{"a":100,"b":false}"#); } #[test] fn stringify_array_with_push() { let mut array = JsonValue::new_array(); array.push(100).unwrap(); array.push(Null).unwrap(); array.push(false).unwrap(); array.push(Some("foo".to_string())).unwrap(); assert_eq!(stringify(array), "[100,null,false,\"foo\"]"); } #[test] fn stringify_escaped_characters() { assert_eq!(stringify("\r____\n___\t\u{8}\u{c}\\\"__"), r#""\r____\n___\t\b\f\\\"__""#); } #[test] fn stringify_dont_escape_forward_slash() { assert_eq!(stringify("foo/bar"), r#""foo/bar""#); } #[test] fn stringify_escaped() { assert_eq!(stringify("http://www.google.com/\t"), r#""http://www.google.com/\t""#); } #[test] fn stringify_control_escaped() { assert_eq!(stringify("foo\u{1f}bar\u{0}baz"), r#""foo\u001fbar\u0000baz""#); } #[test] fn stringify_pretty_object() { let object = object!{ "name" => "Urlich", "age" => 50, "parents" => object!{ "mother" => "Helga", "father" => "Brutus" }, "cars" => array![ "Golf", "Mercedes", "Porsche" ] }; let expected = "{\n \"name\": \"Urlich\",\n \"age\": 50,\n \"parents\": {\n \"mother\": \"Helga\",\n \"father\": \"Brutus\"\n },\n \"cars\": [\n \"Golf\",\n \"Mercedes\",\n \"Porsche\"\n ]\n}"; assert_eq!(object.pretty(2), expected); assert_eq!(stringify_pretty(object, 2), expected); } json-0.12.0/tests/value.rs010064400017500001750000000336631347550352200136310ustar0000000000000000#[macro_use] extern crate json; use json::{ parse, JsonValue, JsonError, Null }; #[test] fn is_as_string() { let string = JsonValue::from("foo"); assert!(string.is_string()); assert_eq!(string.as_str().unwrap(), "foo"); } #[test] fn is_as_number() { let number = JsonValue::from(42); assert!(number.is_number()); assert_eq!(number.as_f64().unwrap(), 42.0f64); assert_eq!(number.as_f32().unwrap(), 42.0f32); assert_eq!(number.as_u64().unwrap(), 42u64); assert_eq!(number.as_u32().unwrap(), 42u32); assert_eq!(number.as_u16().unwrap(), 42u16); assert_eq!(number.as_u8().unwrap(), 42u8); assert_eq!(number.as_usize().unwrap(), 42usize); assert_eq!(number.as_i64().unwrap(), 42i64); assert_eq!(number.as_i32().unwrap(), 42i32); assert_eq!(number.as_i16().unwrap(), 42i16); assert_eq!(number.as_i8().unwrap(), 42i8); assert_eq!(number.as_isize().unwrap(), 42isize); let number = JsonValue::from(-1); assert_eq!(number.as_u64(), None); assert_eq!(number.as_u32(), None); assert_eq!(number.as_u16(), None); assert_eq!(number.as_u8(), None); assert_eq!(number.as_usize(), None); assert_eq!(number.as_i64(), Some(-1)); assert_eq!(number.as_i32(), Some(-1)); assert_eq!(number.as_i16(), Some(-1)); assert_eq!(number.as_i8(), Some(-1)); assert_eq!(number.as_isize(), Some(-1)); let number = JsonValue::from(40_000); assert_eq!(number.as_u8(), None); assert_eq!(number.as_u16(), Some(40_000)); assert_eq!(number.as_i8(), None); assert_eq!(number.as_i16(), None); assert_eq!(number.as_i32(), Some(40_000)); } #[test] fn as_fixed_point() { let number = JsonValue::from(3.14); assert_eq!(number.as_fixed_point_u64(4).unwrap(), 31400_u64); assert_eq!(number.as_fixed_point_u64(2).unwrap(), 314_u64); assert_eq!(number.as_fixed_point_u64(0).unwrap(), 3_u64); assert_eq!(number.as_fixed_point_i64(4).unwrap(), 31400_i64); assert_eq!(number.as_fixed_point_i64(2).unwrap(), 314_i64); assert_eq!(number.as_fixed_point_i64(0).unwrap(), 3_i64); let number = JsonValue::from(-3.14); assert_eq!(number.as_fixed_point_u64(4), None); assert_eq!(number.as_fixed_point_u64(2), None); assert_eq!(number.as_fixed_point_u64(0), None); assert_eq!(number.as_fixed_point_i64(4).unwrap(), -31400_i64); assert_eq!(number.as_fixed_point_i64(2).unwrap(), -314_i64); assert_eq!(number.as_fixed_point_i64(0).unwrap(), -3_i64); } #[test] fn is_as_boolean() { let boolean = JsonValue::Boolean(true); assert!(boolean.is_boolean()); assert_eq!(boolean.as_bool().unwrap(), true); } #[test] fn is_true() { let boolean = JsonValue::Boolean(true); assert_eq!(boolean, true); } #[test] fn is_false() { let boolean = JsonValue::Boolean(false); assert_eq!(boolean, false); } #[test] fn is_null() { let null = JsonValue::Null; assert!(null.is_null()); } #[test] fn is_empty() { assert!(Null.is_empty()); assert!(json::from(0).is_empty()); assert!(json::from("").is_empty()); assert!(json::from(false).is_empty()); assert!(array![].is_empty()); assert!(object!{}.is_empty()); assert!(!json::from(1).is_empty()); assert!(!json::from("foo").is_empty()); assert!(!json::from(true).is_empty()); assert!(!array![0].is_empty()); assert!(!object!{ "foo" => false }.is_empty()); } #[test] fn array_len() { let data = array![0, 1, 2, 3]; assert_eq!(data.len(), 4); } #[test] fn array_contains() { let data = array![true, Null, 3.14, "foo"]; assert!(data.contains(true)); assert!(data.contains(Null)); assert!(data.contains(3.14)); assert!(data.contains("foo")); assert!(!data.contains(false)); assert!(!data.contains(42)); assert!(!data.contains("bar")); } #[test] fn array_push() { let mut data = array![1, 2]; data.push(3).unwrap(); assert_eq!(data, array![1, 2, 3]); } #[test] fn array_pop() { let mut data = array![1, 2, 3]; assert_eq!(data.pop(), 3); assert_eq!(data, array![1, 2]); } #[test] fn array_remove() { let mut data = array![1, 2, 3]; assert_eq!(data.array_remove(1), 2); assert_eq!(data, array![1, 3]); // Test with index out of bounds assert_eq!(data.array_remove(2), JsonValue::Null); } #[test] fn array_members() { let data = array![1, "foo"]; for member in data.members() { assert!(!member.is_null()); } let mut members = data.members(); assert_eq!(members.next().unwrap(), 1); assert_eq!(members.next().unwrap(), "foo"); assert!(members.next().is_none()); } #[test] fn array_members_rev() { let data = array![1, "foo"]; for member in data.members() { assert!(!member.is_null()); } let mut members = data.members().rev(); assert_eq!(members.next().unwrap(), "foo"); assert_eq!(members.next().unwrap(), 1); assert!(members.next().is_none()); } #[test] fn array_members_mut() { let mut data = array![Null, Null]; for member in data.members_mut() { assert!(member.is_null()); *member = 100.into(); } assert_eq!(data, array![100, 100]); } #[test] fn array_members_mut_rev() { let mut data = array![Null, Null]; let mut item = 100; for member in data.members_mut().rev() { assert!(member.is_null()); *member = item.into(); item += 1; } assert_eq!(data, array![item - 1, item - 2]); } #[test] fn object_len() { let data = object!{ "a" => true, "b" => false }; assert_eq!(data.len(), 2); } #[test] fn object_remove() { let mut data = object!{ "foo" => "bar", "answer" => 42 }; assert_eq!(data.remove("foo"), "bar"); assert_eq!(data, object!{ "answer" => 42 }); } #[test] fn object_entries() { let data = object!{ "a" => 1, "b" => "foo" }; for (_, value) in data.entries() { assert!(!value.is_null()); } let mut entries = data.entries(); let (key, value) = entries.next().unwrap(); assert_eq!(key, "a"); assert_eq!(value, 1); let (key, value) = entries.next().unwrap(); assert_eq!(key, "b"); assert_eq!(value, "foo"); assert!(entries.next().is_none()); } #[test] fn object_entries_rev() { let data = object!{ "a" => 1, "b" => "foo" }; for (_, value) in data.entries().rev() { assert!(!value.is_null()); } let mut entries = data.entries().rev(); let (key, value) = entries.next().unwrap(); assert_eq!(key, "b"); assert_eq!(value, "foo"); let (key, value) = entries.next().unwrap(); assert_eq!(key, "a"); assert_eq!(value, 1); assert!(entries.next().is_none()); } #[test] fn object_entries_mut() { let mut data = object!{ "a" => Null, "b" => Null }; for (_, value) in data.entries_mut() { assert!(value.is_null()); *value = 100.into(); } assert_eq!(data, object!{ "a" => 100, "b" => 100 }); } #[test] fn object_entries_mut_rev() { let mut data = object!{ "a" => Null, "b" => Null }; let mut item = 100; for (_, value) in data.entries_mut().rev() { assert!(value.is_null()); *value = item.into(); item += 1; } assert_eq!(data, object!{ "a" => item - 1, "b" => item - 2 }); } #[test] fn object_dump_minified() { let object = object!{ "name" => "Maciej", "age" => 30 }; assert_eq!(object.dump(), "{\"name\":\"Maciej\",\"age\":30}"); } #[test] fn object_dump_pretty() { let object = object!{ "name" => "Urlich", "age" => 50, "parents" => object!{ "mother" => "Helga", "father" => "Brutus" }, "cars" => array![ "Golf", "Mercedes", "Porsche" ] }; assert_eq!(object.pretty(2), "{\n \"name\": \"Urlich\",\n \"age\": 50,\n \"parents\": {\n \"mother\": \"Helga\",\n \"father\": \"Brutus\"\n },\n \"cars\": [\n \"Golf\",\n \"Mercedes\",\n \"Porsche\"\n ]\n}"); } #[test] fn null_len() { let data = json::Null; assert_eq!(data.len(), 0); } #[test] fn index_by_str() { let data = object!{ "foo" => "bar" }; assert_eq!(data["foo"], "bar"); } #[test] fn index_by_string() { let data = object!{ "foo" => "bar" }; assert_eq!(data["foo".to_string()], "bar"); } #[test] fn index_by_string_ref() { let data = object!{ "foo" => "bar" }; let key = "foo".to_string(); let ref key_ref = key; assert_eq!(data[key_ref], "bar"); } #[test] fn index_mut_by_str() { let mut data = object!{ "foo" => Null }; data["foo"] = "bar".into(); assert_eq!(data["foo"], "bar"); } #[test] fn index_mut_by_string() { let mut data = object!{ "foo" => Null }; data["foo".to_string()] = "bar".into(); assert_eq!(data["foo"], "bar"); } #[test] fn index_mut_by_string_ref() { let mut data = object!{ "foo" => Null }; let key = "foo".to_string(); let ref key_ref = key; data[key_ref] = "bar".into(); assert_eq!(data["foo"], "bar"); } #[test] fn object_index_by_str() { let val = object!{ "foo" => "bar" }; if let JsonValue::Object(data) = val { assert_eq!(data["foo"], "bar"); } } #[test] fn object_index_by_string() { let val = object!{ "foo" => "bar" }; if let JsonValue::Object(data) = val { assert_eq!(data["foo".to_string()], "bar"); } } #[test] fn object_index_by_string_ref() { let val = object!{ "foo" => "bar" }; let key = "foo".to_string(); let ref key_ref = key; if let JsonValue::Object(data) = val { assert_eq!(data[key_ref], "bar"); } } #[test] fn object_index_mut_by_str() { let val = object!{ "foo" => Null }; if let JsonValue::Object(mut data) = val { data["foo"] = "bar".into(); assert_eq!(data["foo"], "bar"); } } #[test] fn object_index_mut_by_string() { let val = object!{ "foo" => Null }; if let JsonValue::Object(mut data) = val { data["foo".to_string()] = "bar".into(); assert_eq!(data["foo"], "bar"); } } #[test] fn object_index_mut_by_string_ref() { let val = object!{ "foo" => Null }; let key = "foo".to_string(); let ref key_ref = key; if let JsonValue::Object(mut data) = val { data[key_ref] = "bar".into(); assert_eq!(data["foo"], "bar"); } } #[test] fn fmt_string() { let data: JsonValue = "foobar".into(); assert_eq!(format!("{}", data), "foobar"); assert_eq!(format!("{:#}", data), r#""foobar""#); } #[test] fn fmt_number() { let data: JsonValue = 42.into(); assert_eq!(format!("{}", data), "42"); assert_eq!(format!("{:#}", data), "42"); } #[test] fn fmt_boolean() { let data: JsonValue = true.into(); assert_eq!(format!("{}", data), "true"); assert_eq!(format!("{:#}", data), "true"); } #[test] fn fmt_null() { let data = Null; assert_eq!(format!("{}", data), "null"); assert_eq!(format!("{:#}", data), "null"); } #[test] fn fmt_array() { let data = array![1, true, "three"]; assert_eq!(format!("{}", data), r#"[1,true,"three"]"#); assert_eq!(format!("{:#}", data), "[\n 1,\n true,\n \"three\"\n]"); } #[test] fn fmt_object() { let data = object!{ "foo" => "bar", "answer" => 42 }; assert_eq!(format!("{}", data), r#"{"foo":"bar","answer":42}"#); assert_eq!(format!("{:#}", data), "{\n \"foo\": \"bar\",\n \"answer\": 42\n}"); } #[test] fn error_unexpected_character() { let err = parse("\n\nnulX\n").unwrap_err(); assert_eq!(err, JsonError::UnexpectedCharacter { ch: 'X', line: 3, column: 4, }); assert_eq!(format!("{}", err), "Unexpected character: X at (3:4)"); } #[test] fn error_unexpected_unicode_character() { let err = parse("\n\nnul🦄\n").unwrap_err(); assert_eq!(err, JsonError::UnexpectedCharacter { ch: '🦄', line: 3, column: 4, }); assert_eq!(format!("{}", err), "Unexpected character: 🦄 at (3:4)"); } #[test] fn error_unexpected_token() { let err = parse("\n [\n null,\n ] \n").unwrap_err(); assert_eq!(err, JsonError::UnexpectedCharacter { ch: ']', line: 4, column: 3, }); assert_eq!(format!("{}", err), "Unexpected character: ] at (4:3)"); } #[test] fn writer_generator() { let data = object!{ "foo" => array!["bar", 100, true] }; let mut buf = Vec::new(); data.write(&mut buf).expect("Can't fail with a Vec"); assert_eq!(String::from_utf8(buf).unwrap(), r#"{"foo":["bar",100,true]}"#); } #[test] fn pretty_writer_generator() { let data = object!{ "foo" => array!["bar", 100, true] }; let mut buf = Vec::new(); data.write_pretty(&mut buf, 4).expect("Can't fail with a Vec"); assert_eq!(String::from_utf8(buf).unwrap(), "{\n \"foo\": [\n \"bar\",\n 100,\n true\n ]\n}"); } #[test] fn equality() { let left = object!{ "foo" => array!["bar", 100, true] }; let left_copy = object!{ "foo" => array!["bar", 100, true] }; let left_string = object!{ "foo" => array![JsonValue::String("bar".to_string()), 100, true] }; let left_short = object!{ "foo" => array![JsonValue::Short(unsafe { json::short::Short::from_slice("bar") }), 100, true] }; let change_bool = object!{ "foo" => array!["bar", 100, false] }; let change_string = object!{ "foo" => array![JsonValue::String("sna".to_string()), 100, true] }; let change_short = object!{ "foo" => array![JsonValue::Short(unsafe { json::short::Short::from_slice("sna") }), 100, true] }; assert_eq!(left, left_copy); assert_eq!(left, left_string); assert_eq!(left, left_short); assert_ne!(left, change_bool); assert_ne!(left, change_string); assert_ne!(left, change_short); } json-0.12.0/.cargo_vcs_info.json0000644000000001120000000000000121160ustar00{ "git": { "sha1": "2a5727320e797019e7c6a89ebad870968285a5d1" } }