diff options
35 files changed, 624 insertions, 662 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 55d7152..37acde7 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "7025523603fe604d11b92ccd4ca314e343d3ae50" + "sha1": "26f147fde7ce6441f7db978131150605c5500c28" }, "path_in_vcs": "" }
\ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7e82ab..411aa42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: pull_request: schedule: [cron: "40 1 * * *"] +permissions: + contents: read + env: RUSTFLAGS: -Dwarnings @@ -16,8 +19,9 @@ jobs: fail-fast: false matrix: os: [ubuntu, windows] + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - run: cargo test - run: cargo test --features preserve_order --tests -- --skip ui --exact @@ -33,47 +37,46 @@ jobs: strategy: fail-fast: false matrix: - rust: [beta, stable, 1.53.0, 1.46.0, 1.45.0, 1.40.0, 1.38.0, 1.36.0] + rust: [beta, 1.56.1, 1.53.0, 1.46.0, 1.40.0, 1.38.0, 1.36.0] os: [ubuntu] include: - rust: stable + os: ubuntu + target: aarch64-unknown-none + - rust: stable os: windows + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} + targets: ${{matrix.target}} - run: cargo check - run: cargo check --features float_roundtrip - run: cargo check --features arbitrary_precision - run: cargo check --features raw_value - run: cargo check --features unbounded_depth - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc + - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,arbitrary_precision - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,raw_value - run: cargo check --features preserve_order - if: matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0' + if: matrix.rust != '1.53.0' && matrix.rust != '1.46.0' && matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0' - run: cargo check --manifest-path tests/crate/Cargo.toml --no-default-features --features alloc,preserve_order - if: matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0' + if: matrix.rust != '1.53.0' && matrix.rust != '1.46.0' && matrix.rust != '1.45.0' && matrix.rust != '1.40.0' && matrix.rust != '1.38.0' && matrix.rust != '1.36.0' - name: Build without std - run: | - rustup target add aarch64-unknown-none - cargo check \ - --manifest-path tests/crate/Cargo.toml \ - --target aarch64-unknown-none \ - --no-default-features \ - --features alloc - if: matrix.rust == 'stable' && matrix.os == 'ubuntu' + run: cargo check --manifest-path tests/crate/Cargo.toml --target ${{matrix.target}} --no-default-features --features alloc + if: matrix.target miri: name: Miri runs-on: ubuntu-latest env: - MIRIFLAGS: "-Zmiri-tag-raw-pointers" + MIRIFLAGS: -Zmiri-strict-provenance + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@nightly - with: - components: miri + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@miri - run: cargo miri test - run: cargo miri test --features preserve_order,float_roundtrip,arbitrary_precision,raw_value @@ -81,8 +84,9 @@ jobs: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@clippy - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic - run: cargo clippy --all-features --tests -- -Dclippy::all -Dclippy::pedantic @@ -90,8 +94,9 @@ jobs: docs: name: Documentation runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - run: cargo doc --features raw_value,unbounded_depth env: @@ -100,8 +105,20 @@ jobs: fuzz: name: Fuzz runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - - run: cargo install cargo-fuzz --debug + - uses: dtolnay/install@cargo-fuzz - run: cargo fuzz build -O + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 + - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 @@ -43,7 +43,7 @@ rust_library { host_supported: true, crate_name: "serde_json", cargo_env_compat: true, - cargo_pkg_version: "1.0.79", + cargo_pkg_version: "1.0.91", srcs: ["src/lib.rs"], edition: "2018", features: [ @@ -13,7 +13,7 @@ edition = "2018" rust-version = "1.36" name = "serde_json" -version = "1.0.79" +version = "1.0.91" authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>", @@ -26,7 +26,11 @@ keywords = [ "serde", "serialization", ] -categories = ["encoding"] +categories = [ + "encoding", + "parser-implementations", + "no-std", +] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/json" @@ -44,8 +48,12 @@ rustdoc-args = [ [package.metadata.playground] features = ["raw_value"] +[lib] +doc-scrape-examples = false + [dependencies.indexmap] -version = "1.5" +version = "1.5.2" +features = ["std"] optional = true [dependencies.itoa] @@ -61,12 +69,19 @@ default-features = false [dev-dependencies.automod] version = "1.0" +[dev-dependencies.indoc] +version = "1.0" + [dev-dependencies.ref-cast] version = "1.0" [dev-dependencies.rustversion] version = "1.0" +[dev-dependencies.serde] +version = "1.0.100" +features = ["derive"] + [dev-dependencies.serde_bytes] version = "0.11" @@ -85,7 +100,10 @@ alloc = ["serde/alloc"] arbitrary_precision = [] default = ["std"] float_roundtrip = [] -preserve_order = ["indexmap"] +preserve_order = [ + "indexmap", + "std", +] raw_value = [] std = ["serde/std"] unbounded_depth = [] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 1513e9b..2feb6dd 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,27 +1,28 @@ [package] name = "serde_json" -version = "1.0.79" # remember to update html_root_url +version = "1.0.91" # remember to update html_root_url authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] -license = "MIT OR Apache-2.0" +categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" -repository = "https://github.com/serde-rs/json" documentation = "https://docs.serde.rs/serde_json/" -keywords = ["json", "serde", "serialization"] -categories = ["encoding"] -readme = "README.md" edition = "2018" +keywords = ["json", "serde", "serialization"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/serde-rs/json" rust-version = "1.36" [dependencies] serde = { version = "1.0.100", default-features = false } -indexmap = { version = "1.5", optional = true } +indexmap = { version = "1.5.2", features = ["std"], optional = true } itoa = "1.0" ryu = "1.0" [dev-dependencies] automod = "1.0" +indoc = "1.0" ref-cast = "1.0" rustversion = "1.0" +serde = { version = "1.0.100", features = ["derive"] } serde_bytes = "0.11" serde_derive = "1.0" serde_stacker = "0.1" @@ -30,6 +31,9 @@ trybuild = { version = "1.0.49", features = ["diff"] } [workspace] members = ["tests/crate"] +[lib] +doc-scrape-examples = false + [package.metadata.docs.rs] features = ["raw_value", "unbounded_depth"] targets = ["x86_64-unknown-linux-gnu"] @@ -49,13 +53,12 @@ std = ["serde/std"] # Provide integration for heap-allocated collections without depending on the # rest of the Rust standard library. # NOTE: Disabling both `std` *and* `alloc` features is not supported yet. -# Available on Rust 1.36+. alloc = ["serde/alloc"] # Make serde_json::Map use a representation which maintains insertion order. # This allows data to be read into a Value and written back to a JSON string # while preserving the order of map keys in the input. -preserve_order = ["indexmap"] +preserve_order = ["indexmap", "std"] # Use sufficient precision when parsing fixed precision floats from JSON to # ensure that they maintain accuracy when round-tripped through JSON. This comes @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/serde_json +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "serde_json" description: "A JSON serialization file format" third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/serde_json/serde_json-1.0.79.crate" + value: "https://static.crates.io/crates/serde_json/serde_json-1.0.91.crate" } - version: "1.0.79" + version: "1.0.91" license_type: NOTICE last_upgrade_date { year: 2022 - month: 3 - day: 1 + month: 12 + day: 19 } } @@ -1,7 +1,7 @@ -# Serde JSON   [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.36+]][rustc] +# Serde JSON   [![Build Status]][actions] [![Latest Version]][crates.io] [![Rustc Version 1.36+]][rustc] -[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/json/CI/master -[travis]: https://github.com/serde-rs/json/actions?query=branch%3Amaster +[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/json/ci.yml?branch=master +[actions]: https://github.com/serde-rs/json/actions?query=branch%3Amaster [Latest Version]: https://img.shields.io/crates/v/serde_json.svg [crates.io]: https://crates.io/crates/serde\_json [Rustc Version 1.36+]: https://img.shields.io/badge/rustc-1.36+-lightgray.svg @@ -42,22 +42,21 @@ transmit data objects consisting of key-value pairs. } ``` -There are three common ways that you might find yourself needing to work -with JSON data in Rust. +There are three common ways that you might find yourself needing to work with +JSON data in Rust. - - **As text data.** An unprocessed string of JSON data that you receive on - an HTTP endpoint, read from a file, or prepare to send to a remote - server. - - **As an untyped or loosely typed representation.** Maybe you want to - check that some JSON data is valid before passing it on, but without - knowing the structure of what it contains. Or you want to do very basic - manipulations like insert a key in a particular spot. - - **As a strongly typed Rust data structure.** When you expect all or most - of your data to conform to a particular structure and want to get real - work done without JSON's loosey-goosey nature tripping you up. + - **As text data.** An unprocessed string of JSON data that you receive on an + HTTP endpoint, read from a file, or prepare to send to a remote server. + - **As an untyped or loosely typed representation.** Maybe you want to check + that some JSON data is valid before passing it on, but without knowing the + structure of what it contains. Or you want to do very basic manipulations + like insert a key in a particular spot. + - **As a strongly typed Rust data structure.** When you expect all or most of + your data to conform to a particular structure and want to get real work done + without JSON's loosey-goosey nature tripping you up. -Serde JSON provides efficient, flexible, safe ways of converting data -between each of these representations. +Serde JSON provides efficient, flexible, safe ways of converting data between +each of these representations. ## Operating on untyped JSON values @@ -78,8 +77,8 @@ enum Value { A string of JSON data can be parsed into a `serde_json::Value` by the [`serde_json::from_str`][from_str] function. There is also [`from_slice`][from_slice] for parsing from a byte slice &[u8] and -[`from_reader`][from_reader] for parsing from any `io::Read` like a File or -a TCP stream. +[`from_reader`][from_reader] for parsing from any `io::Read` like a File or a +TCP stream. <div align="right"> <a href="https://play.rust-lang.org/?edition=2018&gist=d69d8e3156d4bb81c4461b60b772ab72" target="_blank"> @@ -185,20 +184,20 @@ fn typed_example() -> Result<()> { This is the same `serde_json::from_str` function as before, but this time we assign the return value to a variable of type `Person` so Serde will automatically interpret the input data as a `Person` and produce informative -error messages if the layout does not conform to what a `Person` is expected -to look like. +error messages if the layout does not conform to what a `Person` is expected to +look like. -Any type that implements Serde's `Deserialize` trait can be deserialized -this way. This includes built-in Rust standard library types like `Vec<T>` -and `HashMap<K, V>`, as well as any structs or enums annotated with +Any type that implements Serde's `Deserialize` trait can be deserialized this +way. This includes built-in Rust standard library types like `Vec<T>` and +`HashMap<K, V>`, as well as any structs or enums annotated with `#[derive(Deserialize)]`. -Once we have `p` of type `Person`, our IDE and the Rust compiler can help us -use it correctly like they do for any other Rust code. The IDE can -autocomplete field names to prevent typos, which was impossible in the -`serde_json::Value` representation. And the Rust compiler can check that -when we write `p.phones[0]`, then `p.phones` is guaranteed to be a -`Vec<String>` so indexing into it makes sense and produces a `String`. +Once we have `p` of type `Person`, our IDE and the Rust compiler can help us use +it correctly like they do for any other Rust code. The IDE can autocomplete +field names to prevent typos, which was impossible in the `serde_json::Value` +representation. And the Rust compiler can check that when we write +`p.phones[0]`, then `p.phones` is guaranteed to be a `Vec<String>` so indexing +into it makes sense and produces a `String`. The necessary setup for using Serde's derive macros is explained on the *[Using derive]* page of the Serde site. @@ -237,13 +236,13 @@ fn main() { } ``` -The `Value::to_string()` function converts a `serde_json::Value` into a -`String` of JSON text. +The `Value::to_string()` function converts a `serde_json::Value` into a `String` +of JSON text. -One neat thing about the `json!` macro is that variables and expressions can -be interpolated directly into the JSON value as you are building it. Serde -will check at compile time that the value you are interpolating is able to -be represented as JSON. +One neat thing about the `json!` macro is that variables and expressions can be +interpolated directly into the JSON value as you are building it. Serde will +check at compile time that the value you are interpolating is able to be +represented as JSON. <div align="right"> <a href="https://play.rust-lang.org/?edition=2018&gist=f9101a6e61dfc9e02c6a67f315ed24f2" target="_blank"> @@ -265,10 +264,10 @@ let john = json!({ }); ``` -This is amazingly convenient but we have the problem we had before with -`Value` which is that the IDE and Rust compiler cannot help us if we get it -wrong. Serde JSON provides a better way of serializing strongly-typed data -structures into JSON text. +This is amazingly convenient, but we have the problem we had before with +`Value`: the IDE and Rust compiler cannot help us if we get it wrong. Serde JSON +provides a better way of serializing strongly-typed data structures into JSON +text. ## Creating JSON by serializing data structures @@ -311,10 +310,9 @@ fn print_an_address() -> Result<()> { } ``` -Any type that implements Serde's `Serialize` trait can be serialized this -way. This includes built-in Rust standard library types like `Vec<T>` and -`HashMap<K, V>`, as well as any structs or enums annotated with -`#[derive(Serialize)]`. +Any type that implements Serde's `Serialize` trait can be serialized this way. +This includes built-in Rust standard library types like `Vec<T>` and `HashMap<K, +V>`, as well as any structs or enums annotated with `#[derive(Serialize)]`. ## Performance @@ -328,16 +326,16 @@ Benchmarks live in the [serde-rs/json-benchmark] repo. ## Getting help -Serde is one of the most widely used Rust libraries so any place that Rustaceans -congregate will be able to help you out. For chat, consider trying the -[#rust-questions] or [#rust-beginners] channels of the unofficial community +Serde is one of the most widely used Rust libraries, so any place that +Rustaceans congregate will be able to help you out. For chat, consider trying +the [#rust-questions] or [#rust-beginners] channels of the unofficial community Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage] or [#beginners] channels of the official Rust Project Discord (invite: <https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust [Discourse forum][discourse]. It's acceptable to file a support issue in this -repo but they tend not to get as many eyes as any of the above and may get +repo, but they tend not to get as many eyes as any of the above and may get closed without a response after some time. [#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513 @@ -352,8 +350,8 @@ closed without a response after some time. ## No-std support As long as there is a memory allocator, it is possible to use serde_json without -the rest of the Rust standard library. This is supported on Rust 1.36+. Disable -the default "std" feature and enable the "alloc" feature: +the rest of the Rust standard library. Disable the default "std" feature and +enable the "alloc" feature: ```toml [dependencies] @@ -3,6 +3,8 @@ use std::process::Command; use std::str::{self, FromStr}; fn main() { + println!("cargo:rerun-if-changed=build.rs"); + // Decide ideal limb width for arithmetic in the float parser. Refer to // src/lexical/math.rs for where this has an effect. let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); @@ -14,7 +14,7 @@ use core::marker::PhantomData; use core::result; use core::str::FromStr; use serde::de::{self, Expected, Unexpected}; -use serde::{forward_to_deserialize_any, serde_if_integer128}; +use serde::forward_to_deserialize_any; #[cfg(feature = "arbitrary_precision")] use crate::number::NumberDeserializer; @@ -335,31 +335,25 @@ impl<'de, R: Read<'de>> Deserializer<R> { } } - serde_if_integer128! { - fn scan_integer128(&mut self, buf: &mut String) -> Result<()> { - match tri!(self.next_char_or_null()) { - b'0' => { - buf.push('0'); - // There can be only one leading '0'. - match tri!(self.peek_or_null()) { - b'0'..=b'9' => { - Err(self.peek_error(ErrorCode::InvalidNumber)) - } - _ => Ok(()), - } + fn scan_integer128(&mut self, buf: &mut String) -> Result<()> { + match tri!(self.next_char_or_null()) { + b'0' => { + buf.push('0'); + // There can be only one leading '0'. + match tri!(self.peek_or_null()) { + b'0'..=b'9' => Err(self.peek_error(ErrorCode::InvalidNumber)), + _ => Ok(()), } - c @ b'1'..=b'9' => { + } + c @ b'1'..=b'9' => { + buf.push(c as char); + while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) { + self.eat_char(); buf.push(c as char); - while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) { - self.eat_char(); - buf.push(c as char); - } - Ok(()) - } - _ => { - Err(self.error(ErrorCode::InvalidNumber)) } + Ok(()) } + _ => Err(self.error(ErrorCode::InvalidNumber)), } } @@ -457,30 +451,33 @@ impl<'de, R: Read<'de>> Deserializer<R> { &mut self, positive: bool, mut significand: u64, - mut exponent: i32, + exponent_before_decimal_point: i32, ) -> Result<f64> { self.eat_char(); + let mut exponent_after_decimal_point = 0; while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) { let digit = (c - b'0') as u64; if overflow!(significand * 10 + digit, u64::max_value()) { + let exponent = exponent_before_decimal_point + exponent_after_decimal_point; return self.parse_decimal_overflow(positive, significand, exponent); } self.eat_char(); significand = significand * 10 + digit; - exponent -= 1; + exponent_after_decimal_point -= 1; } // Error if there is not at least one digit after the decimal point. - if exponent == 0 { + if exponent_after_decimal_point == 0 { match tri!(self.peek()) { Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)), None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)), } } + let exponent = exponent_before_decimal_point + exponent_after_decimal_point; match tri!(self.peek_or_null()) { b'e' | b'E' => self.parse_exponent(positive, significand, exponent), _ => self.f64_from_parts(positive, significand, exponent), @@ -1437,67 +1434,65 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> { val } - serde_if_integer128! { - fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value> - where - V: de::Visitor<'de>, - { - let mut buf = String::new(); - - match tri!(self.parse_whitespace()) { - Some(b'-') => { - self.eat_char(); - buf.push('-'); - } - Some(_) => {} - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } - }; + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value> + where + V: de::Visitor<'de>, + { + let mut buf = String::new(); - tri!(self.scan_integer128(&mut buf)); + match tri!(self.parse_whitespace()) { + Some(b'-') => { + self.eat_char(); + buf.push('-'); + } + Some(_) => {} + None => { + return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); + } + }; - let value = match buf.parse() { - Ok(int) => visitor.visit_i128(int), - Err(_) => { - return Err(self.error(ErrorCode::NumberOutOfRange)); - } - }; + tri!(self.scan_integer128(&mut buf)); - match value { - Ok(value) => Ok(value), - Err(err) => Err(self.fix_position(err)), + let value = match buf.parse() { + Ok(int) => visitor.visit_i128(int), + Err(_) => { + return Err(self.error(ErrorCode::NumberOutOfRange)); } + }; + + match value { + Ok(value) => Ok(value), + Err(err) => Err(self.fix_position(err)), } + } - fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value> - where - V: de::Visitor<'de>, - { - match tri!(self.parse_whitespace()) { - Some(b'-') => { - return Err(self.peek_error(ErrorCode::NumberOutOfRange)); - } - Some(_) => {} - None => { - return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); - } + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value> + where + V: de::Visitor<'de>, + { + match tri!(self.parse_whitespace()) { + Some(b'-') => { + return Err(self.peek_error(ErrorCode::NumberOutOfRange)); } + Some(_) => {} + None => { + return Err(self.peek_error(ErrorCode::EofWhileParsingValue)); + } + } - let mut buf = String::new(); - tri!(self.scan_integer128(&mut buf)); - - let value = match buf.parse() { - Ok(int) => visitor.visit_u128(int), - Err(_) => { - return Err(self.error(ErrorCode::NumberOutOfRange)); - } - }; + let mut buf = String::new(); + tri!(self.scan_integer128(&mut buf)); - match value { - Ok(value) => Ok(value), - Err(err) => Err(self.fix_position(err)), + let value = match buf.parse() { + Ok(int) => visitor.visit_u128(int), + Err(_) => { + return Err(self.error(ErrorCode::NumberOutOfRange)); } + }; + + match value { + Ok(value) => Ok(value), + Err(err) => Err(self.fix_position(err)), } } @@ -2164,15 +2159,12 @@ where deserialize_integer_key!(deserialize_i16 => visit_i16); deserialize_integer_key!(deserialize_i32 => visit_i32); deserialize_integer_key!(deserialize_i64 => visit_i64); + deserialize_integer_key!(deserialize_i128 => visit_i128); deserialize_integer_key!(deserialize_u8 => visit_u8); deserialize_integer_key!(deserialize_u16 => visit_u16); deserialize_integer_key!(deserialize_u32 => visit_u32); deserialize_integer_key!(deserialize_u64 => visit_u64); - - serde_if_integer128! { - deserialize_integer_key!(deserialize_i128 => visit_i128); - deserialize_integer_key!(deserialize_u128 => visit_u128); - } + deserialize_integer_key!(deserialize_u128 => visit_u128); #[inline] fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> diff --git a/src/error.rs b/src/error.rs index 6390c43..1875ef0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -284,9 +284,9 @@ impl Error { impl Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ErrorCode::Message(ref msg) => f.write_str(msg), - ErrorCode::Io(ref err) => Display::fmt(err, f), + match self { + ErrorCode::Message(msg) => f.write_str(msg), + ErrorCode::Io(err) => Display::fmt(err, f), ErrorCode::EofWhileParsingList => f.write_str("EOF while parsing a list"), ErrorCode::EofWhileParsingObject => f.write_str("EOF while parsing an object"), ErrorCode::EofWhileParsingString => f.write_str("EOF while parsing a string"), @@ -318,8 +318,8 @@ impl Display for ErrorCode { impl serde::de::StdError for Error { #[cfg(feature = "std")] fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self.err.code { - ErrorCode::Io(ref err) => Some(err), + match &self.err.code { + ErrorCode::Io(err) => Some(err), _ => None, } } @@ -438,7 +438,7 @@ fn parse_line_col(msg: &mut String) -> Option<(usize, usize)> { } fn starts_with_digit(slice: &str) -> bool { - match slice.as_bytes().get(0) { + match slice.as_bytes().first() { None => false, Some(&byte) => byte >= b'0' && byte <= b'9', } @@ -227,10 +227,10 @@ //! }); //! ``` //! -//! This is amazingly convenient but we have the problem we had before with -//! `Value` which is that the IDE and Rust compiler cannot help us if we get it -//! wrong. Serde JSON provides a better way of serializing strongly-typed data -//! structures into JSON text. +//! This is amazingly convenient, but we have the problem we had before with +//! `Value`: the IDE and Rust compiler cannot help us if we get it wrong. Serde +//! JSON provides a better way of serializing strongly-typed data structures +//! into JSON text. //! //! # Creating JSON by serializing data structures //! @@ -279,8 +279,8 @@ //! # No-std support //! //! As long as there is a memory allocator, it is possible to use serde_json -//! without the rest of the Rust standard library. This is supported on Rust -//! 1.36+. Disable the default "std" feature and enable the "alloc" feature: +//! without the rest of the Rust standard library. Disable the default "std" +//! feature and enable the "alloc" feature: //! //! ```toml //! [dependencies] @@ -300,7 +300,7 @@ //! [macro]: https://docs.serde.rs/serde_json/macro.json.html //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.79")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.91")] // Ignored clippy lints #![allow( clippy::collapsible_else_if, @@ -308,6 +308,7 @@ clippy::deprecated_cfg_attr, clippy::doc_markdown, clippy::excessive_precision, + clippy::explicit_auto_deref, clippy::float_cmp, clippy::manual_range_contains, clippy::match_like_matches_macro, @@ -193,13 +193,12 @@ impl Map<String, Value> { } } - /// Moves all elements from other into Self, leaving other empty. + /// Moves all elements from other into self, leaving other empty. #[inline] pub fn append(&mut self, other: &mut Self) { #[cfg(feature = "preserve_order")] - for (k, v) in mem::replace(&mut other.map, MapImpl::default()) { - self.map.insert(k, v); - } + self.map + .extend(mem::replace(&mut other.map, MapImpl::default())); #[cfg(not(feature = "preserve_order"))] self.map.append(&mut other.map); } @@ -304,6 +303,11 @@ impl Clone for Map<String, Value> { map: self.map.clone(), } } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.map.clone_from(&source.map); + } } impl PartialEq for Map<String, Value> { @@ -323,10 +327,10 @@ impl Eq for Map<String, Value> {} /// # /// # let val = &Value::String("".to_owned()); /// # let _ = -/// match *val { -/// Value::String(ref s) => Some(s.as_str()), -/// Value::Array(ref arr) => arr[0].as_str(), -/// Value::Object(ref map) => map["type"].as_str(), +/// match val { +/// Value::String(s) => Some(s.as_str()), +/// Value::Array(arr) => arr[0].as_str(), +/// Value::Object(map) => map["type"].as_str(), /// _ => None, /// } /// # ; @@ -530,9 +534,9 @@ impl<'a> Entry<'a> { /// assert_eq!(map.entry("serde").key(), &"serde"); /// ``` pub fn key(&self) -> &String { - match *self { - Entry::Vacant(ref e) => e.key(), - Entry::Occupied(ref e) => e.key(), + match self { + Entry::Vacant(e) => e.key(), + Entry::Occupied(e) => e.key(), } } diff --git a/src/number.rs b/src/number.rs index b965271..21a7641 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,18 +1,18 @@ use crate::de::ParserNumber; use crate::error::Error; +#[cfg(feature = "arbitrary_precision")] +use crate::error::ErrorCode; +#[cfg(feature = "arbitrary_precision")] +use alloc::borrow::ToOwned; +#[cfg(feature = "arbitrary_precision")] +use alloc::string::{String, ToString}; use core::fmt::{self, Debug, Display}; #[cfg(not(feature = "arbitrary_precision"))] use core::hash::{Hash, Hasher}; use serde::de::{self, Unexpected, Visitor}; -use serde::{ - forward_to_deserialize_any, serde_if_integer128, Deserialize, Deserializer, Serialize, - Serializer, -}; - -#[cfg(feature = "arbitrary_precision")] -use crate::error::ErrorCode; #[cfg(feature = "arbitrary_precision")] use serde::de::{IntoDeserializer, MapAccess}; +use serde::{forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "arbitrary_precision")] pub(crate) const TOKEN: &str = "$serde_json::private::Number"; @@ -292,9 +292,9 @@ impl Display for Number { #[cfg(not(feature = "arbitrary_precision"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.n { - N::PosInt(u) => Display::fmt(&u, formatter), - N::NegInt(i) => Display::fmt(&i, formatter), - N::Float(f) => Display::fmt(&f, formatter), + N::PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)), + N::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)), + N::Float(f) => formatter.write_str(ryu::Buffer::new().format_finite(f)), } } @@ -305,29 +305,8 @@ impl Display for Number { } impl Debug for Number { - #[cfg(not(feature = "arbitrary_precision"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - let mut debug = formatter.debug_tuple("Number"); - match self.n { - N::PosInt(i) => { - debug.field(&i); - } - N::NegInt(i) => { - debug.field(&i); - } - N::Float(f) => { - debug.field(&f); - } - } - debug.finish() - } - - #[cfg(feature = "arbitrary_precision")] - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_tuple("Number") - .field(&format_args!("{}", self.n)) - .finish() + write!(formatter, "Number({})", self) } } @@ -558,18 +537,15 @@ impl<'de> Deserializer<'de> for Number { deserialize_number!(deserialize_i16 => visit_i16); deserialize_number!(deserialize_i32 => visit_i32); deserialize_number!(deserialize_i64 => visit_i64); + deserialize_number!(deserialize_i128 => visit_i128); deserialize_number!(deserialize_u8 => visit_u8); deserialize_number!(deserialize_u16 => visit_u16); deserialize_number!(deserialize_u32 => visit_u32); deserialize_number!(deserialize_u64 => visit_u64); + deserialize_number!(deserialize_u128 => visit_u128); deserialize_number!(deserialize_f32 => visit_f32); deserialize_number!(deserialize_f64 => visit_f64); - serde_if_integer128! { - deserialize_number!(deserialize_i128 => visit_i128); - deserialize_number!(deserialize_u128 => visit_u128); - } - forward_to_deserialize_any! { bool char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier @@ -586,18 +562,15 @@ impl<'de, 'a> Deserializer<'de> for &'a Number { deserialize_number!(deserialize_i16 => visit_i16); deserialize_number!(deserialize_i32 => visit_i32); deserialize_number!(deserialize_i64 => visit_i64); + deserialize_number!(deserialize_i128 => visit_i128); deserialize_number!(deserialize_u8 => visit_u8); deserialize_number!(deserialize_u16 => visit_u16); deserialize_number!(deserialize_u32 => visit_u32); deserialize_number!(deserialize_u64 => visit_u64); + deserialize_number!(deserialize_u128 => visit_u128); deserialize_number!(deserialize_f32 => visit_f32); deserialize_number!(deserialize_f64 => visit_f64); - serde_if_integer128! { - deserialize_number!(deserialize_i128 => visit_i128); - deserialize_number!(deserialize_u128 => visit_u128); - } - forward_to_deserialize_any! { bool char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier @@ -749,19 +722,9 @@ impl_from_unsigned!(u8, u16, u32, u64, usize); impl_from_signed!(i8, i16, i32, i64, isize); #[cfg(feature = "arbitrary_precision")] -serde_if_integer128! { - impl From<i128> for Number { - fn from(i: i128) -> Self { - Number { n: i.to_string() } - } - } - - impl From<u128> for Number { - fn from(u: u128) -> Self { - Number { n: u.to_string() } - } - } -} +impl_from_unsigned!(u128); +#[cfg(feature = "arbitrary_precision")] +impl_from_signed!(i128); impl Number { #[cfg(not(feature = "arbitrary_precision"))] diff --git a/src/read.rs b/src/read.rs index 1319d89..fc3a3ca 100644 --- a/src/read.rs +++ b/src/read.rs @@ -252,7 +252,7 @@ where Some(ch) => { #[cfg(feature = "raw_value")] { - if let Some(ref mut buf) = self.raw_buffer { + if let Some(buf) = &mut self.raw_buffer { buf.push(ch); } } @@ -263,7 +263,7 @@ where Some(Ok(ch)) => { #[cfg(feature = "raw_value")] { - if let Some(ref mut buf) = self.raw_buffer { + if let Some(buf) = &mut self.raw_buffer { buf.push(ch); } } @@ -298,7 +298,7 @@ where #[cfg(feature = "raw_value")] fn discard(&mut self) { if let Some(ch) = self.ch.take() { - if let Some(ref mut buf) = self.raw_buffer { + if let Some(buf) = &mut self.raw_buffer { buf.push(ch); } } @@ -7,7 +7,6 @@ use alloc::vec::Vec; use core::fmt::{self, Display}; use core::num::FpCategory; use serde::ser::{self, Impossible, Serialize}; -use serde::serde_if_integer128; /// A structure for serializing Rust values into JSON. #[cfg_attr(docsrs, doc(cfg(feature = "std")))] @@ -75,137 +74,105 @@ where #[inline] fn serialize_bool(self, value: bool) -> Result<()> { - tri!(self - .formatter + self.formatter .write_bool(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i8(self, value: i8) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i8(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i16(self, value: i16) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i16(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i32(self, value: i32) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i32(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_i64(self, value: i64) -> Result<()> { - tri!(self - .formatter + self.formatter .write_i64(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } - serde_if_integer128! { - fn serialize_i128(self, value: i128) -> Result<()> { - self.formatter - .write_number_str(&mut self.writer, &value.to_string()) - .map_err(Error::io) - } + fn serialize_i128(self, value: i128) -> Result<()> { + self.formatter + .write_i128(&mut self.writer, value) + .map_err(Error::io) } #[inline] fn serialize_u8(self, value: u8) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u8(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u16(self, value: u16) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u16(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u32(self, value: u32) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u32(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] fn serialize_u64(self, value: u64) -> Result<()> { - tri!(self - .formatter + self.formatter .write_u64(&mut self.writer, value) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } - serde_if_integer128! { - fn serialize_u128(self, value: u128) -> Result<()> { - self.formatter - .write_number_str(&mut self.writer, &value.to_string()) - .map_err(Error::io) - } + fn serialize_u128(self, value: u128) -> Result<()> { + self.formatter + .write_u128(&mut self.writer, value) + .map_err(Error::io) } #[inline] fn serialize_f32(self, value: f32) -> Result<()> { match value.classify() { - FpCategory::Nan | FpCategory::Infinite => { - tri!(self - .formatter - .write_null(&mut self.writer) - .map_err(Error::io)); - } - _ => { - tri!(self - .formatter - .write_f32(&mut self.writer, value) - .map_err(Error::io)); - } + FpCategory::Nan | FpCategory::Infinite => self + .formatter + .write_null(&mut self.writer) + .map_err(Error::io), + _ => self + .formatter + .write_f32(&mut self.writer, value) + .map_err(Error::io), } - Ok(()) } #[inline] fn serialize_f64(self, value: f64) -> Result<()> { match value.classify() { - FpCategory::Nan | FpCategory::Infinite => { - tri!(self - .formatter - .write_null(&mut self.writer) - .map_err(Error::io)); - } - _ => { - tri!(self - .formatter - .write_f64(&mut self.writer, value) - .map_err(Error::io)); - } + FpCategory::Nan | FpCategory::Infinite => self + .formatter + .write_null(&mut self.writer) + .map_err(Error::io), + _ => self + .formatter + .write_f64(&mut self.writer, value) + .map_err(Error::io), } - Ok(()) } #[inline] @@ -217,8 +184,7 @@ where #[inline] fn serialize_str(self, value: &str) -> Result<()> { - tri!(format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io)); - Ok(()) + format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io) } #[inline] @@ -233,11 +199,9 @@ where #[inline] fn serialize_unit(self) -> Result<()> { - tri!(self - .formatter + self.formatter .write_null(&mut self.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] @@ -297,11 +261,9 @@ where .formatter .end_object_value(&mut self.writer) .map_err(Error::io)); - tri!(self - .formatter + self.formatter .end_object(&mut self.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[inline] @@ -490,11 +452,9 @@ where } } } - tri!(self - .formatter + self.formatter .end_string(&mut self.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } } @@ -533,22 +493,17 @@ where where T: ?Sized + Serialize, { - match *self { - Compound::Map { - ref mut ser, - ref mut state, - } => { + match self { + Compound::Map { ser, state } => { tri!(ser .formatter .begin_array_value(&mut ser.writer, *state == State::First) .map_err(Error::io)); *state = State::Rest; tri!(value.serialize(&mut **ser)); - tri!(ser - .formatter + ser.formatter .end_array_value(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -560,13 +515,10 @@ where #[inline] fn end(self) -> Result<()> { match self { - Compound::Map { ser, state } => { - match state { - State::Empty => {} - _ => tri!(ser.formatter.end_array(&mut ser.writer).map_err(Error::io)), - } - Ok(()) - } + Compound::Map { ser, state } => match state { + State::Empty => Ok(()), + _ => ser.formatter.end_array(&mut ser.writer).map_err(Error::io), + }, #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), #[cfg(feature = "raw_value")] @@ -647,8 +599,7 @@ where .formatter .end_object_value(&mut ser.writer) .map_err(Error::io)); - tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)); - Ok(()) + ser.formatter.end_object(&mut ser.writer).map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -671,11 +622,8 @@ where where T: ?Sized + Serialize, { - match *self { - Compound::Map { - ref mut ser, - ref mut state, - } => { + match self { + Compound::Map { ser, state } => { tri!(ser .formatter .begin_object_key(&mut ser.writer, *state == State::First) @@ -684,11 +632,9 @@ where tri!(key.serialize(MapKeySerializer { ser: *ser })); - tri!(ser - .formatter + ser.formatter .end_object_key(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -702,18 +648,16 @@ where where T: ?Sized + Serialize, { - match *self { - Compound::Map { ref mut ser, .. } => { + match self { + Compound::Map { ser, .. } => { tri!(ser .formatter .begin_object_value(&mut ser.writer) .map_err(Error::io)); tri!(value.serialize(&mut **ser)); - tri!(ser - .formatter + ser.formatter .end_object_value(&mut ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -725,13 +669,10 @@ where #[inline] fn end(self) -> Result<()> { match self { - Compound::Map { ser, state } => { - match state { - State::Empty => {} - _ => tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)), - } - Ok(()) - } + Compound::Map { ser, state } => match state { + State::Empty => Ok(()), + _ => ser.formatter.end_object(&mut ser.writer).map_err(Error::io), + }, #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), #[cfg(feature = "raw_value")] @@ -753,22 +694,20 @@ where where T: ?Sized + Serialize, { - match *self { + match self { Compound::Map { .. } => ser::SerializeMap::serialize_entry(self, key, value), #[cfg(feature = "arbitrary_precision")] - Compound::Number { ref mut ser, .. } => { + Compound::Number { ser, .. } => { if key == crate::number::TOKEN { - tri!(value.serialize(NumberStrEmitter(ser))); - Ok(()) + value.serialize(NumberStrEmitter(ser)) } else { Err(invalid_number()) } } #[cfg(feature = "raw_value")] - Compound::RawValue { ref mut ser, .. } => { + Compound::RawValue { ser, .. } => { if key == crate::raw::TOKEN { - tri!(value.serialize(RawValueStrEmitter(ser))); - Ok(()) + value.serialize(RawValueStrEmitter(ser)) } else { Err(invalid_raw_value()) } @@ -822,8 +761,7 @@ where .formatter .end_object_value(&mut ser.writer) .map_err(Error::io)); - tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)); - Ok(()) + ser.formatter.end_object(&mut ser.writer).map_err(Error::io) } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), @@ -905,12 +843,10 @@ where .formatter .write_i8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_i16(self, value: i16) -> Result<()> { @@ -924,12 +860,10 @@ where .formatter .write_i16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_i32(self, value: i32) -> Result<()> { @@ -943,12 +877,10 @@ where .formatter .write_i32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_i64(self, value: i64) -> Result<()> { @@ -962,33 +894,27 @@ where .formatter .write_i64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } - serde_if_integer128! { - fn serialize_i128(self, value: i128) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); - tri!(self - .ser - .formatter - .write_number_str(&mut self.ser.writer, &value.to_string()) - .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) - } + fn serialize_i128(self, value: i128) -> Result<()> { + tri!(self + .ser + .formatter + .begin_string(&mut self.ser.writer) + .map_err(Error::io)); + tri!(self + .ser + .formatter + .write_i128(&mut self.ser.writer, value) + .map_err(Error::io)); + self.ser + .formatter + .end_string(&mut self.ser.writer) + .map_err(Error::io) } fn serialize_u8(self, value: u8) -> Result<()> { @@ -1002,12 +928,10 @@ where .formatter .write_u8(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_u16(self, value: u16) -> Result<()> { @@ -1021,12 +945,10 @@ where .formatter .write_u16(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_u32(self, value: u32) -> Result<()> { @@ -1040,12 +962,10 @@ where .formatter .write_u32(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } fn serialize_u64(self, value: u64) -> Result<()> { @@ -1059,33 +979,27 @@ where .formatter .write_u64(&mut self.ser.writer, value) .map_err(Error::io)); - tri!(self - .ser + self.ser .formatter .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) + .map_err(Error::io) } - serde_if_integer128! { - fn serialize_u128(self, value: u128) -> Result<()> { - tri!(self - .ser - .formatter - .begin_string(&mut self.ser.writer) - .map_err(Error::io)); - tri!(self - .ser - .formatter - .write_number_str(&mut self.ser.writer, &value.to_string()) - .map_err(Error::io)); - tri!(self - .ser - .formatter - .end_string(&mut self.ser.writer) - .map_err(Error::io)); - Ok(()) - } + fn serialize_u128(self, value: u128) -> Result<()> { + tri!(self + .ser + .formatter + .begin_string(&mut self.ser.writer) + .map_err(Error::io)); + tri!(self + .ser + .formatter + .write_u128(&mut self.ser.writer, value) + .map_err(Error::io)); + self.ser + .formatter + .end_string(&mut self.ser.writer) + .map_err(Error::io) } fn serialize_f32(self, _value: f32) -> Result<()> { @@ -1224,10 +1138,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, Err(invalid_number()) } - serde_if_integer128! { - fn serialize_i128(self, _v: i128) -> Result<()> { - Err(invalid_number()) - } + fn serialize_i128(self, _v: i128) -> Result<()> { + Err(invalid_number()) } fn serialize_u8(self, _v: u8) -> Result<()> { @@ -1246,10 +1158,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, Err(invalid_number()) } - serde_if_integer128! { - fn serialize_u128(self, _v: u128) -> Result<()> { - Err(invalid_number()) - } + fn serialize_u128(self, _v: u128) -> Result<()> { + Err(invalid_number()) } fn serialize_f32(self, _v: f32) -> Result<()> { @@ -1405,10 +1315,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a, Err(ser::Error::custom("expected RawValue")) } - serde_if_integer128! { - fn serialize_i128(self, _v: i128) -> Result<()> { - Err(ser::Error::custom("expected RawValue")) - } + fn serialize_i128(self, _v: i128) -> Result<()> { + Err(ser::Error::custom("expected RawValue")) } fn serialize_u8(self, _v: u8) -> Result<()> { @@ -1427,10 +1335,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a, Err(ser::Error::custom("expected RawValue")) } - serde_if_integer128! { - fn serialize_u128(self, _v: u128) -> Result<()> { - Err(ser::Error::custom("expected RawValue")) - } + fn serialize_u128(self, _v: u128) -> Result<()> { + Err(ser::Error::custom("expected RawValue")) } fn serialize_f32(self, _v: f32) -> Result<()> { @@ -1667,6 +1573,17 @@ pub trait Formatter { writer.write_all(s.as_bytes()) } + /// Writes an integer value like `-123` to the specified writer. + #[inline] + fn write_i128<W>(&mut self, writer: &mut W, value: i128) -> io::Result<()> + where + W: ?Sized + io::Write, + { + let mut buffer = itoa::Buffer::new(); + let s = buffer.format(value); + writer.write_all(s.as_bytes()) + } + /// Writes an integer value like `123` to the specified writer. #[inline] fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()> @@ -1711,6 +1628,17 @@ pub trait Formatter { writer.write_all(s.as_bytes()) } + /// Writes an integer value like `123` to the specified writer. + #[inline] + fn write_u128<W>(&mut self, writer: &mut W, value: u128) -> io::Result<()> + where + W: ?Sized + io::Write, + { + let mut buffer = itoa::Buffer::new(); + let s = buffer.format(value); + writer.write_all(s.as_bytes()) + } + /// Writes a floating point value like `-31.26e+12` to the specified writer. #[inline] fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()> @@ -1991,13 +1919,8 @@ impl<'a> Formatter for PrettyFormatter<'a> { where W: ?Sized + io::Write, { - if first { - tri!(writer.write_all(b"\n")); - } else { - tri!(writer.write_all(b",\n")); - } - tri!(indent(writer, self.current_indent, self.indent)); - Ok(()) + tri!(writer.write_all(if first { b"\n" } else { b",\n" })); + indent(writer, self.current_indent, self.indent) } #[inline] @@ -2039,11 +1962,7 @@ impl<'a> Formatter for PrettyFormatter<'a> { where W: ?Sized + io::Write, { - if first { - tri!(writer.write_all(b"\n")); - } else { - tri!(writer.write_all(b",\n")); - } + tri!(writer.write_all(if first { b"\n" } else { b",\n" })); indent(writer, self.current_indent, self.indent) } @@ -2072,8 +1991,7 @@ where { tri!(formatter.begin_string(writer)); tri!(format_escaped_str_contents(writer, formatter, value)); - tri!(formatter.end_string(writer)); - Ok(()) + formatter.end_string(writer) } fn format_escaped_str_contents<W, F>( @@ -2105,11 +2023,11 @@ where start = i + 1; } - if start != bytes.len() { - tri!(formatter.write_string_fragment(writer, &value[start..])); + if start == bytes.len() { + return Ok(()); } - Ok(()) + formatter.write_string_fragment(writer, &value[start..]) } const BB: u8 = b'b'; // \x08 @@ -2158,8 +2076,7 @@ where T: ?Sized + Serialize, { let mut ser = Serializer::new(writer); - tri!(value.serialize(&mut ser)); - Ok(()) + value.serialize(&mut ser) } /// Serialize the given data structure as pretty-printed JSON into the IO @@ -2177,8 +2094,7 @@ where T: ?Sized + Serialize, { let mut ser = Serializer::pretty(writer); - tri!(value.serialize(&mut ser)); - Ok(()) + value.serialize(&mut ser) } /// Serialize the given data structure as a JSON byte vector. diff --git a/src/value/de.rs b/src/value/de.rs index 75e49df..9c266d0 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -14,7 +14,7 @@ use serde::de::{ self, Deserialize, DeserializeSeed, EnumAccess, Expected, IntoDeserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }; -use serde::{forward_to_deserialize_any, serde_if_integer128}; +use serde::forward_to_deserialize_any; #[cfg(feature = "arbitrary_precision")] use crate::number::NumberFromString; @@ -228,18 +228,15 @@ impl<'de> serde::Deserializer<'de> for Value { deserialize_number!(deserialize_i16); deserialize_number!(deserialize_i32); deserialize_number!(deserialize_i64); + deserialize_number!(deserialize_i128); deserialize_number!(deserialize_u8); deserialize_number!(deserialize_u16); deserialize_number!(deserialize_u32); deserialize_number!(deserialize_u64); + deserialize_number!(deserialize_u128); deserialize_number!(deserialize_f32); deserialize_number!(deserialize_f64); - serde_if_integer128! { - deserialize_number!(deserialize_i128); - deserialize_number!(deserialize_u128); - } - #[inline] fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> where @@ -648,8 +645,8 @@ macro_rules! deserialize_value_ref_number { where V: Visitor<'de>, { - match *self { - Value::Number(ref n) => n.deserialize_any(visitor), + match self { + Value::Number(n) => n.deserialize_any(visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -659,8 +656,8 @@ macro_rules! deserialize_value_ref_number { where V: Visitor<'de>, { - match *self { - Value::Number(ref n) => n.$method(visitor), + match self { + Value::Number(n) => n.$method(visitor), _ => self.deserialize_any(visitor), } } @@ -710,13 +707,13 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { + match self { Value::Null => visitor.visit_unit(), - Value::Bool(v) => visitor.visit_bool(v), - Value::Number(ref n) => n.deserialize_any(visitor), - Value::String(ref v) => visitor.visit_borrowed_str(v), - Value::Array(ref v) => visit_array_ref(v, visitor), - Value::Object(ref v) => visit_object_ref(v, visitor), + Value::Bool(v) => visitor.visit_bool(*v), + Value::Number(n) => n.deserialize_any(visitor), + Value::String(v) => visitor.visit_borrowed_str(v), + Value::Array(v) => visit_array_ref(v, visitor), + Value::Object(v) => visit_object_ref(v, visitor), } } @@ -724,18 +721,15 @@ impl<'de> serde::Deserializer<'de> for &'de Value { deserialize_value_ref_number!(deserialize_i16); deserialize_value_ref_number!(deserialize_i32); deserialize_value_ref_number!(deserialize_i64); + deserialize_number!(deserialize_i128); deserialize_value_ref_number!(deserialize_u8); deserialize_value_ref_number!(deserialize_u16); deserialize_value_ref_number!(deserialize_u32); deserialize_value_ref_number!(deserialize_u64); + deserialize_number!(deserialize_u128); deserialize_value_ref_number!(deserialize_f32); deserialize_value_ref_number!(deserialize_f64); - serde_if_integer128! { - deserialize_number!(deserialize_i128); - deserialize_number!(deserialize_u128); - } - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> where V: Visitor<'de>, @@ -755,8 +749,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - let (variant, value) = match *self { - Value::Object(ref value) => { + let (variant, value) = match self { + Value::Object(value) => { let mut iter = value.into_iter(); let (variant, value) = match iter.next() { Some(v) => v, @@ -776,8 +770,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value { } (variant, Some(value)) } - Value::String(ref variant) => (variant, None), - ref other => { + Value::String(variant) => (variant, None), + other => { return Err(serde::de::Error::invalid_type( other.unexpected(), &"string or map", @@ -831,8 +825,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { - Value::String(ref v) => visitor.visit_borrowed_str(v), + match self { + Value::String(v) => visitor.visit_borrowed_str(v), _ => Err(self.invalid_type(&visitor)), } } @@ -848,9 +842,9 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { - Value::String(ref v) => visitor.visit_borrowed_str(v), - Value::Array(ref v) => visit_array_ref(v, visitor), + match self { + Value::String(v) => visitor.visit_borrowed_str(v), + Value::Array(v) => visit_array_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -883,8 +877,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { - Value::Array(ref v) => visit_array_ref(v, visitor), + match self { + Value::Array(v) => visit_array_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -912,8 +906,8 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { - Value::Object(ref v) => visit_object_ref(v, visitor), + match self { + Value::Object(v) => visit_object_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -927,9 +921,9 @@ impl<'de> serde::Deserializer<'de> for &'de Value { where V: Visitor<'de>, { - match *self { - Value::Array(ref v) => visit_array_ref(v, visitor), - Value::Object(ref v) => visit_object_ref(v, visitor), + match self { + Value::Array(v) => visit_array_ref(v, visitor), + Value::Object(v) => visit_object_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -1000,7 +994,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> { V: Visitor<'de>, { match self.value { - Some(&Value::Array(ref v)) => { + Some(Value::Array(v)) => { if v.is_empty() { visitor.visit_unit() } else { @@ -1027,7 +1021,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> { V: Visitor<'de>, { match self.value { - Some(&Value::Object(ref v)) => visit_object_ref(v, visitor), + Some(Value::Object(v)) => visit_object_ref(v, visitor), Some(other) => Err(serde::de::Error::invalid_type( other.unexpected(), &"struct variant", @@ -1156,15 +1150,12 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> { deserialize_integer_key!(deserialize_i16 => visit_i16); deserialize_integer_key!(deserialize_i32 => visit_i32); deserialize_integer_key!(deserialize_i64 => visit_i64); + deserialize_integer_key!(deserialize_i128 => visit_i128); deserialize_integer_key!(deserialize_u8 => visit_u8); deserialize_integer_key!(deserialize_u16 => visit_u16); deserialize_integer_key!(deserialize_u32 => visit_u32); deserialize_integer_key!(deserialize_u64 => visit_u64); - - serde_if_integer128! { - deserialize_integer_key!(deserialize_i128 => visit_i128); - deserialize_integer_key!(deserialize_u128 => visit_u128); - } + deserialize_integer_key!(deserialize_u128 => visit_u128); #[inline] fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> @@ -1274,11 +1265,11 @@ impl Value { #[cold] fn unexpected(&self) -> Unexpected { - match *self { + match self { Value::Null => Unexpected::Unit, - Value::Bool(b) => Unexpected::Bool(b), - Value::Number(ref n) => n.unexpected(), - Value::String(ref s) => Unexpected::Str(s), + Value::Bool(b) => Unexpected::Bool(*b), + Value::Number(n) => n.unexpected(), + Value::String(s) => Unexpected::Str(s), Value::Array(_) => Unexpected::Seq, Value::Object(_) => Unexpected::Map, } diff --git a/src/value/from.rs b/src/value/from.rs index 7b37ef6..c5a6a39 100644 --- a/src/value/from.rs +++ b/src/value/from.rs @@ -6,9 +6,6 @@ use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::iter::FromIterator; -#[cfg(feature = "arbitrary_precision")] -use serde::serde_if_integer128; - macro_rules! from_integer { ($($ty:ident)*) => { $( @@ -27,10 +24,8 @@ from_integer! { } #[cfg(feature = "arbitrary_precision")] -serde_if_integer128! { - from_integer! { - i128 u128 - } +from_integer! { + i128 u128 } impl From<f32> for Value { @@ -268,3 +263,15 @@ impl From<()> for Value { Value::Null } } + +impl<T> From<Option<T>> for Value +where + T: Into<Value>, +{ + fn from(opt: Option<T>) -> Self { + match opt { + None => Value::Null, + Some(value) => Into::into(value), + } + } +} diff --git a/src/value/index.rs b/src/value/index.rs index 0d90a5d..c74042b 100644 --- a/src/value/index.rs +++ b/src/value/index.rs @@ -53,20 +53,20 @@ pub trait Index: private::Sealed { impl Index for usize { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { - match *v { - Value::Array(ref vec) => vec.get(*self), + match v { + Value::Array(vec) => vec.get(*self), _ => None, } } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { - match *v { - Value::Array(ref mut vec) => vec.get_mut(*self), + match v { + Value::Array(vec) => vec.get_mut(*self), _ => None, } } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { - match *v { - Value::Array(ref mut vec) => { + match v { + Value::Array(vec) => { let len = vec.len(); vec.get_mut(*self).unwrap_or_else(|| { panic!( @@ -82,23 +82,23 @@ impl Index for usize { impl Index for str { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { - match *v { - Value::Object(ref map) => map.get(self), + match v { + Value::Object(map) => map.get(self), _ => None, } } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { - match *v { - Value::Object(ref mut map) => map.get_mut(self), + match v { + Value::Object(map) => map.get_mut(self), _ => None, } } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { - if let Value::Null = *v { + if let Value::Null = v { *v = Value::Object(Map::new()); } - match *v { - Value::Object(ref mut map) => map.entry(self.to_owned()).or_insert(Value::Null), + match v { + Value::Object(map) => map.entry(self.to_owned()).or_insert(Value::Null), _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)), } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 3f00c95..c467df6 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -176,20 +176,18 @@ pub enum Value { impl Debug for Value { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match *self { - Value::Null => formatter.debug_tuple("Null").finish(), - Value::Bool(v) => formatter.debug_tuple("Bool").field(&v).finish(), - Value::Number(ref v) => Debug::fmt(v, formatter), - Value::String(ref v) => formatter.debug_tuple("String").field(v).finish(), - Value::Array(ref v) => { - formatter.write_str("Array(")?; - Debug::fmt(v, formatter)?; - formatter.write_str(")") + match self { + Value::Null => formatter.write_str("Null"), + Value::Bool(boolean) => write!(formatter, "Bool({})", boolean), + Value::Number(number) => Debug::fmt(number, formatter), + Value::String(string) => write!(formatter, "String({:?})", string), + Value::Array(vec) => { + formatter.write_str("Array ")?; + Debug::fmt(vec, formatter) } - Value::Object(ref v) => { - formatter.write_str("Object(")?; - Debug::fmt(v, formatter)?; - formatter.write_str(")") + Value::Object(map) => { + formatter.write_str("Object ")?; + Debug::fmt(map, formatter) } } } @@ -365,8 +363,8 @@ impl Value { /// assert_eq!(v["b"].as_object(), None); /// ``` pub fn as_object(&self) -> Option<&Map<String, Value>> { - match *self { - Value::Object(ref map) => Some(map), + match self { + Value::Object(map) => Some(map), _ => None, } } @@ -383,8 +381,8 @@ impl Value { /// assert_eq!(v, json!({ "a": {} })); /// ``` pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>> { - match *self { - Value::Object(ref mut map) => Some(map), + match self { + Value::Object(map) => Some(map), _ => None, } } @@ -424,8 +422,8 @@ impl Value { /// assert_eq!(v["b"].as_array(), None); /// ``` pub fn as_array(&self) -> Option<&Vec<Value>> { - match *self { - Value::Array(ref array) => Some(&*array), + match self { + Value::Array(array) => Some(array), _ => None, } } @@ -442,8 +440,8 @@ impl Value { /// assert_eq!(v, json!({ "a": [] })); /// ``` pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> { - match *self { - Value::Array(ref mut list) => Some(list), + match self { + Value::Array(list) => Some(list), _ => None, } } @@ -491,8 +489,8 @@ impl Value { /// println!("The value is: {}", v["a"].as_str().unwrap()); /// ``` pub fn as_str(&self) -> Option<&str> { - match *self { - Value::String(ref s) => Some(s), + match self { + Value::String(s) => Some(s), _ => None, } } @@ -537,8 +535,8 @@ impl Value { /// assert!(!v["c"].is_i64()); /// ``` pub fn is_i64(&self) -> bool { - match *self { - Value::Number(ref n) => n.is_i64(), + match self { + Value::Number(n) => n.is_i64(), _ => false, } } @@ -562,8 +560,8 @@ impl Value { /// assert!(!v["c"].is_u64()); /// ``` pub fn is_u64(&self) -> bool { - match *self { - Value::Number(ref n) => n.is_u64(), + match self { + Value::Number(n) => n.is_u64(), _ => false, } } @@ -588,8 +586,8 @@ impl Value { /// assert!(!v["c"].is_f64()); /// ``` pub fn is_f64(&self) -> bool { - match *self { - Value::Number(ref n) => n.is_f64(), + match self { + Value::Number(n) => n.is_f64(), _ => false, } } @@ -608,8 +606,8 @@ impl Value { /// assert_eq!(v["c"].as_i64(), None); /// ``` pub fn as_i64(&self) -> Option<i64> { - match *self { - Value::Number(ref n) => n.as_i64(), + match self { + Value::Number(n) => n.as_i64(), _ => None, } } @@ -627,8 +625,8 @@ impl Value { /// assert_eq!(v["c"].as_u64(), None); /// ``` pub fn as_u64(&self) -> Option<u64> { - match *self { - Value::Number(ref n) => n.as_u64(), + match self { + Value::Number(n) => n.as_u64(), _ => None, } } @@ -646,8 +644,8 @@ impl Value { /// assert_eq!(v["c"].as_f64(), Some(-64.0)); /// ``` pub fn as_f64(&self) -> Option<f64> { - match *self { - Value::Number(ref n) => n.as_f64(), + match self { + Value::Number(n) => n.as_f64(), _ => None, } } diff --git a/src/value/ser.rs b/src/value/ser.rs index 179380a..892a63d 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -9,23 +9,20 @@ use core::fmt::Display; use core::result; use serde::ser::{Impossible, Serialize}; -#[cfg(feature = "arbitrary_precision")] -use serde::serde_if_integer128; - impl Serialize for Value { #[inline] fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> where S: ::serde::Serializer, { - match *self { + match self { Value::Null => serializer.serialize_unit(), - Value::Bool(b) => serializer.serialize_bool(b), - Value::Number(ref n) => n.serialize(serializer), - Value::String(ref s) => serializer.serialize_str(s), - Value::Array(ref v) => v.serialize(serializer), + Value::Bool(b) => serializer.serialize_bool(*b), + Value::Number(n) => n.serialize(serializer), + Value::String(s) => serializer.serialize_str(s), + Value::Array(v) => v.serialize(serializer), #[cfg(any(feature = "std", feature = "alloc"))] - Value::Object(ref m) => { + Value::Object(m) => { use serde::ser::SerializeMap; let mut map = tri!(serializer.serialize_map(Some(m.len()))); for (k, v) in m { @@ -96,10 +93,8 @@ impl serde::Serializer for Serializer { } #[cfg(feature = "arbitrary_precision")] - serde_if_integer128! { - fn serialize_i128(self, value: i128) -> Result<Value> { - Ok(Value::Number(value.into())) - } + fn serialize_i128(self, value: i128) -> Result<Value> { + Ok(Value::Number(value.into())) } #[inline] @@ -123,10 +118,8 @@ impl serde::Serializer for Serializer { } #[cfg(feature = "arbitrary_precision")] - serde_if_integer128! { - fn serialize_u128(self, value: u128) -> Result<Value> { - Ok(Value::Number(value.into())) - } + fn serialize_u128(self, value: u128) -> Result<Value> { + Ok(Value::Number(value.into())) } #[inline] @@ -195,7 +188,7 @@ impl serde::Serializer for Serializer { T: ?Sized + Serialize, { let mut values = Map::new(); - values.insert(String::from(variant), tri!(to_value(&value))); + values.insert(String::from(variant), tri!(to_value(value))); Ok(Value::Object(values)) } @@ -273,9 +266,9 @@ impl serde::Serializer for Serializer { }) } - fn collect_str<T: ?Sized>(self, value: &T) -> Result<Value> + fn collect_str<T>(self, value: &T) -> Result<Value> where - T: Display, + T: ?Sized + Display, { Ok(Value::String(value.to_string())) } @@ -314,7 +307,7 @@ impl serde::ser::SerializeSeq for SerializeVec { where T: ?Sized + Serialize, { - self.vec.push(tri!(to_value(&value))); + self.vec.push(tri!(to_value(value))); Ok(()) } @@ -363,7 +356,7 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { where T: ?Sized + Serialize, { - self.vec.push(tri!(to_value(&value))); + self.vec.push(tri!(to_value(value))); Ok(()) } @@ -384,10 +377,8 @@ impl serde::ser::SerializeMap for SerializeMap { where T: ?Sized + Serialize, { - match *self { - SerializeMap::Map { - ref mut next_key, .. - } => { + match self { + SerializeMap::Map { next_key, .. } => { *next_key = Some(tri!(key.serialize(MapKeySerializer))); Ok(()) } @@ -402,16 +393,13 @@ impl serde::ser::SerializeMap for SerializeMap { where T: ?Sized + Serialize, { - match *self { - SerializeMap::Map { - ref mut map, - ref mut next_key, - } => { + match self { + SerializeMap::Map { map, next_key } => { let key = next_key.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect("serialize_value called before serialize_key"); - map.insert(key, tri!(to_value(&value))); + map.insert(key, tri!(to_value(value))); Ok(()) } #[cfg(feature = "arbitrary_precision")] @@ -606,9 +594,9 @@ impl serde::Serializer for MapKeySerializer { Err(key_must_be_a_string()) } - fn collect_str<T: ?Sized>(self, value: &T) -> Result<String> + fn collect_str<T>(self, value: &T) -> Result<String> where - T: Display, + T: ?Sized + Display, { Ok(value.to_string()) } @@ -622,10 +610,10 @@ impl serde::ser::SerializeStruct for SerializeMap { where T: ?Sized + Serialize, { - match *self { + match self { SerializeMap::Map { .. } => serde::ser::SerializeMap::serialize_entry(self, key, value), #[cfg(feature = "arbitrary_precision")] - SerializeMap::Number { ref mut out_value } => { + SerializeMap::Number { out_value } => { if key == crate::number::TOKEN { *out_value = Some(value.serialize(NumberValueEmitter)?); Ok(()) @@ -634,7 +622,7 @@ impl serde::ser::SerializeStruct for SerializeMap { } } #[cfg(feature = "raw_value")] - SerializeMap::RawValue { ref mut out_value } => { + SerializeMap::RawValue { out_value } => { if key == crate::raw::TOKEN { *out_value = Some(value.serialize(RawValueEmitter)?); Ok(()) @@ -668,7 +656,7 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant { where T: ?Sized + Serialize, { - self.map.insert(String::from(key), tri!(to_value(&value))); + self.map.insert(String::from(key), tri!(to_value(value))); Ok(()) } diff --git a/tests/debug.rs b/tests/debug.rs index d2d8448..8ddcf5a 100644 --- a/tests/debug.rs +++ b/tests/debug.rs @@ -1,3 +1,4 @@ +use indoc::indoc; use serde_json::{json, Number, Value}; #[test] @@ -26,6 +27,8 @@ fn value_number() { assert_eq!(format!("{:?}", json!(1)), "Number(1)"); assert_eq!(format!("{:?}", json!(-1)), "Number(-1)"); assert_eq!(format!("{:?}", json!(1.0)), "Number(1.0)"); + assert_eq!(Number::from_f64(1.0).unwrap().to_string(), "1.0"); // not just "1" + assert_eq!(Number::from_f64(12e40).unwrap().to_string(), "1.2e41"); } #[test] @@ -35,12 +38,12 @@ fn value_string() { #[test] fn value_array() { - assert_eq!(format!("{:?}", json!([])), "Array([])"); + assert_eq!(format!("{:?}", json!([])), "Array []"); } #[test] fn value_object() { - assert_eq!(format!("{:?}", json!({})), "Object({})"); + assert_eq!(format!("{:?}", json!({})), "Object {}"); } #[test] @@ -50,19 +53,29 @@ fn error() { assert_eq!(format!("{:?}", err), expected); } -const INDENTED_EXPECTED: &str = r#"Object({ - "array": Array([ - Number( - 0, - ), - Number( - 1, - ), - ]), -})"#; - #[test] fn indented() { - let j = json!({ "array": [0, 1] }); - assert_eq!(format!("{:#?}", j), INDENTED_EXPECTED); + let j = json!({ + "Array": [true], + "Bool": true, + "EmptyArray": [], + "EmptyObject": {}, + "Null": null, + "Number": 1, + "String": "...", + }); + let expected = indoc! {r#" + Object { + "Array": Array [ + Bool(true), + ], + "Bool": Bool(true), + "EmptyArray": Array [], + "EmptyObject": Object {}, + "Null": Null, + "Number": Number(1), + "String": String("..."), + }"# + }; + assert_eq!(format!("{:#?}", j), expected); } diff --git a/tests/macros/mod.rs b/tests/macros/mod.rs index 8ac4619..aaf820f 100644 --- a/tests/macros/mod.rs +++ b/tests/macros/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused_macro_rules)] + macro_rules! json_str { ([]) => { "[]" diff --git a/tests/regression/issue795.rs b/tests/regression/issue795.rs index 06b6872..bb82852 100644 --- a/tests/regression/issue795.rs +++ b/tests/regression/issue795.rs @@ -1,3 +1,5 @@ +#![allow(clippy::assertions_on_result_states)] + use serde::de::{ Deserialize, Deserializer, EnumAccess, IgnoredAny, MapAccess, VariantAccess, Visitor, }; diff --git a/tests/regression/issue845.rs b/tests/regression/issue845.rs index dcca556..56037ae 100644 --- a/tests/regression/issue845.rs +++ b/tests/regression/issue845.rs @@ -1,3 +1,5 @@ +#![allow(clippy::trait_duplication_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/8757 + use serde::{Deserialize, Deserializer}; use std::convert::TryFrom; use std::fmt::{self, Display}; diff --git a/tests/regression/issue953.rs b/tests/regression/issue953.rs new file mode 100644 index 0000000..771aa52 --- /dev/null +++ b/tests/regression/issue953.rs @@ -0,0 +1,9 @@ +use serde_json::Value; + +#[test] +fn test() { + let x1 = serde_json::from_str::<Value>("18446744073709551615."); + assert!(x1.is_err()); + let x2 = serde_json::from_str::<Value>("18446744073709551616."); + assert!(x2.is_err()); +} diff --git a/tests/stream.rs b/tests/stream.rs index ca54e9a..ec6b9e3 100644 --- a/tests/stream.rs +++ b/tests/stream.rs @@ -1,4 +1,5 @@ #![cfg(not(feature = "preserve_order"))] +#![allow(clippy::assertions_on_result_states)] use serde_json::{json, Deserializer, Value}; diff --git a/tests/test.rs b/tests/test.rs index b11635e..c205072 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,10 +1,11 @@ #![cfg(not(feature = "preserve_order"))] #![allow( + clippy::assertions_on_result_states, clippy::cast_precision_loss, + clippy::derive_partial_eq_without_eq, clippy::excessive_precision, clippy::float_cmp, clippy::items_after_statements, - clippy::let_underscore_drop, clippy::shadow_unrelated, clippy::too_many_lines, clippy::unreadable_literal, @@ -93,7 +94,7 @@ where let s = to_string(value).unwrap(); assert_eq!(s, out); - let v = to_value(&value).unwrap(); + let v = to_value(value).unwrap(); let s = to_string(&v).unwrap(); assert_eq!(s, out); } @@ -109,7 +110,7 @@ where let s = to_string_pretty(value).unwrap(); assert_eq!(s, out); - let v = to_value(&value).unwrap(); + let v = to_value(value).unwrap(); let s = to_string_pretty(&v).unwrap(); assert_eq!(s, out); } @@ -1105,7 +1106,7 @@ fn test_parse_string() { ]); test_parse_ok(vec![ - ("\"\"", "".to_string()), + ("\"\"", String::new()), ("\"foo\"", "foo".to_string()), (" \"foo\" ", "foo".to_string()), ("\"\\\"\"", "\"".to_string()), @@ -1926,7 +1927,7 @@ fn test_deny_float_key() { // map with float key let map = treemap!(Float => "x"); - assert!(serde_json::to_value(&map).is_err()); + assert!(serde_json::to_value(map).is_err()); } #[test] diff --git a/tests/ui/missing_colon.stderr b/tests/ui/missing_colon.stderr index 9b83c17..1515211 100644 --- a/tests/ui/missing_colon.stderr +++ b/tests/ui/missing_colon.stderr @@ -4,4 +4,9 @@ error: unexpected end of macro invocation 4 | json!({ "a" }); | ^^^^^^^^^^^^^^ missing tokens in macro arguments | - = note: this error originates in the macro `json_internal` (in Nightly builds, run with -Z macro-backtrace for more info) +note: while trying to match `@` + --> src/macros.rs + | + | (@array [$($elems:expr,)*]) => { + | ^ + = note: this error originates in the macro `json_internal` which comes from the expansion of the macro `json` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/missing_comma.stderr b/tests/ui/missing_comma.stderr index bd911d0..bafa0f8 100644 --- a/tests/ui/missing_comma.stderr +++ b/tests/ui/missing_comma.stderr @@ -5,3 +5,9 @@ error: no rules expected the token `"2"` | -^^^ no rules expected this token in macro call | | | help: missing comma here + | +note: while trying to match `,` + --> src/macros.rs + | + | ($e:expr , $($tt:tt)*) => {}; + | ^ diff --git a/tests/ui/missing_value.stderr b/tests/ui/missing_value.stderr index d538d96..9c9de99 100644 --- a/tests/ui/missing_value.stderr +++ b/tests/ui/missing_value.stderr @@ -4,4 +4,9 @@ error: unexpected end of macro invocation 4 | json!({ "a" : }); | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments | - = note: this error originates in the macro `json_internal` (in Nightly builds, run with -Z macro-backtrace for more info) +note: while trying to match `@` + --> src/macros.rs + | + | (@array [$($elems:expr,)*]) => { + | ^ + = note: this error originates in the macro `json_internal` which comes from the expansion of the macro `json` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/parse_expr.stderr b/tests/ui/parse_expr.stderr index 6959673..cd3e1c9 100644 --- a/tests/ui/parse_expr.stderr +++ b/tests/ui/parse_expr.stderr @@ -3,3 +3,9 @@ error: no rules expected the token `~` | 4 | json!({ "a" : ~ }); | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> src/macros.rs + | + | ($e:expr , $($tt:tt)*) => {}; + | ^^^^^^^ diff --git a/tests/ui/unexpected_after_array_element.stderr b/tests/ui/unexpected_after_array_element.stderr index f745a21..ef449f7 100644 --- a/tests/ui/unexpected_after_array_element.stderr +++ b/tests/ui/unexpected_after_array_element.stderr @@ -3,3 +3,5 @@ error: no rules expected the token `=>` | 4 | json!([ true => ]); | ^^ no rules expected this token in macro call + | + = note: while trying to match end of macro diff --git a/tests/ui/unexpected_after_map_entry.stderr b/tests/ui/unexpected_after_map_entry.stderr index a18c9b4..c62d90b 100644 --- a/tests/ui/unexpected_after_map_entry.stderr +++ b/tests/ui/unexpected_after_map_entry.stderr @@ -3,3 +3,5 @@ error: no rules expected the token `=>` | 4 | json!({ "k": true => }); | ^^ no rules expected this token in macro call + | + = note: while trying to match end of macro diff --git a/tests/ui/unexpected_colon.stderr b/tests/ui/unexpected_colon.stderr index ed038f6..7e47726 100644 --- a/tests/ui/unexpected_colon.stderr +++ b/tests/ui/unexpected_colon.stderr @@ -3,3 +3,5 @@ error: no rules expected the token `:` | 4 | json!({ : true }); | ^ no rules expected this token in macro call + | + = note: while trying to match end of macro diff --git a/tests/ui/unexpected_comma.stderr b/tests/ui/unexpected_comma.stderr index a4309c4..552f399 100644 --- a/tests/ui/unexpected_comma.stderr +++ b/tests/ui/unexpected_comma.stderr @@ -3,3 +3,5 @@ error: no rules expected the token `,` | 4 | json!({ "a" , "b": true }); | ^ no rules expected this token in macro call + | + = note: while trying to match end of macro |