Compare commits

...

24 Commits

Author SHA1 Message Date
David Tolnay bd588db067 Release 1.0.121 2021-01-23 13:17:08 -08:00
David Tolnay 8f09aeacdd Merge pull request #1959 from serde-rs/1917
Touch up borrowed field identifiers PR
2021-01-23 13:15:30 -08:00
David Tolnay 0b5c56b0db Touch up documentation from PR #1917 2021-01-23 13:09:37 -08:00
David Tolnay 85de92e6f7 Inline forward_deserializer for bytes deserializers 2021-01-23 13:08:08 -08:00
David Tolnay c858a1fa77 Clean up unnecessary macro_use from PR #1917 2021-01-23 12:59:12 -08:00
David Tolnay d02eb22557 Inline some unnecessary constructor functions from PR #1917 2021-01-23 12:58:42 -08:00
David Tolnay 034fe25d5b Remove redundant unused trait impls from private types from PR #1917 2021-01-23 12:58:42 -08:00
David Tolnay 0a230e8598 Inline forward_deserializer into private::de for Str deserializers
We shouldn't try to use the same macro for public and private types. The
API for a private type can usually be pared much further down to save
compile time, such as Debug and Copy and Clone impls.
2021-01-23 12:57:35 -08:00
David Tolnay b20214d4a0 Undo macro exports from PR #1917
All of these macros are only used internally within the serde crate.
There is no need for them to have #[macro_export] and need to be hidden
from docs.
2021-01-23 12:40:01 -08:00
David Tolnay 34f4b68f77 Fix unneeded clone from PR #1917 2021-01-23 12:40:00 -08:00
David Tolnay 60e08f9545 Format PR #1917 with rustfmt 1.4.32 2021-01-23 12:39:59 -08:00
David Tolnay ba46f45dc5 Merge pull request 1917 from Mingun/borrow-identifier 2021-01-23 12:39:28 -08:00
David Tolnay 44b9567e21 Merge pull request #1958 from jonasbb/duration-panic
Prevent panic when deserializing malformed Duration
2021-01-23 00:45:39 -08:00
Jonas Bushart b276849ce1 Prevent panic when deserializing malformed Duration
std::time::Duration::new can panic. There is no alternative non-panicing constructor.
Check the panic condition beforehand and return an error instead of panicing.

Fixes #1933
2021-01-20 20:41:45 +01:00
David Tolnay 398fba9b1e Release 1.0.120 2021-01-18 22:55:13 -08:00
David Tolnay cd6697b0e4 Merge pull request #1955 from TheJokr/patch-1
Add 128-bit integer support to de::IgnoredAny
2021-01-18 22:54:43 -08:00
Leo Blöcher c162d51866 Add 128-bit integer support to de::IgnoredAny
This fixes the errors that occur when IgnoredAny is deserialized
from anything containing a 128-bit integer somewhere. As IgnoredAny
is used in serde_derive to skip ignored fields in structs, these
errors currently prevent parsing of structs with an ignored field
containing a 128-bit integer in the serialization.
2021-01-19 02:32:26 +01:00
David Tolnay 78a9dbc57e Merge pull request #1948 from Marwes/from_str
refactor: Merge multiple FromStr visitors to a single FromStrVisitor
2021-01-12 13:12:54 -08:00
David Tolnay 391d3ababf Touch up PR 1948 2021-01-12 13:08:50 -08:00
Markus Westerlind 99d9151ce9 refactor: Merge multiple FromStr visitors to a single FromStrVisitor
Only refactors, doesn't actually expose this visitor
2021-01-12 11:32:16 +01:00
Mingun 7a7a182ab6 Allow borrow for field identifiers 2020-10-23 19:03:18 +05:00
Mingun 9e1f573f88 Use forward_deserializer macro for define StrDeserializer for IdentifierDeserializer 2020-10-23 19:03:18 +05:00
Mingun 094f63b86a Introduce a forward_deserializer macro.
It helps to create deserializers that can stop time: save the value and then use visitor to get it later!
2020-10-23 19:03:14 +05:00
Mingun 42fa79455e Make BytesDeserializer public 2020-10-23 12:13:57 +05:00
13 changed files with 290 additions and 179 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.119" # remember to update html_root_url and serde_derive dependency version = "1.0.121" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
@@ -14,7 +14,7 @@ include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APAC
build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
serde_derive = { version = "=1.0.119", optional = true, path = "../serde_derive" } serde_derive = { version = "=1.0.121", optional = true, path = "../serde_derive" }
[dev-dependencies] [dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
+16
View File
@@ -130,12 +130,28 @@ impl<'de> Visitor<'de> for IgnoredAny {
Ok(IgnoredAny) Ok(IgnoredAny)
} }
serde_if_integer128! {
#[inline]
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
}
#[inline] #[inline]
fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> { fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
let _ = x; let _ = x;
Ok(IgnoredAny) Ok(IgnoredAny)
} }
serde_if_integer128! {
#[inline]
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
}
#[inline] #[inline]
fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> { fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
let _ = x; let _ = x;
+53 -72
View File
@@ -1260,24 +1260,7 @@ macro_rules! parse_ip_impl {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
struct IpAddrVisitor; deserializer.deserialize_str(FromStrVisitor::new($expecting))
impl<'de> Visitor<'de> for IpAddrVisitor {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str($expecting)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(IpAddrVisitor)
} else { } else {
<[u8; $size]>::deserialize(deserializer).map(<$ty>::from) <[u8; $size]>::deserialize(deserializer).map(<$ty>::from)
} }
@@ -1405,24 +1388,7 @@ impl<'de> Deserialize<'de> for net::IpAddr {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
struct IpAddrVisitor; deserializer.deserialize_str(FromStrVisitor::new("IP address"))
impl<'de> Visitor<'de> for IpAddrVisitor {
type Value = net::IpAddr;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("IP address")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(IpAddrVisitor)
} else { } else {
use lib::net::IpAddr; use lib::net::IpAddr;
deserialize_enum! { deserialize_enum! {
@@ -1449,24 +1415,7 @@ macro_rules! parse_socket_impl {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
struct SocketAddrVisitor; deserializer.deserialize_str(FromStrVisitor::new($expecting))
impl<'de> Visitor<'de> for SocketAddrVisitor {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str($expecting)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(SocketAddrVisitor)
} else { } else {
<(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port)) <(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port))
} }
@@ -1482,24 +1431,7 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
struct SocketAddrVisitor; deserializer.deserialize_str(FromStrVisitor::new("socket address"))
impl<'de> Visitor<'de> for SocketAddrVisitor {
type Value = net::SocketAddr;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("socket address")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(SocketAddrVisitor)
} else { } else {
use lib::net::SocketAddr; use lib::net::SocketAddr;
deserialize_enum! { deserialize_enum! {
@@ -1917,6 +1849,17 @@ impl<'de> Deserialize<'de> for Duration {
} }
} }
fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
where
E: Error,
{
static NANOS_PER_SEC: u32 = 1_000_000_000;
match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
Some(_) => Ok(()),
None => Err(E::custom("overflow deserializing Duration")),
}
}
struct DurationVisitor; struct DurationVisitor;
impl<'de> Visitor<'de> for DurationVisitor { impl<'de> Visitor<'de> for DurationVisitor {
@@ -1942,6 +1885,7 @@ impl<'de> Deserialize<'de> for Duration {
return Err(Error::invalid_length(1, &self)); return Err(Error::invalid_length(1, &self));
} }
}; };
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
@@ -1975,6 +1919,7 @@ impl<'de> Deserialize<'de> for Duration {
Some(nanos) => nanos, Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos")), None => return Err(<A::Error as Error>::missing_field("nanos")),
}; };
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
} }
@@ -2603,3 +2548,39 @@ atomic_impl! {
atomic_impl! { atomic_impl! {
AtomicI64 AtomicU64 AtomicI64 AtomicU64
} }
#[cfg(feature = "std")]
struct FromStrVisitor<T> {
expecting: &'static str,
ty: PhantomData<T>,
}
#[cfg(feature = "std")]
impl<T> FromStrVisitor<T> {
fn new(expecting: &'static str) -> Self {
FromStrVisitor {
expecting: expecting,
ty: PhantomData,
}
}
}
#[cfg(feature = "std")]
impl<'de, T> Visitor<'de> for FromStrVisitor<T>
where
T: str::FromStr,
T::Err: fmt::Display,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expecting)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
+53 -14
View File
@@ -25,7 +25,7 @@ use lib::*;
use self::private::{First, Second}; use self::private::{First, Second};
use __private::de::size_hint; use __private::de::size_hint;
use de::{self, Expected, IntoDeserializer, SeqAccess}; use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use ser; use ser;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -665,27 +665,26 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&[u8]` with a lifetime tied to another /// A deserializer holding a `&[u8]`. Always calls [`Visitor::visit_bytes`].
/// deserializer.
#[derive(Debug)] #[derive(Debug)]
pub struct BorrowedBytesDeserializer<'de, E> { pub struct BytesDeserializer<'a, E> {
value: &'de [u8], value: &'a [u8],
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(BorrowedBytesDeserializer<'de>); impl<'a, E> BytesDeserializer<'a, E> {
/// Create a new deserializer from the given bytes.
impl<'de, E> BorrowedBytesDeserializer<'de, E> { pub fn new(value: &'a [u8]) -> Self {
/// Create a new borrowed deserializer from the given byte slice. BytesDeserializer {
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
BorrowedBytesDeserializer {
value: value, value: value,
marker: PhantomData, marker: PhantomData,
} }
} }
} }
impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E> impl_copy_clone!(BytesDeserializer<'a>);
impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -693,7 +692,47 @@ where
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
V: de::Visitor<'de>, V: Visitor<'de>,
{
visitor.visit_bytes(self.value)
}
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 enum identifier ignored_any
}
}
/// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer. Always calls [`Visitor::visit_borrowed_bytes`].
#[derive(Debug)]
pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8],
marker: PhantomData<E>,
}
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given borrowed bytes.
pub fn new(value: &'de [u8]) -> Self {
BorrowedBytesDeserializer {
value: value,
marker: PhantomData,
}
}
}
impl_copy_clone!(BorrowedBytesDeserializer<'de>);
impl<'de, E> Deserializer<'de> for BorrowedBytesDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{ {
visitor.visit_borrowed_bytes(self.value) visitor.visit_borrowed_bytes(self.value)
} }
@@ -701,7 +740,7 @@ where
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 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 bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any enum tuple_struct map struct enum identifier ignored_any
} }
} }
+1 -1
View File
@@ -84,7 +84,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.119")] #![doc(html_root_url = "https://docs.rs/serde/1.0.121")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and // Unstable functionality only if the user asks for it. For tracking and
+50 -32
View File
@@ -1,5 +1,6 @@
use lib::*; use lib::*;
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor}; use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -2538,8 +2539,10 @@ mod content {
// } // }
pub trait IdentifierDeserializer<'de, E: Error> { pub trait IdentifierDeserializer<'de, E: Error> {
type Deserializer: Deserializer<'de, Error = E>; type Deserializer: Deserializer<'de, Error = E>;
type BorrowedDeserializer: Deserializer<'de, Error = E>;
fn from(self) -> Self::Deserializer; fn from(self) -> Self::Deserializer;
fn borrowed(self) -> Self::BorrowedDeserializer;
} }
impl<'de, E> IdentifierDeserializer<'de, E> for u32 impl<'de, E> IdentifierDeserializer<'de, E> for u32
@@ -2547,10 +2550,15 @@ where
E: Error, E: Error,
{ {
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer; type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
type BorrowedDeserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
fn from(self) -> Self::Deserializer { fn from(self) -> Self::Deserializer {
self.into_deserializer() self.into_deserializer()
} }
fn borrowed(self) -> Self::BorrowedDeserializer {
self.into_deserializer()
}
} }
pub struct StrDeserializer<'a, E> { pub struct StrDeserializer<'a, E> {
@@ -2558,20 +2566,6 @@ pub struct StrDeserializer<'a, E> {
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
where
E: Error,
{
type Deserializer = StrDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
StrDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E>
where where
E: Error, E: Error,
@@ -2592,26 +2586,12 @@ where
} }
} }
pub struct BytesDeserializer<'a, E> { pub struct BorrowedStrDeserializer<'de, E> {
value: &'a [u8], value: &'de str,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8] impl<'de, E> Deserializer<'de> for BorrowedStrDeserializer<'de, E>
where
E: Error,
{
type Deserializer = BytesDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
BytesDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E>
where where
E: Error, E: Error,
{ {
@@ -2621,7 +2601,7 @@ where
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_bytes(self.value) visitor.visit_borrowed_str(self.value)
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
@@ -2631,6 +2611,44 @@ where
} }
} }
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
where
E: Error,
{
type Deserializer = StrDeserializer<'a, E>;
type BorrowedDeserializer = BorrowedStrDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
StrDeserializer {
value: self,
marker: PhantomData,
}
}
fn borrowed(self) -> Self::BorrowedDeserializer {
BorrowedStrDeserializer {
value: self,
marker: PhantomData,
}
}
}
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8]
where
E: Error,
{
type Deserializer = BytesDeserializer<'a, E>;
type BorrowedDeserializer = BorrowedBytesDeserializer<'a, E>;
fn from(self) -> Self::Deserializer {
BytesDeserializer::new(self)
}
fn borrowed(self) -> Self::BorrowedDeserializer {
BorrowedBytesDeserializer::new(self)
}
}
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors. /// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
/// ///
/// Wraps a mutable reference and calls deserialize_in_place on it. /// Wraps a mutable reference and calls deserialize_in_place on it.
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.119" # remember to update html_root_url version = "1.0.121" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
+64 -52
View File
@@ -1891,17 +1891,23 @@ fn deserialize_generated_identifier(
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() { let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),); let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value))); let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough)) (
Some(ignore_variant),
Some((fallthrough.clone(), fallthrough)),
)
} else if let Some(other_idx) = other_idx { } else if let Some(other_idx) = other_idx {
let ignore_variant = fields[other_idx].1.clone(); let ignore_variant = fields[other_idx].1.clone();
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant)); let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
(None, Some(fallthrough)) (None, Some((fallthrough.clone(), fallthrough)))
} else if is_variant || cattrs.deny_unknown_fields() { } else if is_variant || cattrs.deny_unknown_fields() {
(None, None) (None, None)
} else { } else {
let ignore_variant = quote!(__ignore,); let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore)); let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough)) (
Some(ignore_variant),
Some((fallthrough.clone(), fallthrough)),
)
}; };
let visitor_impl = Stmts(deserialize_identifier( let visitor_impl = Stmts(deserialize_identifier(
@@ -1964,16 +1970,22 @@ fn deserialize_custom_identifier(
if last.attrs.other() { if last.attrs.other() {
let ordinary = &variants[..variants.len() - 1]; let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident)); let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident));
(ordinary, Some(fallthrough)) (ordinary, Some((fallthrough.clone(), fallthrough)))
} else if let Style::Newtype = last.style { } else if let Style::Newtype = last.style {
let ordinary = &variants[..variants.len() - 1]; let ordinary = &variants[..variants.len() - 1];
let deserializer = quote!(_serde::__private::de::IdentifierDeserializer::from(__value)); let fallthrough = |method| {
let fallthrough = quote! { quote! {
_serde::__private::Result::map( _serde::__private::Result::map(
_serde::Deserialize::deserialize(#deserializer), _serde::Deserialize::deserialize(
_serde::__private::de::IdentifierDeserializer::#method(__value)
),
#this::#last_ident) #this::#last_ident)
}
}; };
(ordinary, Some(fallthrough)) (
ordinary,
Some((fallthrough(quote!(from)), fallthrough(quote!(borrowed)))),
)
} else { } else {
(variants, None) (variants, None)
} }
@@ -2045,7 +2057,8 @@ fn deserialize_identifier(
this: &TokenStream, this: &TokenStream,
fields: &[(String, Ident, Vec<String>)], fields: &[(String, Ident, Vec<String>)],
is_variant: bool, is_variant: bool,
fallthrough: Option<TokenStream>, // .0 for referenced data, .1 -- for borrowed
fallthrough: Option<(TokenStream, TokenStream)>,
collect_other_fields: bool, collect_other_fields: bool,
) -> Fragment { ) -> Fragment {
let mut flat_fields = Vec::new(); let mut flat_fields = Vec::new();
@@ -2053,14 +2066,11 @@ fn deserialize_identifier(
flat_fields.extend(aliases.iter().map(|alias| (alias, ident))) flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
} }
let field_strs = flat_fields.iter().map(|(name, _)| name); let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
let field_borrowed_strs = flat_fields.iter().map(|(name, _)| name); let field_bytes: &Vec<_> = &flat_fields
let field_bytes = flat_fields
.iter() .iter()
.map(|(name, _)| Literal::byte_string(name.as_bytes())); .map(|(name, _)| Literal::byte_string(name.as_bytes()))
let field_borrowed_bytes = flat_fields .collect();
.iter()
.map(|(name, _)| Literal::byte_string(name.as_bytes()));
let constructors: &Vec<_> = &flat_fields let constructors: &Vec<_> = &flat_fields
.iter() .iter()
@@ -2111,16 +2121,18 @@ fn deserialize_identifier(
(None, None, None, None) (None, None, None, None)
}; };
let fallthrough_arm = if let Some(fallthrough) = fallthrough { let (fallthrough_arm, fallthrough_borrowed_arm) = if let Some(fallthrough) = fallthrough {
fallthrough fallthrough
} else if is_variant { } else if is_variant {
quote! { let fallthrough = quote! {
_serde::__private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS)) _serde::__private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
} };
(fallthrough.clone(), fallthrough)
} else { } else {
quote! { let fallthrough = quote! {
_serde::__private::Err(_serde::de::Error::unknown_field(__value, FIELDS)) _serde::__private::Err(_serde::de::Error::unknown_field(__value, FIELDS))
} };
(fallthrough.clone(), fallthrough)
}; };
let variant_indices = 0_u64..; let variant_indices = 0_u64..;
@@ -2217,37 +2229,6 @@ fn deserialize_identifier(
{ {
_serde::__private::Ok(__Field::__other(_serde::__private::de::Content::Unit)) _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::Unit))
} }
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(
#field_borrowed_strs => _serde::__private::Ok(#constructors),
)*
_ => {
#value_as_borrowed_str_content
#fallthrough_arm
}
}
}
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(
#field_borrowed_bytes => _serde::__private::Ok(#constructors),
)*
_ => {
#bytes_to_str
#value_as_borrowed_bytes_content
#fallthrough_arm
}
}
}
} }
} else { } else {
quote! { quote! {
@@ -2290,6 +2271,21 @@ fn deserialize_identifier(
} }
} }
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(
#field_strs => _serde::__private::Ok(#constructors),
)*
_ => {
#value_as_borrowed_str_content
#fallthrough_borrowed_arm
}
}
}
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::__private::Result<Self::Value, __E> fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::__private::Result<Self::Value, __E>
where where
__E: _serde::de::Error, __E: _serde::de::Error,
@@ -2305,6 +2301,22 @@ fn deserialize_identifier(
} }
} }
} }
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::__private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(
#field_bytes => _serde::__private::Ok(#constructors),
)*
_ => {
#bytes_to_str
#value_as_borrowed_bytes_content
#fallthrough_borrowed_arm
}
}
}
} }
} }
+1 -1
View File
@@ -13,7 +13,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.119")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.121")]
#![allow(unknown_lints, bare_trait_objects)] #![allow(unknown_lints, bare_trait_objects)]
#![deny(clippy::all, clippy::pedantic)] #![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints // Ignored clippy lints
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.119" # remember to update html_root_url version = "1.0.121" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
+1 -1
View File
@@ -144,7 +144,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.119")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.121")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints // Ignored clippy lints
+24
View File
@@ -90,6 +90,30 @@ fn test_struct() {
); );
} }
#[test]
fn test_field_identifier() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier)]
enum FieldStr<'a> {
#[serde(borrow)]
Str(&'a str),
}
assert_de_tokens(&FieldStr::Str("value"), &[Token::BorrowedStr("value")]);
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier)]
enum FieldBytes<'a> {
#[serde(borrow)]
Bytes(&'a [u8]),
}
assert_de_tokens(
&FieldBytes::Bytes(b"value"),
&[Token::BorrowedBytes(b"value")],
);
}
#[test] #[test]
fn test_cow() { fn test_cow() {
#[derive(Deserialize)] #[derive(Deserialize)]
+21
View File
@@ -1452,4 +1452,25 @@ declare_error_tests! {
], ],
"invalid value: integer `65536`, expected u16", "invalid value: integer `65536`, expected u16",
} }
test_duration_overflow_seq<Duration> {
&[
Token::Seq { len: Some(2) },
Token::U64(u64::max_value()),
Token::U32(1_000_000_000),
Token::SeqEnd,
],
"overflow deserializing Duration",
}
test_duration_overflow_struct<Duration> {
&[
Token::Struct { name: "Duration", len: 2 },
Token::Str("secs"),
Token::U64(u64::max_value()),
Token::Str("nanos"),
Token::U32(1_000_000_000),
Token::StructEnd,
],
"overflow deserializing Duration",
}
} }