diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72f1c9197..387322431 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: with: name: Cargo.lock path: Cargo.lock + continue-on-error: true build: name: Rust ${{matrix.rust}} ${{matrix.os == 'windows' && '(windows)' || ''}} @@ -43,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [beta, 1.64.0, 1.56.1] + rust: [beta, 1.65.0, 1.56.1] os: [ubuntu] include: - rust: stable diff --git a/Cargo.toml b/Cargo.toml index 36f42c820..4d9e82c7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_json" -version = "1.0.128" +version = "1.0.133" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" diff --git a/src/de.rs b/src/de.rs index bd6f2e50c..5b64138d8 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1378,7 +1378,7 @@ macro_rules! check_recursion { }; } -impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { +impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer { type Error = Error; #[inline] @@ -1926,31 +1926,37 @@ impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { where T: de::DeserializeSeed<'de>, { - let peek = match tri!(self.de.parse_whitespace()) { - Some(b']') => { - return Ok(None); - } - Some(b',') if !self.first => { - self.de.eat_char(); - tri!(self.de.parse_whitespace()) - } - Some(b) => { - if self.first { - self.first = false; - Some(b) - } else { - return Err(self.de.peek_error(ErrorCode::ExpectedListCommaOrEnd)); + fn has_next_element<'de, 'a, R: Read<'de> + 'a>( + seq: &mut SeqAccess<'a, R>, + ) -> Result { + let peek = match tri!(seq.de.parse_whitespace()) { + Some(b) => b, + None => { + return Err(seq.de.peek_error(ErrorCode::EofWhileParsingList)); } + }; + + if peek == b']' { + Ok(false) + } else if seq.first { + seq.first = false; + Ok(true) + } else if peek == b',' { + seq.de.eat_char(); + match tri!(seq.de.parse_whitespace()) { + Some(b']') => Err(seq.de.peek_error(ErrorCode::TrailingComma)), + Some(_) => Ok(true), + None => Err(seq.de.peek_error(ErrorCode::EofWhileParsingValue)), + } + } else { + Err(seq.de.peek_error(ErrorCode::ExpectedListCommaOrEnd)) } - None => { - return Err(self.de.peek_error(ErrorCode::EofWhileParsingList)); - } - }; + } - match peek { - Some(b']') => Err(self.de.peek_error(ErrorCode::TrailingComma)), - Some(_) => Ok(Some(tri!(seed.deserialize(&mut *self.de)))), - None => Err(self.de.peek_error(ErrorCode::EofWhileParsingValue)), + if tri!(has_next_element(self)) { + Ok(Some(tri!(seed.deserialize(&mut *self.de)))) + } else { + Ok(None) } } } @@ -1973,32 +1979,40 @@ impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { where K: de::DeserializeSeed<'de>, { - let peek = match tri!(self.de.parse_whitespace()) { - Some(b'}') => { - return Ok(None); - } - Some(b',') if !self.first => { - self.de.eat_char(); - tri!(self.de.parse_whitespace()) - } - Some(b) => { - if self.first { - self.first = false; - Some(b) + fn has_next_key<'de, 'a, R: Read<'de> + 'a>(map: &mut MapAccess<'a, R>) -> Result { + let peek = match tri!(map.de.parse_whitespace()) { + Some(b) => b, + None => { + return Err(map.de.peek_error(ErrorCode::EofWhileParsingObject)); + } + }; + + if peek == b'}' { + Ok(false) + } else if map.first { + map.first = false; + if peek == b'"' { + Ok(true) } else { - return Err(self.de.peek_error(ErrorCode::ExpectedObjectCommaOrEnd)); + Err(map.de.peek_error(ErrorCode::KeyMustBeAString)) } + } else if peek == b',' { + map.de.eat_char(); + match tri!(map.de.parse_whitespace()) { + Some(b'"') => Ok(true), + Some(b'}') => Err(map.de.peek_error(ErrorCode::TrailingComma)), + Some(_) => Err(map.de.peek_error(ErrorCode::KeyMustBeAString)), + None => Err(map.de.peek_error(ErrorCode::EofWhileParsingValue)), + } + } else { + Err(map.de.peek_error(ErrorCode::ExpectedObjectCommaOrEnd)) } - None => { - return Err(self.de.peek_error(ErrorCode::EofWhileParsingObject)); - } - }; + } - match peek { - Some(b'"') => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), - Some(b'}') => Err(self.de.peek_error(ErrorCode::TrailingComma)), - Some(_) => Err(self.de.peek_error(ErrorCode::KeyMustBeAString)), - None => Err(self.de.peek_error(ErrorCode::EofWhileParsingValue)), + if tri!(has_next_key(self)) { + Ok(Some(tri!(seed.deserialize(MapKey { de: &mut *self.de })))) + } else { + Ok(None) } } diff --git a/src/lexical/math.rs b/src/lexical/math.rs index adacb42e1..2e900f1a1 100644 --- a/src/lexical/math.rs +++ b/src/lexical/math.rs @@ -272,9 +272,7 @@ mod scalar { mod small { use super::*; - // MULTIPLICATIION - - /// ADDITION + // ADDITION /// Implied AddAssign implementation for adding a small integer to bigint. /// diff --git a/src/lib.rs b/src/lib.rs index 8358c76d7..b98cad696 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,7 +299,7 @@ //! [macro]: crate::json //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.128")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.133")] // Ignored clippy lints #![allow( clippy::collapsible_else_if, @@ -314,6 +314,7 @@ clippy::match_single_binding, clippy::needless_doctest_main, clippy::needless_late_init, + clippy::needless_lifetimes, clippy::return_self_not_must_use, clippy::transmute_ptr_to_ptr, clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133 diff --git a/src/map.rs b/src/map.rs index 49265c3fe..bc9a9307b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -6,6 +6,7 @@ //! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html //! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html +use crate::error::Error; use crate::value::Value; use alloc::string::String; #[cfg(feature = "preserve_order")] @@ -348,6 +349,29 @@ impl Map { { self.map.retain(f); } + + /// Sorts this map's entries in-place using `str`'s usual ordering. + /// + /// If serde_json's "preserve_order" feature is not enabled, this method + /// does no work because all JSON maps are always kept in a sorted state. + /// + /// If serde_json's "preserve_order" feature is enabled, this method + /// destroys the original source order or insertion order of this map in + /// favor of an alphanumerical order that matches how a BTreeMap with the + /// same contents would be ordered. This takes **O(n log n + c)** time where + /// _n_ is the length of the map and _c_ is the capacity. + /// + /// Other maps nested within the values of this map are not sorted. If you + /// need the entire data structure to be sorted at all levels, you must also + /// call + /// map.[values_mut]\().for_each([Value::sort_all_objects]). + /// + /// [values_mut]: Map::values_mut + #[inline] + pub fn sort_keys(&mut self) { + #[cfg(feature = "preserve_order")] + self.map.sort_unstable_keys(); + } } #[allow(clippy::derivable_impls)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7655 @@ -415,7 +439,7 @@ impl Hash for Map { /// } /// # ; /// ``` -impl<'a, Q> ops::Index<&'a Q> for Map +impl ops::Index<&Q> for Map where String: Borrow, Q: ?Sized + Ord + Eq + Hash, @@ -438,7 +462,7 @@ where /// # /// map["key"] = json!("value"); /// ``` -impl<'a, Q> ops::IndexMut<&'a Q> for Map +impl ops::IndexMut<&Q> for Map where String: Borrow, Q: ?Sized + Ord + Eq + Hash, @@ -566,6 +590,22 @@ macro_rules! delegate_iterator { } } +impl<'de> de::IntoDeserializer<'de, Error> for Map { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de> de::IntoDeserializer<'de, Error> for &'de Map { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + ////////////////////////////////////////////////////////////////////////////// /// A view into a single entry in a map, which may either be vacant or occupied. diff --git a/src/number.rs b/src/number.rs index 878a3dcb2..8cb0c3b7b 100644 --- a/src/number.rs +++ b/src/number.rs @@ -78,22 +78,6 @@ impl Number { /// /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to /// return the integer value. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let big = i64::MAX as u64 + 10; - /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); - /// - /// assert!(v["a"].is_i64()); - /// - /// // Greater than i64::MAX. - /// assert!(!v["b"].is_i64()); - /// - /// // Numbers with a decimal point are not considered integers. - /// assert!(!v["c"].is_i64()); - /// ``` - #[inline] pub fn is_i64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -109,21 +93,6 @@ impl Number { /// /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to /// return the integer value. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let v = json!({ "a": 64, "b": -64, "c": 256.0 }); - /// - /// assert!(v["a"].is_u64()); - /// - /// // Negative integer. - /// assert!(!v["b"].is_u64()); - /// - /// // Numbers with a decimal point are not considered integers. - /// assert!(!v["c"].is_u64()); - /// ``` - #[inline] pub fn is_u64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -141,19 +110,6 @@ impl Number { /// /// Currently this function returns true if and only if both `is_i64` and /// `is_u64` return false but this is not a guarantee in the future. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let v = json!({ "a": 256.0, "b": 64, "c": -64 }); - /// - /// assert!(v["a"].is_f64()); - /// - /// // Integers. - /// assert!(!v["b"].is_f64()); - /// assert!(!v["c"].is_f64()); - /// ``` - #[inline] pub fn is_f64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -173,18 +129,6 @@ impl Number { /// If the `Number` is an integer, represent it as i64 if possible. Returns /// None otherwise. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let big = i64::MAX as u64 + 10; - /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); - /// - /// assert_eq!(v["a"].as_i64(), Some(64)); - /// assert_eq!(v["b"].as_i64(), None); - /// assert_eq!(v["c"].as_i64(), None); - /// ``` - #[inline] pub fn as_i64(&self) -> Option { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -204,17 +148,6 @@ impl Number { /// If the `Number` is an integer, represent it as u64 if possible. Returns /// None otherwise. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let v = json!({ "a": 64, "b": -64, "c": 256.0 }); - /// - /// assert_eq!(v["a"].as_u64(), Some(64)); - /// assert_eq!(v["b"].as_u64(), None); - /// assert_eq!(v["c"].as_u64(), None); - /// ``` - #[inline] pub fn as_u64(&self) -> Option { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -226,17 +159,6 @@ impl Number { } /// Represents the number as f64 if possible. Returns None otherwise. - /// - /// ``` - /// # use serde_json::json; - /// # - /// let v = json!({ "a": 256.0, "b": 64, "c": -64 }); - /// - /// assert_eq!(v["a"].as_f64(), Some(256.0)); - /// assert_eq!(v["b"].as_f64(), Some(64.0)); - /// assert_eq!(v["c"].as_f64(), Some(-64.0)); - /// ``` - #[inline] pub fn as_f64(&self) -> Option { #[cfg(not(feature = "arbitrary_precision"))] match self.n { @@ -252,15 +174,12 @@ impl Number { /// numbers. /// /// ``` - /// # use std::f64; - /// # /// # use serde_json::Number; /// # /// assert!(Number::from_f64(256.0).is_some()); /// /// assert!(Number::from_f64(f64::NAN).is_none()); /// ``` - #[inline] pub fn from_f64(f: f64) -> Option { if f.is_finite() { let n = { @@ -279,6 +198,87 @@ impl Number { } } + /// If the `Number` is an integer, represent it as i128 if possible. Returns + /// None otherwise. + pub fn as_i128(&self) -> Option { + #[cfg(not(feature = "arbitrary_precision"))] + match self.n { + N::PosInt(n) => Some(n as i128), + N::NegInt(n) => Some(n as i128), + N::Float(_) => None, + } + #[cfg(feature = "arbitrary_precision")] + self.n.parse().ok() + } + + /// If the `Number` is an integer, represent it as u128 if possible. Returns + /// None otherwise. + pub fn as_u128(&self) -> Option { + #[cfg(not(feature = "arbitrary_precision"))] + match self.n { + N::PosInt(n) => Some(n as u128), + N::NegInt(_) | N::Float(_) => None, + } + #[cfg(feature = "arbitrary_precision")] + self.n.parse().ok() + } + + /// Converts an `i128` to a `Number`. Numbers smaller than i64::MIN or + /// larger than u64::MAX can only be represented in `Number` if serde_json's + /// "arbitrary_precision" feature is enabled. + /// + /// ``` + /// # use serde_json::Number; + /// # + /// assert!(Number::from_i128(256).is_some()); + /// ``` + pub fn from_i128(i: i128) -> Option { + let n = { + #[cfg(not(feature = "arbitrary_precision"))] + { + if let Ok(u) = u64::try_from(i) { + N::PosInt(u) + } else if let Ok(i) = i64::try_from(i) { + N::NegInt(i) + } else { + return None; + } + } + #[cfg(feature = "arbitrary_precision")] + { + i.to_string() + } + }; + Some(Number { n }) + } + + /// Converts a `u128` to a `Number`. Numbers greater than u64::MAX can only + /// be represented in `Number` if serde_json's "arbitrary_precision" feature + /// is enabled. + /// + /// ``` + /// # use serde_json::Number; + /// # + /// assert!(Number::from_u128(256).is_some()); + /// ``` + pub fn from_u128(i: u128) -> Option { + let n = { + #[cfg(not(feature = "arbitrary_precision"))] + { + if let Ok(u) = u64::try_from(i) { + N::PosInt(u) + } else { + return None; + } + } + #[cfg(feature = "arbitrary_precision")] + { + i.to_string() + } + }; + Some(Number { n }) + } + /// Returns the exact original JSON representation that this Number was /// parsed from. /// @@ -368,7 +368,6 @@ impl Debug for Number { impl Serialize for Number { #[cfg(not(feature = "arbitrary_precision"))] - #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -381,7 +380,6 @@ impl Serialize for Number { } #[cfg(feature = "arbitrary_precision")] - #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -409,17 +407,30 @@ impl<'de> Deserialize<'de> for Number { formatter.write_str("a JSON number") } - #[inline] fn visit_i64(self, value: i64) -> Result { Ok(value.into()) } - #[inline] + fn visit_i128(self, value: i128) -> Result + where + E: de::Error, + { + Number::from_i128(value) + .ok_or_else(|| de::Error::custom("JSON number out of range")) + } + fn visit_u64(self, value: u64) -> Result { Ok(value.into()) } - #[inline] + fn visit_u128(self, value: u128) -> Result + where + E: de::Error, + { + Number::from_u128(value) + .ok_or_else(|| de::Error::custom("JSON number out of range")) + } + fn visit_f64(self, value: f64) -> Result where E: de::Error, @@ -428,7 +439,6 @@ impl<'de> Deserialize<'de> for Number { } #[cfg(feature = "arbitrary_precision")] - #[inline] fn visit_map(self, mut visitor: V) -> Result where V: de::MapAccess<'de>, @@ -522,7 +532,6 @@ fn invalid_number() -> Error { macro_rules! deserialize_any { (@expand [$($num_string:tt)*]) => { #[cfg(not(feature = "arbitrary_precision"))] - #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, @@ -535,7 +544,6 @@ macro_rules! deserialize_any { } #[cfg(feature = "arbitrary_precision")] - #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de> { @@ -543,6 +551,10 @@ macro_rules! deserialize_any { return visitor.visit_u64(u); } else if let Some(i) = self.as_i64() { return visitor.visit_i64(i); + } else if let Some(u) = self.as_u128() { + return visitor.visit_u128(u); + } else if let Some(i) = self.as_i128() { + return visitor.visit_i128(i); } else if let Some(f) = self.as_f64() { if ryu::Buffer::new().format_finite(f) == self.n || f.to_string() == self.n { return visitor.visit_f64(f); @@ -609,7 +621,7 @@ impl<'de> Deserializer<'de> for Number { } } -impl<'de, 'a> Deserializer<'de> for &'a Number { +impl<'de> Deserializer<'de> for &Number { type Error = Error; deserialize_any!(ref); @@ -692,7 +704,7 @@ impl From for Number { } #[cfg(feature = "arbitrary_precision")] { - f.to_string() + ryu::Buffer::new().format_finite(f).to_owned() } } ParserNumber::U64(u) => { @@ -702,7 +714,7 @@ impl From for Number { } #[cfg(feature = "arbitrary_precision")] { - u.to_string() + itoa::Buffer::new().format(u).to_owned() } } ParserNumber::I64(i) => { @@ -712,7 +724,7 @@ impl From for Number { } #[cfg(feature = "arbitrary_precision")] { - i.to_string() + itoa::Buffer::new().format(i).to_owned() } } #[cfg(feature = "arbitrary_precision")] @@ -728,7 +740,6 @@ macro_rules! impl_from_unsigned { ) => { $( impl From<$ty> for Number { - #[inline] fn from(u: $ty) -> Self { let n = { #[cfg(not(feature = "arbitrary_precision"))] @@ -751,7 +762,6 @@ macro_rules! impl_from_signed { ) => { $( impl From<$ty> for Number { - #[inline] fn from(i: $ty) -> Self { let n = { #[cfg(not(feature = "arbitrary_precision"))] diff --git a/src/read.rs b/src/read.rs index b84ec223a..eaa46996b 100644 --- a/src/read.rs +++ b/src/read.rs @@ -751,9 +751,9 @@ impl<'a> Read<'a> for StrRead<'a> { ////////////////////////////////////////////////////////////////////////////// -impl<'a, 'de, R> private::Sealed for &'a mut R where R: Read<'de> {} +impl<'de, R> private::Sealed for &mut R where R: Read<'de> {} -impl<'a, 'de, R> Read<'de> for &'a mut R +impl<'de, R> Read<'de> for &mut R where R: Read<'de>, { @@ -977,6 +977,11 @@ fn push_wtf8_codepoint(n: u32, scratch: &mut Vec) { scratch.reserve(4); + // SAFETY: After the `reserve` call, `scratch` has at least 4 bytes of + // allocated but unintialized memory after its last initialized byte, which + // is where `ptr` points. All reachable match arms write `encoded_len` bytes + // to that region and update the length accordingly, and `encoded_len` is + // always <= 4. unsafe { let ptr = scratch.as_mut_ptr().add(scratch.len()); diff --git a/src/ser.rs b/src/ser.rs index 3742e0bef..6956671b4 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -2,7 +2,9 @@ use crate::error::{Error, ErrorCode, Result}; use crate::io; -use alloc::string::{String, ToString}; +use alloc::string::String; +#[cfg(feature = "raw_value")] +use alloc::string::ToString; use alloc::vec::Vec; use core::fmt::{self, Display}; use core::num::FpCategory; @@ -1057,7 +1059,7 @@ where } fn serialize_char(self, value: char) -> Result<()> { - self.ser.serialize_str(&value.to_string()) + self.ser.serialize_str(value.encode_utf8(&mut [0u8; 4])) } fn serialize_bytes(self, _value: &[u8]) -> Result<()> { diff --git a/src/value/de.rs b/src/value/de.rs index 936725635..dd4698e80 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -11,8 +11,8 @@ use core::fmt; use core::slice; use core::str::FromStr; use serde::de::{ - self, Deserialize, DeserializeSeed, EnumAccess, Expected, IntoDeserializer, MapAccess, - SeqAccess, Unexpected, VariantAccess, Visitor, + self, Deserialize, DeserializeSeed, Deserializer as _, EnumAccess, Expected, IntoDeserializer, + MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }; use serde::forward_to_deserialize_any; @@ -44,11 +44,27 @@ impl<'de> Deserialize<'de> for Value { Ok(Value::Number(value.into())) } + fn visit_i128(self, value: i128) -> Result + where + E: serde::de::Error, + { + let de = serde::de::value::I128Deserializer::new(value); + Number::deserialize(de).map(Value::Number) + } + #[inline] fn visit_u64(self, value: u64) -> Result { Ok(Value::Number(value.into())) } + fn visit_u128(self, value: u128) -> Result + where + E: serde::de::Error, + { + let de = serde::de::value::U128Deserializer::new(value); + Number::deserialize(de).map(Value::Number) + } + #[inline] fn visit_f64(self, value: f64) -> Result { Ok(Number::from_f64(value).map_or(Value::Null, Value::Number)) @@ -187,21 +203,72 @@ where } } -fn visit_object<'de, V>(object: Map, visitor: V) -> Result -where - V: Visitor<'de>, -{ - let len = object.len(); - let mut deserializer = MapDeserializer::new(object); - let map = tri!(visitor.visit_map(&mut deserializer)); - let remaining = deserializer.iter.len(); - if remaining == 0 { - Ok(map) - } else { - Err(serde::de::Error::invalid_length( - len, - &"fewer elements in map", - )) +impl<'de> serde::Deserializer<'de> for Map { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = self.len(); + let mut deserializer = MapDeserializer::new(self); + let map = tri!(visitor.visit_map(&mut deserializer)); + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(map) + } else { + Err(serde::de::Error::invalid_length( + len, + &"fewer elements in map", + )) + } + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let mut iter = self.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(serde::de::Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err(serde::de::Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + + visitor.visit_enum(EnumDeserializer { + variant, + value: Some(value), + }) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct identifier } } @@ -222,7 +289,7 @@ impl<'de> serde::Deserializer<'de> for Value { #[cfg(not(any(feature = "std", feature = "alloc")))] Value::String(_) => unreachable!(), Value::Array(v) => visit_array(v, visitor), - Value::Object(v) => visit_object(v, visitor), + Value::Object(v) => v.deserialize_any(visitor), } } @@ -253,44 +320,24 @@ impl<'de> serde::Deserializer<'de> for Value { #[inline] fn deserialize_enum( self, - _name: &str, - _variants: &'static [&'static str], + name: &'static str, + variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { - let (variant, value) = match self { - Value::Object(value) => { - let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(serde::de::Error::invalid_value( - Unexpected::Map, - &"map with a single key", - )); - } - }; - // enums are encoded in json as maps with a single key:value pair - if iter.next().is_some() { - return Err(serde::de::Error::invalid_value( - Unexpected::Map, - &"map with a single key", - )); - } - (variant, Some(value)) - } - Value::String(variant) => (variant, None), - other => { - return Err(serde::de::Error::invalid_type( - other.unexpected(), - &"string or map", - )); - } - }; - - visitor.visit_enum(EnumDeserializer { variant, value }) + match self { + Value::Object(value) => value.deserialize_enum(name, variants, visitor), + Value::String(variant) => visitor.visit_enum(EnumDeserializer { + variant, + value: None, + }), + other => Err(serde::de::Error::invalid_type( + other.unexpected(), + &"string or map", + )), + } } #[inline] @@ -420,7 +467,7 @@ impl<'de> serde::Deserializer<'de> for Value { V: Visitor<'de>, { match self { - Value::Object(v) => visit_object(v, visitor), + Value::Object(v) => v.deserialize_any(visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -436,7 +483,7 @@ impl<'de> serde::Deserializer<'de> for Value { { match self { Value::Array(v) => visit_array(v, visitor), - Value::Object(v) => visit_object(v, visitor), + Value::Object(v) => v.deserialize_any(visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -551,7 +598,7 @@ impl<'de> VariantAccess<'de> for VariantDeserializer { V: Visitor<'de>, { match self.value { - Some(Value::Object(v)) => visit_object(v, visitor), + Some(Value::Object(v)) => v.deserialize_any(visitor), Some(other) => Err(serde::de::Error::invalid_type( other.unexpected(), &"struct variant", @@ -692,21 +739,71 @@ where } } -fn visit_object_ref<'de, V>(object: &'de Map, visitor: V) -> Result -where - V: Visitor<'de>, -{ - let len = object.len(); - let mut deserializer = MapRefDeserializer::new(object); - let map = tri!(visitor.visit_map(&mut deserializer)); - let remaining = deserializer.iter.len(); - if remaining == 0 { - Ok(map) - } else { - Err(serde::de::Error::invalid_length( - len, - &"fewer elements in map", - )) +impl<'de> serde::Deserializer<'de> for &'de Map { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = self.len(); + let mut deserializer = MapRefDeserializer::new(self); + let map = tri!(visitor.visit_map(&mut deserializer)); + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(map) + } else { + Err(serde::de::Error::invalid_length( + len, + &"fewer elements in map", + )) + } + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let mut iter = self.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(serde::de::Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err(serde::de::Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + + visitor.visit_enum(EnumRefDeserializer { + variant, + value: Some(value), + }) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct identifier } } @@ -723,7 +820,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value { 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), + Value::Object(v) => v.deserialize_any(visitor), } } @@ -752,44 +849,24 @@ impl<'de> serde::Deserializer<'de> for &'de Value { fn deserialize_enum( self, - _name: &str, - _variants: &'static [&'static str], + name: &'static str, + variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { - let (variant, value) = match self { - Value::Object(value) => { - let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(serde::de::Error::invalid_value( - Unexpected::Map, - &"map with a single key", - )); - } - }; - // enums are encoded in json as maps with a single key:value pair - if iter.next().is_some() { - return Err(serde::de::Error::invalid_value( - Unexpected::Map, - &"map with a single key", - )); - } - (variant, Some(value)) - } - Value::String(variant) => (variant, None), - other => { - return Err(serde::de::Error::invalid_type( - other.unexpected(), - &"string or map", - )); - } - }; - - visitor.visit_enum(EnumRefDeserializer { variant, value }) + match self { + Value::Object(value) => value.deserialize_enum(name, variants, visitor), + Value::String(variant) => visitor.visit_enum(EnumRefDeserializer { + variant, + value: None, + }), + other => Err(serde::de::Error::invalid_type( + other.unexpected(), + &"string or map", + )), + } } #[inline] @@ -917,7 +994,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value { V: Visitor<'de>, { match self { - Value::Object(v) => visit_object_ref(v, visitor), + Value::Object(v) => v.deserialize_any(visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -933,7 +1010,7 @@ impl<'de> serde::Deserializer<'de> for &'de Value { { match self { Value::Array(v) => visit_array_ref(v, visitor), - Value::Object(v) => visit_object_ref(v, visitor), + Value::Object(v) => v.deserialize_any(visitor), _ => Err(self.invalid_type(&visitor)), } } @@ -1031,7 +1108,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> { V: Visitor<'de>, { match self.value { - Some(Value::Object(v)) => visit_object_ref(v, visitor), + Some(Value::Object(v)) => v.deserialize_any(visitor), Some(other) => Err(serde::de::Error::invalid_type( other.unexpected(), &"struct variant", diff --git a/src/value/from.rs b/src/value/from.rs index ed1e3338b..df4b2038c 100644 --- a/src/value/from.rs +++ b/src/value/from.rs @@ -1,8 +1,8 @@ use super::Value; use crate::map::Map; use crate::number::Number; -use alloc::borrow::Cow; -use alloc::string::{String, ToString}; +use alloc::borrow::{Cow, ToOwned}; +use alloc::string::String; use alloc::vec::Vec; macro_rules! from_integer { @@ -85,7 +85,7 @@ impl From for Value { /// ``` /// use serde_json::Value; /// - /// let s: String = "lorem".to_string(); + /// let s: String = "lorem".to_owned(); /// let x: Value = s.into(); /// ``` fn from(f: String) -> Self { @@ -105,7 +105,7 @@ impl From<&str> for Value { /// let x: Value = s.into(); /// ``` fn from(f: &str) -> Self { - Value::String(f.to_string()) + Value::String(f.to_owned()) } } @@ -126,7 +126,7 @@ impl<'a> From> for Value { /// use serde_json::Value; /// use std::borrow::Cow; /// - /// let s: Cow = Cow::Owned("lorem".to_string()); + /// let s: Cow = Cow::Owned("lorem".to_owned()); /// let x: Value = s.into(); /// ``` fn from(f: Cow<'a, str>) -> Self { @@ -159,7 +159,7 @@ impl From> for Value { /// use serde_json::{Map, Value}; /// /// let mut m = Map::new(); - /// m.insert("Lorem".to_string(), "ipsum".into()); + /// m.insert("Lorem".to_owned(), "ipsum".into()); /// let x: Value = m.into(); /// ``` fn from(f: Map) -> Self { @@ -183,6 +183,12 @@ impl> From> for Value { } } +impl, const N: usize> From<[T; N]> for Value { + fn from(array: [T; N]) -> Self { + Value::Array(array.into_iter().map(Into::into).collect()) + } +} + impl> From<&[T]> for Value { /// Convert a slice to `Value::Array`. /// diff --git a/src/value/index.rs b/src/value/index.rs index c56135b33..4e41a39be 100644 --- a/src/value/index.rs +++ b/src/value/index.rs @@ -137,7 +137,7 @@ mod private { impl Sealed for usize {} impl Sealed for str {} impl Sealed for alloc::string::String {} - impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {} + impl Sealed for &T where T: ?Sized + Sealed {} } /// Used in panic messages. diff --git a/src/value/mod.rs b/src/value/mod.rs index 026f10dcb..6b40f9a52 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -861,6 +861,32 @@ impl Value { pub fn take(&mut self) -> Value { mem::replace(self, Value::Null) } + + /// Reorders the entries of all `Value::Object` nested within this JSON + /// value according to `str`'s usual ordering. + /// + /// If serde_json's "preserve_order" feature is not enabled, this method + /// does no work because all JSON maps are always kept in a sorted state. + /// + /// If serde_json's "preserve_order" feature is enabled, this method + /// destroys the original source order or insertion order of the JSON + /// objects in favor of an alphanumerical order that matches how a BTreeMap + /// with the same contents would be ordered. + pub fn sort_all_objects(&mut self) { + #[cfg(feature = "preserve_order")] + { + match self { + Value::Object(map) => { + map.sort_keys(); + map.values_mut().for_each(Value::sort_all_objects); + } + Value::Array(list) => { + list.iter_mut().for_each(Value::sort_all_objects); + } + _ => {} + } + } + } } /// The default value is `Value::Null`. diff --git a/src/value/partial_eq.rs b/src/value/partial_eq.rs index 46c1dbc33..8626eed7f 100644 --- a/src/value/partial_eq.rs +++ b/src/value/partial_eq.rs @@ -2,30 +2,30 @@ use super::Value; use alloc::string::String; fn eq_i64(value: &Value, other: i64) -> bool { - value.as_i64().map_or(false, |i| i == other) + value.as_i64() == Some(other) } fn eq_u64(value: &Value, other: u64) -> bool { - value.as_u64().map_or(false, |i| i == other) + value.as_u64() == Some(other) } fn eq_f32(value: &Value, other: f32) -> bool { match value { - Value::Number(n) => n.as_f32().map_or(false, |i| i == other), + Value::Number(n) => n.as_f32() == Some(other), _ => false, } } fn eq_f64(value: &Value, other: f64) -> bool { - value.as_f64().map_or(false, |i| i == other) + value.as_f64() == Some(other) } fn eq_bool(value: &Value, other: bool) -> bool { - value.as_bool().map_or(false, |i| i == other) + value.as_bool() == Some(other) } fn eq_str(value: &Value, other: &str) -> bool { - value.as_str().map_or(false, |i| i == other) + value.as_str() == Some(other) } impl PartialEq for Value { diff --git a/src/value/ser.rs b/src/value/ser.rs index b292f9820..a68193437 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -486,47 +486,47 @@ impl serde::Serializer for MapKeySerializer { } fn serialize_bool(self, value: bool) -> Result { - Ok(value.to_string()) + Ok(if value { "true" } else { "false" }.to_owned()) } fn serialize_i8(self, value: i8) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_i16(self, value: i16) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_i32(self, value: i32) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_i64(self, value: i64) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_i128(self, value: i128) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_u8(self, value: u8) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_u16(self, value: u16) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_u32(self, value: u32) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_u64(self, value: u64) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_u128(self, value: u128) -> Result { - Ok(value.to_string()) + Ok(itoa::Buffer::new().format(value).to_owned()) } fn serialize_f32(self, value: f32) -> Result { diff --git a/tests/lexical.rs b/tests/lexical.rs index 368c84478..77967956c 100644 --- a/tests/lexical.rs +++ b/tests/lexical.rs @@ -12,6 +12,7 @@ clippy::let_underscore_untyped, clippy::module_name_repetitions, clippy::needless_late_init, + clippy::question_mark, clippy::shadow_unrelated, clippy::similar_names, clippy::single_match_else, diff --git a/tests/map.rs b/tests/map.rs index c3c64d70b..aa3cb2549 100644 --- a/tests/map.rs +++ b/tests/map.rs @@ -20,7 +20,7 @@ fn test_preserve_order() { fn test_shift_insert() { let mut v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap(); let val = v.as_object_mut().unwrap(); - val.shift_insert(0, "d".to_string(), Value::Null); + val.shift_insert(0, "d".to_owned(), Value::Null); let keys: Vec<_> = val.keys().collect(); assert_eq!(keys, &["d", "b", "a", "c"]); diff --git a/tests/regression.rs b/tests/regression.rs index fb2b25c89..22cca8243 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_lifetimes)] + mod regression { automod::dir!("tests/regression"); } diff --git a/tests/test.rs b/tests/test.rs index dc8c3c22f..d41a2336a 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -269,11 +269,11 @@ fn test_write_list() { fn test_write_object() { test_encode_ok(&[ (treemap!(), "{}"), - (treemap!("a".to_string() => true), "{\"a\":true}"), + (treemap!("a".to_owned() => true), "{\"a\":true}"), ( treemap!( - "a".to_string() => true, - "b".to_string() => false, + "a".to_owned() => true, + "b".to_owned() => false, ), "{\"a\":true,\"b\":false}", ), @@ -282,44 +282,44 @@ fn test_write_object() { test_encode_ok(&[ ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], "{\"a\":{},\"b\":{},\"c\":{}}", ), ( treemap![ - "a".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], "{\"a\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"b\":{},\"c\":{}}", ), ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], - "c".to_string() => treemap![], + "c".to_owned() => treemap![], ], "{\"a\":{},\"b\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"c\":{}}", ), ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![], - "c".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], ], "{\"a\":{},\"b\":{},\"c\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}}}", @@ -331,9 +331,9 @@ fn test_write_object() { test_pretty_encode_ok(&[ ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], pretty_str!({ "a": {}, @@ -343,13 +343,13 @@ fn test_write_object() { ), ( treemap![ - "a".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], pretty_str!({ "a": { @@ -369,13 +369,13 @@ fn test_write_object() { ), ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], - "c".to_string() => treemap![], + "c".to_owned() => treemap![], ], pretty_str!({ "a": {}, @@ -395,12 +395,12 @@ fn test_write_object() { ), ( treemap![ - "a".to_string() => treemap![], - "b".to_string() => treemap![], - "c".to_string() => treemap![ - "a".to_string() => treemap!["a" => vec![1,2,3]], - "b".to_string() => treemap![], - "c".to_string() => treemap![], + "a".to_owned() => treemap![], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![ + "a".to_owned() => treemap!["a" => vec![1,2,3]], + "b".to_owned() => treemap![], + "c".to_owned() => treemap![], ], ], pretty_str!({ @@ -424,15 +424,15 @@ fn test_write_object() { test_pretty_encode_ok(&[ (treemap!(), "{}"), ( - treemap!("a".to_string() => true), + treemap!("a".to_owned() => true), pretty_str!({ "a": true }), ), ( treemap!( - "a".to_string() => true, - "b".to_string() => false, + "a".to_owned() => true, + "b".to_owned() => false, ), pretty_str!( { "a": true, @@ -493,26 +493,26 @@ fn test_write_enum() { test_encode_ok(&[ (Animal::Dog, "\"Dog\""), ( - Animal::Frog("Henry".to_string(), vec![]), + Animal::Frog("Henry".to_owned(), vec![]), "{\"Frog\":[\"Henry\",[]]}", ), ( - Animal::Frog("Henry".to_string(), vec![349]), + Animal::Frog("Henry".to_owned(), vec![349]), "{\"Frog\":[\"Henry\",[349]]}", ), ( - Animal::Frog("Henry".to_string(), vec![349, 102]), + Animal::Frog("Henry".to_owned(), vec![349, 102]), "{\"Frog\":[\"Henry\",[349,102]]}", ), ( Animal::Cat { age: 5, - name: "Kate".to_string(), + name: "Kate".to_owned(), }, "{\"Cat\":{\"age\":5,\"name\":\"Kate\"}}", ), ( - Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]), + Animal::AntHive(vec!["Bob".to_owned(), "Stuart".to_owned()]), "{\"AntHive\":[\"Bob\",\"Stuart\"]}", ), ]); @@ -520,7 +520,7 @@ fn test_write_enum() { test_pretty_encode_ok(&[ (Animal::Dog, "\"Dog\""), ( - Animal::Frog("Henry".to_string(), vec![]), + Animal::Frog("Henry".to_owned(), vec![]), pretty_str!({ "Frog": [ "Henry", @@ -529,7 +529,7 @@ fn test_write_enum() { }), ), ( - Animal::Frog("Henry".to_string(), vec![349]), + Animal::Frog("Henry".to_owned(), vec![349]), pretty_str!({ "Frog": [ "Henry", @@ -540,7 +540,7 @@ fn test_write_enum() { }), ), ( - Animal::Frog("Henry".to_string(), vec![349, 102]), + Animal::Frog("Henry".to_owned(), vec![349, 102]), pretty_str!({ "Frog": [ "Henry", @@ -1117,16 +1117,16 @@ fn test_parse_string() { test_parse_ok(vec![ ("\"\"", String::new()), - ("\"foo\"", "foo".to_string()), - (" \"foo\" ", "foo".to_string()), - ("\"\\\"\"", "\"".to_string()), - ("\"\\b\"", "\x08".to_string()), - ("\"\\n\"", "\n".to_string()), - ("\"\\r\"", "\r".to_string()), - ("\"\\t\"", "\t".to_string()), - ("\"\\u12ab\"", "\u{12ab}".to_string()), - ("\"\\uAB12\"", "\u{AB12}".to_string()), - ("\"\\uD83C\\uDF95\"", "\u{1F395}".to_string()), + ("\"foo\"", "foo".to_owned()), + (" \"foo\" ", "foo".to_owned()), + ("\"\\\"\"", "\"".to_owned()), + ("\"\\b\"", "\x08".to_owned()), + ("\"\\n\"", "\n".to_owned()), + ("\"\\r\"", "\r".to_owned()), + ("\"\\t\"", "\t".to_owned()), + ("\"\\u12ab\"", "\u{12ab}".to_owned()), + ("\"\\uAB12\"", "\u{AB12}".to_owned()), + ("\"\\uD83C\\uDF95\"", "\u{1F395}".to_owned()), ]); } @@ -1184,24 +1184,24 @@ fn test_parse_object() { test_parse_ok(vec![ ("{}", treemap!()), ("{ }", treemap!()), - ("{\"a\":3}", treemap!("a".to_string() => 3u64)), - ("{ \"a\" : 3 }", treemap!("a".to_string() => 3)), + ("{\"a\":3}", treemap!("a".to_owned() => 3u64)), + ("{ \"a\" : 3 }", treemap!("a".to_owned() => 3)), ( "{\"a\":3,\"b\":4}", - treemap!("a".to_string() => 3, "b".to_string() => 4), + treemap!("a".to_owned() => 3, "b".to_owned() => 4), ), ( " { \"a\" : 3 , \"b\" : 4 } ", - treemap!("a".to_string() => 3, "b".to_string() => 4), + treemap!("a".to_owned() => 3, "b".to_owned() => 4), ), ]); test_parse_ok(vec![( "{\"a\": {\"b\": 3, \"c\": 4}}", treemap!( - "a".to_string() => treemap!( - "b".to_string() => 3u64, - "c".to_string() => 4, + "a".to_owned() => treemap!( + "b".to_owned() => 3u64, + "c".to_owned() => 4, ), ), )]); @@ -1248,7 +1248,7 @@ fn test_parse_struct() { inner: vec![Inner { a: (), b: 2, - c: vec!["abc".to_string(), "xyz".to_string()], + c: vec!["abc".to_owned(), "xyz".to_owned()], }], }, ), @@ -1269,7 +1269,7 @@ fn test_parse_struct() { inner: vec![Inner { a: (), b: 2, - c: vec!["abc".to_string(), "xyz".to_string()], + c: vec!["abc".to_owned(), "xyz".to_owned()], }], } ); @@ -1283,7 +1283,7 @@ fn test_parse_struct() { fn test_parse_option() { test_parse_ok(vec![ ("null", None::), - ("\"jodhpurs\"", Some("jodhpurs".to_string())), + ("\"jodhpurs\"", Some("jodhpurs".to_owned())), ]); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -1338,29 +1338,29 @@ fn test_parse_enum() { (" \"Dog\" ", Animal::Dog), ( "{\"Frog\":[\"Henry\",[]]}", - Animal::Frog("Henry".to_string(), vec![]), + Animal::Frog("Henry".to_owned(), vec![]), ), ( " { \"Frog\": [ \"Henry\" , [ 349, 102 ] ] } ", - Animal::Frog("Henry".to_string(), vec![349, 102]), + Animal::Frog("Henry".to_owned(), vec![349, 102]), ), ( "{\"Cat\": {\"age\": 5, \"name\": \"Kate\"}}", Animal::Cat { age: 5, - name: "Kate".to_string(), + name: "Kate".to_owned(), }, ), ( " { \"Cat\" : { \"age\" : 5 , \"name\" : \"Kate\" } } ", Animal::Cat { age: 5, - name: "Kate".to_string(), + name: "Kate".to_owned(), }, ), ( " { \"AntHive\" : [\"Bob\", \"Stuart\"] } ", - Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]), + Animal::AntHive(vec!["Bob".to_owned(), "Stuart".to_owned()]), ), ]); @@ -1377,8 +1377,8 @@ fn test_parse_enum() { "}" ), treemap!( - "a".to_string() => Animal::Dog, - "b".to_string() => Animal::Frog("Henry".to_string(), vec![]), + "a".to_owned() => Animal::Dog, + "b".to_owned() => Animal::Frog("Henry".to_owned(), vec![]), ), )]); } @@ -1653,7 +1653,7 @@ fn test_deserialize_from_stream() { let mut stream = TcpStream::connect("localhost:20000").unwrap(); let request = Message { - message: "hi there".to_string(), + message: "hi there".to_owned(), }; to_writer(&mut stream, &request).unwrap(); @@ -1679,20 +1679,20 @@ fn test_serialize_rejects_adt_keys() { fn test_bytes_ser() { let buf = vec![]; let bytes = Bytes::new(&buf); - assert_eq!(to_string(&bytes).unwrap(), "[]".to_string()); + assert_eq!(to_string(&bytes).unwrap(), "[]".to_owned()); let buf = vec![1, 2, 3]; let bytes = Bytes::new(&buf); - assert_eq!(to_string(&bytes).unwrap(), "[1,2,3]".to_string()); + assert_eq!(to_string(&bytes).unwrap(), "[1,2,3]".to_owned()); } #[test] fn test_byte_buf_ser() { let bytes = ByteBuf::new(); - assert_eq!(to_string(&bytes).unwrap(), "[]".to_string()); + assert_eq!(to_string(&bytes).unwrap(), "[]".to_owned()); let bytes = ByteBuf::from(vec![1, 2, 3]); - assert_eq!(to_string(&bytes).unwrap(), "[1,2,3]".to_string()); + assert_eq!(to_string(&bytes).unwrap(), "[1,2,3]".to_owned()); } #[test] diff --git a/tests/ui/missing_comma.stderr b/tests/ui/missing_comma.stderr index bafa0f891..b0f0e4bd4 100644 --- a/tests/ui/missing_comma.stderr +++ b/tests/ui/missing_comma.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `"2"` +error: no rules expected `"2"` --> tests/ui/missing_comma.rs:4:21 | 4 | json!({ "1": "" "2": "" }); diff --git a/tests/ui/parse_expr.stderr b/tests/ui/parse_expr.stderr index cd3e1c94d..70cd74162 100644 --- a/tests/ui/parse_expr.stderr +++ b/tests/ui/parse_expr.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `~` +error: no rules expected `~` --> tests/ui/parse_expr.rs:4:19 | 4 | json!({ "a" : ~ }); diff --git a/tests/ui/unexpected_after_array_element.stderr b/tests/ui/unexpected_after_array_element.stderr index ef449f764..b848e4dbd 100644 --- a/tests/ui/unexpected_after_array_element.stderr +++ b/tests/ui/unexpected_after_array_element.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `=>` +error: no rules expected `=>` --> tests/ui/unexpected_after_array_element.rs:4:18 | 4 | json!([ true => ]); diff --git a/tests/ui/unexpected_after_map_entry.stderr b/tests/ui/unexpected_after_map_entry.stderr index c62d90ba0..9f77c0729 100644 --- a/tests/ui/unexpected_after_map_entry.stderr +++ b/tests/ui/unexpected_after_map_entry.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `=>` +error: no rules expected `=>` --> tests/ui/unexpected_after_map_entry.rs:4:23 | 4 | json!({ "k": true => }); diff --git a/tests/ui/unexpected_colon.stderr b/tests/ui/unexpected_colon.stderr index 7e47726bc..d47e88161 100644 --- a/tests/ui/unexpected_colon.stderr +++ b/tests/ui/unexpected_colon.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `:` +error: no rules expected `:` --> tests/ui/unexpected_colon.rs:4:13 | 4 | json!({ : true }); diff --git a/tests/ui/unexpected_comma.stderr b/tests/ui/unexpected_comma.stderr index 552f399a5..e30827453 100644 --- a/tests/ui/unexpected_comma.stderr +++ b/tests/ui/unexpected_comma.stderr @@ -1,4 +1,4 @@ -error: no rules expected the token `,` +error: no rules expected `,` --> tests/ui/unexpected_comma.rs:4:17 | 4 | json!({ "a" , "b": true });