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 }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy