Compare commits

...

30 Commits

Author SHA1 Message Date
David Tolnay 807bd20a64 Release 1.0.167 2023-07-06 16:25:48 -07:00
David Tolnay ed9a140348 Merge pull request #2444 from Mingun/dedup
Simplify code for generation of struct deserializers
2023-07-06 16:25:15 -07:00
David Tolnay 2de7c2bea2 Resolve redundant_static_lifetimes clippy lint from PR 2471
error: constants have by default a `'static` lifetime
        --> serde/src/de/impls.rs:2467:24
         |
    2467 |     pub const FIELDS: &'static [&'static str] = &["end"];
         |                       -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
         = note: `-D clippy::redundant-static-lifetimes` implied by `-D clippy::all`

    error: constants have by default a `'static` lifetime
        --> serde/src/de/impls.rs:2467:34
         |
    2467 |     pub const FIELDS: &'static [&'static str] = &["end"];
         |                                 -^^^^^^^---- help: consider removing `'static`: `&str`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes

    error: constants have by default a `'static` lifetime
        --> serde/src/de/impls.rs:2605:24
         |
    2605 |     pub const FIELDS: &'static [&'static str] = &["start"];
         |                       -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes

    error: constants have by default a `'static` lifetime
        --> serde/src/de/impls.rs:2605:34
         |
    2605 |     pub const FIELDS: &'static [&'static str] = &["start"];
         |                                 -^^^^^^^---- help: consider removing `'static`: `&str`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
2023-07-06 16:18:39 -07:00
David Tolnay e6a4a3772e Delete unuseful RangeFull impls 2023-07-06 16:10:21 -07:00
David Tolnay 0fca04e1a6 Merge pull request 2471 from tbu-/pr_more_ranges 2023-07-06 16:09:13 -07:00
David Tolnay 92bfc8d3af Merge pull request #2290 from Mingun/enum-tests-and-cleanup
Remove unused `impl` and unnecessary struct-wrapper around tuple
2023-07-06 16:02:27 -07:00
David Tolnay fa0312ac45 More formatting of doc tests and example code 2023-07-06 15:56:47 -07:00
David Tolnay 1920b694aa Declare required automod dev-dependency
1.0.0 does not work with workspaces.

    error: No such file or directory (os error 2)
     --> test_suite/tests/regression.rs:2:5
      |
    2 |     automod::dir!("tests/regression");
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |
      = note: this error originates in the macro `automod::dir` (in Nightly builds, run with -Z macro-backtrace for more info)
2023-07-06 15:50:32 -07:00
David Tolnay 3bfd41d624 Format doctests using rustfmt's format_code_in_doc_comments
cargo fmt -- --config format_code_in_doc_comments=true
2023-07-06 15:44:32 -07:00
David Tolnay 290449f19b Fix doc tests to work whether or not serde derive feature is used 2023-07-06 15:40:12 -07:00
David Tolnay 3a1f387e69 Merge pull request #2493 from dtolnay/docedition
Update documentation example code to 2021 edition
2023-07-06 15:40:03 -07:00
David Tolnay 541603ac94 Fix doc tests for 2021 edition 2023-07-06 15:36:17 -07:00
David Tolnay 0666fbfa20 Update documentation example code to 2021 edition 2023-07-06 15:17:05 -07:00
David Tolnay ea071ae1d4 Add CI job using minimal-versions 2023-07-05 10:01:33 -07:00
David Tolnay 992a01bad2 Sort dependency features in Cargo.toml 2023-07-04 12:12:31 -07:00
David Tolnay d640b5624f Add no-alloc category to the macro crate also 2023-07-03 14:05:32 -07:00
Mingun 4cf1fec575 Replace several linked variables with enumeration for tuples 2023-06-26 20:55:52 +05:00
Mingun ee7d77defa Replace several linked variables with enumeration for structs 2023-06-26 20:55:52 +05:00
Mingun d0dfc4577e Replace enum with boolean parameter 2023-06-26 20:55:52 +05:00
Mingun bbbd1d24c9 Move deserialize_generated_identifier out from if because the call is same in both arms 2023-06-26 20:55:51 +05:00
Mingun fb3a9e0d7c Simplify check for missing fields 2023-06-26 20:55:51 +05:00
Mingun 5ffebeb6ef Actually, field_names_idents can be calculated using the same code in both cases
When !cattrs.has_flatten() all fields is !field.attrs.flatten()

Co-authored-by: Oliver Schneider <oli-obk@users.noreply.github.com>
2023-06-26 20:55:51 +05:00
Mingun 75db73066b Inline deserialize_struct_as_map_visitor and deserialize_struct_as_struct_visitor 2023-06-26 20:55:51 +05:00
Mingun 2796833c82 Pull up call to deserialize_map because it's identical 2023-06-26 20:55:50 +05:00
Mingun 95730dc7f7 Reorder variables to match order in final quote! 2023-06-26 20:55:50 +05:00
Mingun 795261919f Generate visit_seq only when needed 2023-06-26 20:55:50 +05:00
Mingun 3783a30ae7 Remove TaggedContent, replace it by a tuple
That type does not give any benefits so we can avoid that hidden public but no-API struct
2023-06-24 20:49:49 +05:00
Mingun b61ec84886 Remove implementation of DeserializeSeed for TaggedContentVisitor
It is not used anywhere
2023-06-24 20:48:09 +05:00
Mingun 780a461d92 Generate one deserializer rather than in each arm 2023-06-24 20:48:08 +05:00
Tobias Bucher e76e87a430 Add Serialize/Deserialize impls for Range{From,Full,To}
CC #796
CC #1466
CC #1713
2023-06-09 15:11:44 +02:00
30 changed files with 876 additions and 546 deletions
+10
View File
@@ -128,6 +128,16 @@ jobs:
- uses: dtolnay/rust-toolchain@1.36.0
- run: cd serde && cargo build --no-default-features --features alloc
minimal:
name: Minimal versions
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
- run: cargo generate-lockfile -Z minimal-versions
- run: cargo check --locked --workspace
clippy:
name: Clippy
runs-on: ubuntu-latest
+1 -1
View File
@@ -48,7 +48,7 @@ serde_json = "1.0"
<p></p>
```rust
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
+1 -1
View File
@@ -16,7 +16,7 @@ You may be looking for:
## Serde in action
```rust
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.166" # remember to update html_root_url and serde_derive dependency
version = "1.0.167" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["encoding", "no-std", "no-std::no-alloc"]
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
rust-version = "1.19"
[dependencies]
serde_derive = { version = "=1.0.166", optional = true, path = "../serde_derive" }
serde_derive = { version = "=1.0.167", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" }
+3 -4
View File
@@ -10,13 +10,12 @@ use de::{
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```edition2018
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// ```edition2021
/// use serde::de::{
/// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor,
/// };
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
+280 -4
View File
@@ -1450,7 +1450,7 @@ macro_rules! variant_identifier {
$($variant),*
}
static $variants_name: &'static [&'static str] = &[$(stringify!($variant)),*];
static $variants_name: &[&str] = &[$(stringify!($variant)),*];
impl<'de> Deserialize<'de> for $name_kind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -2256,9 +2256,9 @@ impl<'de> Deserialize<'de> for SystemTime {
//
// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// struct Range {
// start: u64,
// end: u32,
// struct Range<Idx> {
// start: Idx,
// end: Idx,
// }
impl<'de, Idx> Deserialize<'de> for Range<Idx>
where
@@ -2432,6 +2432,282 @@ mod range {
////////////////////////////////////////////////////////////////////////////////
// Similar to:
//
// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// struct RangeFrom<Idx> {
// start: Idx,
// }
impl<'de, Idx> Deserialize<'de> for RangeFrom<Idx>
where
Idx: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let start = try!(deserializer.deserialize_struct(
"RangeFrom",
range_from::FIELDS,
range_from::RangeFromVisitor {
expecting: "struct RangeFrom",
phantom: PhantomData,
},
));
Ok(start..)
}
}
mod range_from {
use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["end"];
// If this were outside of the serde crate, it would just use:
//
// #[derive(Deserialize)]
// #[serde(field_identifier, rename_all = "lowercase")]
enum Field {
End,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`end`")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"end" => Ok(Field::End),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"end" => Ok(Field::End),
_ => {
let value = ::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
pub struct RangeFromVisitor<Idx> {
pub expecting: &'static str,
pub phantom: PhantomData<Idx>,
}
impl<'de, Idx> Visitor<'de> for RangeFromVisitor<Idx>
where
Idx: Deserialize<'de>,
{
type Value = Idx;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expecting)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let end: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
Ok(end)
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
match key {
Field::End => {
if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end"));
}
end = Some(try!(map.next_value()));
}
}
}
let end = match end {
Some(end) => end,
None => return Err(<A::Error as Error>::missing_field("end")),
};
Ok(end)
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Similar to:
//
// #[derive(Deserialize)]
// #[serde(deny_unknown_fields)]
// struct RangeTo<Idx> {
// start: Idx,
// }
impl<'de, Idx> Deserialize<'de> for RangeTo<Idx>
where
Idx: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let end = try!(deserializer.deserialize_struct(
"RangeTo",
range_to::FIELDS,
range_to::RangeToVisitor {
expecting: "struct RangeTo",
phantom: PhantomData,
},
));
Ok(..end)
}
}
mod range_to {
use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["start"];
// If this were outside of the serde crate, it would just use:
//
// #[derive(Deserialize)]
// #[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Start,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`start`")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"start" => Ok(Field::Start),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"start" => Ok(Field::Start),
_ => {
let value = ::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
pub struct RangeToVisitor<Idx> {
pub expecting: &'static str,
pub phantom: PhantomData<Idx>,
}
impl<'de, Idx> Visitor<'de> for RangeToVisitor<Idx>
where
Idx: Deserialize<'de>,
{
type Value = Idx;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expecting)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let start: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
Ok(start)
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut start: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start"));
}
start = Some(try!(map.next_value()));
}
}
}
let start = match start {
Some(start) => start,
None => return Err(<A::Error as Error>::missing_field("start")),
};
Ok(start)
}
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<'de, T> Deserialize<'de> for Bound<T>
where
+27 -31
View File
@@ -162,7 +162,7 @@ macro_rules! declare_error_trait {
///
/// The message should not be capitalized and should not end with a period.
///
/// ```edition2018
/// ```edition2021
/// # use std::str::FromStr;
/// #
/// # struct IpAddr;
@@ -307,7 +307,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// This is used as an argument to the `invalid_type`, `invalid_value`, and
/// `invalid_length` methods of the `Error` trait to build error messages.
///
/// ```edition2018
/// ```edition2021
/// # use std::fmt;
/// #
/// # use serde::de::{self, Unexpected, Visitor};
@@ -432,10 +432,9 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// Within the context of a `Visitor` implementation, the `Visitor` itself
/// (`&self`) is an implementation of this trait.
///
/// ```edition2018
/// # use std::fmt;
/// #
/// ```edition2021
/// # use serde::de::{self, Unexpected, Visitor};
/// # use std::fmt;
/// #
/// # struct Example;
/// #
@@ -457,7 +456,7 @@ impl<'a> fmt::Display for Unexpected<'a> {
///
/// Outside of a `Visitor`, `&"..."` can be used.
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{self, Unexpected};
/// #
/// # fn example<E>() -> Result<(), E>
@@ -465,7 +464,10 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # E: de::Error,
/// # {
/// # let v = true;
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
/// return Err(de::Error::invalid_type(
/// Unexpected::Bool(v),
/// &"a negative integer",
/// ));
/// # }
/// ```
pub trait Expected {
@@ -577,7 +579,7 @@ pub trait Deserialize<'de>: Sized {
/// from the input string, but a `from_reader` function may only deserialize
/// owned data.
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{Deserialize, DeserializeOwned};
/// # use std::io::{Read, Result};
/// #
@@ -616,7 +618,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
///
/// The canonical API for stateless deserialization looks like this:
///
/// ```edition2018
/// ```edition2021
/// # use serde::Deserialize;
/// #
/// # enum Error {}
@@ -630,7 +632,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// Adjusting an API like this to support stateful deserialization is a matter
/// of accepting a seed as input:
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::DeserializeSeed;
/// #
/// # enum Error {}
@@ -663,12 +665,11 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// into it. This requires stateful deserialization using the `DeserializeSeed`
/// trait.
///
/// ```edition2018
/// ```edition2021
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
///
/// // A DeserializeSeed implementation that uses stateful deserialization to
/// // append array elements onto the end of an existing vector. The preexisting
/// // state ("seed") in this case is the Vec<T>. The `deserialize` method of
@@ -709,7 +710,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// {
/// // Decrease the number of reallocations if there are many elements
/// if let Some(size_hint) = seq.size_hint() {
/// self.0.reserve(size_hint);
/// self.0.reserve(size_hint);
/// }
///
/// // Visit each element in the inner array and push it onto
@@ -1158,7 +1159,7 @@ pub trait Deserializer<'de>: Sized {
/// human-readable one and binary formats like Postcard will prefer the
/// compact one.
///
/// ```edition2018
/// ```edition2021
/// # use std::ops::Add;
/// # use std::str::FromStr;
/// #
@@ -1249,10 +1250,9 @@ pub trait Deserializer<'de>: Sized {
///
/// # Example
///
/// ```edition2018
/// # use std::fmt;
/// #
/// ```edition2021
/// # use serde::de::{self, Unexpected, Visitor};
/// # use std::fmt;
/// #
/// /// A visitor that deserializes a long string - a string containing at least
/// /// some minimum number of bytes.
@@ -1290,7 +1290,7 @@ pub trait Visitor<'de>: Sized {
/// "an integer between 0 and 64". The message should not be capitalized and
/// should not end with a period.
///
/// ```edition2018
/// ```edition2021
/// # use std::fmt;
/// #
/// # struct S {
@@ -2035,7 +2035,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed:
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// #
/// # struct X;
@@ -2075,7 +2075,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed:
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// #
/// # struct X;
@@ -2131,7 +2131,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed:
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// #
/// # struct X;
@@ -2148,11 +2148,7 @@ pub trait VariantAccess<'de>: Sized {
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// fn tuple_variant<V>(
/// self,
/// _len: usize,
/// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// {
@@ -2178,7 +2174,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed:
///
/// ```edition2018
/// ```edition2021
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// #
/// # struct X;
@@ -2238,10 +2234,10 @@ pub trait VariantAccess<'de>: Sized {
///
/// # Example
///
/// ```edition2018
/// ```edition2021
/// use serde::de::{value, Deserialize, IntoDeserializer};
/// use serde_derive::Deserialize;
/// use std::str::FromStr;
/// use serde::Deserialize;
/// use serde::de::{value, IntoDeserializer};
///
/// #[derive(Deserialize)]
/// enum Setting {
+3 -3
View File
@@ -1,10 +1,10 @@
//! Building blocks for deserializing basic values using the `IntoDeserializer`
//! trait.
//!
//! ```edition2018
//! ```edition2021
//! use serde::de::{value, Deserialize, IntoDeserializer};
//! use serde_derive::Deserialize;
//! use std::str::FromStr;
//! use serde::Deserialize;
//! use serde::de::{value, IntoDeserializer};
//!
//! #[derive(Deserialize)]
//! enum Setting {
+3 -3
View File
@@ -9,7 +9,7 @@
/// or do not target platforms that lack 128-bit integers, do not need to
/// bother with this macro and may assume support for 128-bit integers.
///
/// ```edition2018
/// ```edition2021
/// # use serde::__private::doc::Error;
/// #
/// # struct MySerializer;
@@ -50,7 +50,7 @@
/// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens.
///
/// ```edition2018
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {
/// $($tt)*
@@ -61,7 +61,7 @@
/// When built without support for 128-bit integers, this macro expands to
/// nothing.
///
/// ```edition2018
/// ```edition2021
/// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {};
/// }
+2 -2
View File
@@ -93,7 +93,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.166")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.167")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
@@ -180,7 +180,7 @@ mod lib {
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::num::Wrapping;
pub use self::core::ops::Range;
pub use self::core::ops::{Range, RangeFrom, RangeTo};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
+4 -5
View File
@@ -11,7 +11,7 @@
/// input. This requires repetitive implementations of all the [`Deserializer`]
/// trait methods.
///
/// ```edition2018
/// ```edition2021
/// # use serde::forward_to_deserialize_any;
/// # use serde::de::{value, Deserializer, Visitor};
/// #
@@ -47,7 +47,7 @@
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
/// You can choose which methods to forward.
///
/// ```edition2018
/// ```edition2021
/// # use serde::forward_to_deserialize_any;
/// # use serde::de::{value, Deserializer, Visitor};
/// #
@@ -78,11 +78,10 @@
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```edition2018
/// # use std::marker::PhantomData;
/// #
/// ```edition2021
/// # use serde::forward_to_deserialize_any;
/// # use serde::de::{value, Deserializer, Visitor};
/// # use std::marker::PhantomData;
/// #
/// # struct MyDeserializer<V>(PhantomData<V>);
/// #
+7 -35
View File
@@ -797,19 +797,13 @@ mod content {
/// Used by generated code to deserialize an internally tagged enum.
///
/// Not public API.
pub struct TaggedContent<'de, T> {
pub tag: T,
pub content: Content<'de>,
}
/// Not public API.
pub struct TaggedContentVisitor<'de, T> {
pub struct TaggedContentVisitor<T> {
tag_name: &'static str,
expecting: &'static str,
value: PhantomData<TaggedContent<'de, T>>,
value: PhantomData<T>,
}
impl<'de, T> TaggedContentVisitor<'de, T> {
impl<T> TaggedContentVisitor<T> {
/// Visitor for the content of an internally tagged enum with the given
/// tag name.
pub fn new(name: &'static str, expecting: &'static str) -> Self {
@@ -821,27 +815,11 @@ mod content {
}
}
impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T>
impl<'de, T> Visitor<'de> for TaggedContentVisitor<T>
where
T: Deserialize<'de>,
{
type Value = TaggedContent<'de, T>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
// Internally tagged enums are only supported in self-describing
// formats.
deserializer.deserialize_any(self)
}
}
impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T>
where
T: Deserialize<'de>,
{
type Value = TaggedContent<'de, T>;
type Value = (T, Content<'de>);
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(self.expecting)
@@ -858,10 +836,7 @@ mod content {
}
};
let rest = de::value::SeqAccessDeserializer::new(seq);
Ok(TaggedContent {
tag,
content: try!(Content::deserialize(rest)),
})
Ok((tag, try!(Content::deserialize(rest))))
}
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
@@ -886,10 +861,7 @@ mod content {
}
match tag {
None => Err(de::Error::missing_field(self.tag_name)),
Some(tag) => Ok(TaggedContent {
tag,
content: Content::Map(vec),
}),
Some(tag) => Ok((tag, Content::Map(vec))),
}
}
}
+3 -2
View File
@@ -17,8 +17,9 @@ macro_rules! fmt_primitives {
};
}
/// ```edition2018
/// use serde::Serialize;
/// ```edition2021
/// use serde::ser::Serialize;
/// use serde_derive::Serialize;
/// use std::fmt::{self, Display};
///
/// #[derive(Serialize)]
+34
View File
@@ -257,6 +257,23 @@ where
////////////////////////////////////////////////////////////////////////////////
impl<Idx> Serialize for RangeFrom<Idx>
where
Idx: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeFrom", 1));
try!(state.serialize_field("start", &self.start));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx>
where
@@ -276,6 +293,23 @@ where
////////////////////////////////////////////////////////////////////////////////
impl<Idx> Serialize for RangeTo<Idx>
where
Idx: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeTo", 1));
try!(state.serialize_field("end", &self.end));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T>
where
+1 -1
View File
@@ -15,7 +15,7 @@ use ser::{
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
///
/// ```edition2018
/// ```edition2021
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::__private::doc::Error;
/// #
+60 -64
View File
@@ -149,7 +149,7 @@ macro_rules! declare_error_trait {
/// For example, a filesystem [`Path`] may refuse to serialize
/// itself if it contains invalid UTF-8 data.
///
/// ```edition2018
/// ```edition2021
/// # struct Path;
/// #
/// # impl Path {
@@ -221,7 +221,7 @@ pub trait Serialize {
/// See the [Implementing `Serialize`] section of the manual for more
/// information about how to implement this method.
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Person {
@@ -388,7 +388,7 @@ pub trait Serializer: Sized {
/// Serialize a `bool` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -410,7 +410,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -432,7 +432,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -454,7 +454,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -472,7 +472,7 @@ pub trait Serializer: Sized {
/// Serialize an `i64` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -491,7 +491,7 @@ pub trait Serializer: Sized {
serde_if_integer128! {
/// Serialize an `i128` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -520,7 +520,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -542,7 +542,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -564,7 +564,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -582,7 +582,7 @@ pub trait Serializer: Sized {
/// Serialize a `u64` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -601,7 +601,7 @@ pub trait Serializer: Sized {
serde_if_integer128! {
/// Serialize a `u128` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -630,7 +630,7 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `f64` and
/// forward to `serialize_f64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -648,7 +648,7 @@ pub trait Serializer: Sized {
/// Serialize an `f64` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -669,7 +669,7 @@ pub trait Serializer: Sized {
/// If the format does not support characters, it is reasonable to serialize
/// it as a single element `str` or a `u32`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -687,7 +687,7 @@ pub trait Serializer: Sized {
/// Serialize a `&str`.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -711,7 +711,7 @@ pub trait Serializer: Sized {
/// `serialize_seq`. If forwarded, the implementation looks usually just
/// like this:
///
/// ```edition2018
/// ```edition2021
/// # use serde::ser::{Serializer, SerializeSeq};
/// # use serde::__private::doc::Error;
/// #
@@ -740,7 +740,7 @@ pub trait Serializer: Sized {
/// Serialize a [`None`] value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::{Serialize, Serializer};
/// #
/// # enum Option<T> {
@@ -773,7 +773,7 @@ pub trait Serializer: Sized {
/// Serialize a [`Some(T)`] value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::{Serialize, Serializer};
/// #
/// # enum Option<T> {
@@ -808,7 +808,7 @@ pub trait Serializer: Sized {
/// Serialize a `()` value.
///
/// ```edition2018
/// ```edition2021
/// # use serde::Serializer;
/// #
/// # serde::__private_serialize!();
@@ -828,7 +828,7 @@ pub trait Serializer: Sized {
///
/// A reasonable implementation would be to forward to `serialize_unit`.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
///
/// struct Nothing;
@@ -850,7 +850,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, and the `variant` is the name of the
/// variant.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
///
/// enum E {
@@ -883,7 +883,7 @@ pub trait Serializer: Sized {
/// wrappers around the data they contain. A reasonable implementation would
/// be to forward to `value.serialize(self)`.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
///
/// struct Millimeters(u8);
@@ -911,7 +911,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, and the `variant` is the name of the
/// variant. The `value` is the data contained within this newtype variant.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
///
/// enum E {
@@ -949,7 +949,7 @@ pub trait Serializer: Sized {
/// not be computable before the sequence is iterated. Some serializers only
/// support sequences whose length is known up front.
///
/// ```edition2018
/// ```edition2021
/// # use std::marker::PhantomData;
/// #
/// # struct Vec<T>(PhantomData<T>);
@@ -962,14 +962,14 @@ pub trait Serializer: Sized {
/// #
/// # impl<'a, T> IntoIterator for &'a Vec<T> {
/// # type Item = &'a T;
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
/// #
/// # fn into_iter(self) -> Self::IntoIter {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// use serde::ser::{Serialize, SerializeSeq, Serializer};
///
/// impl<T> Serialize for Vec<T>
/// where
@@ -994,8 +994,8 @@ pub trait Serializer: Sized {
/// This call must be followed by zero or more calls to `serialize_element`,
/// then a call to `end`.
///
/// ```edition2018
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
///
/// # mod fool {
/// # trait Serialize {}
@@ -1024,7 +1024,7 @@ pub trait Serializer: Sized {
/// }
/// ```
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
///
/// const VRAM_SIZE: usize = 386;
@@ -1052,7 +1052,7 @@ pub trait Serializer: Sized {
/// The `name` is the name of the tuple struct and the `len` is the number
/// of data fields that will be serialized.
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
///
/// struct Rgb(u8, u8, u8);
@@ -1084,7 +1084,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
///
/// enum E {
@@ -1130,7 +1130,7 @@ pub trait Serializer: Sized {
/// be computable before the map is iterated. Some serializers only support
/// maps whose length is known up front.
///
/// ```edition2018
/// ```edition2021
/// # use std::marker::PhantomData;
/// #
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
@@ -1143,14 +1143,14 @@ pub trait Serializer: Sized {
/// #
/// # impl<'a, K, V> IntoIterator for &'a HashMap<K, V> {
/// # type Item = (&'a K, &'a V);
/// # type IntoIter = Box<Iterator<Item = (&'a K, &'a V)>>;
/// # type IntoIter = Box<dyn Iterator<Item = (&'a K, &'a V)>>;
/// #
/// # fn into_iter(self) -> Self::IntoIter {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use serde::ser::{Serialize, Serializer, SerializeMap};
/// use serde::ser::{Serialize, SerializeMap, Serializer};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where
@@ -1178,7 +1178,7 @@ pub trait Serializer: Sized {
/// The `name` is the name of the struct and the `len` is the number of
/// data fields that will be serialized.
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Rgb {
@@ -1214,7 +1214,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
///
/// enum E {
@@ -1256,7 +1256,7 @@ pub trait Serializer: Sized {
/// using [`serialize_seq`]. Implementors should not need to override this
/// method.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
///
/// struct SecretlyOneHigher {
@@ -1304,7 +1304,7 @@ pub trait Serializer: Sized {
/// using [`serialize_map`]. Implementors should not need to override this
/// method.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Serialize, Serializer};
/// use std::collections::BTreeSet;
///
@@ -1355,7 +1355,7 @@ pub trait Serializer: Sized {
/// delegates to [`serialize_str`]. Serializers are encouraged to provide a
/// more efficient implementation if possible.
///
/// ```edition2018
/// ```edition2021
/// # struct DateTime;
/// #
/// # impl DateTime {
@@ -1370,9 +1370,7 @@ pub trait Serializer: Sized {
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset()))
/// }
/// }
/// ```
@@ -1393,7 +1391,7 @@ pub trait Serializer: Sized {
/// of this method. If no more sensible behavior is possible, the
/// implementation is expected to return an error.
///
/// ```edition2018
/// ```edition2021
/// # struct DateTime;
/// #
/// # impl DateTime {
@@ -1408,9 +1406,7 @@ pub trait Serializer: Sized {
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
/// self.offset()))
/// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset()))
/// }
/// }
/// ```
@@ -1428,7 +1424,7 @@ pub trait Serializer: Sized {
/// human-readable one and binary formats like Postcard will prefer the
/// compact one.
///
/// ```edition2018
/// ```edition2021
/// # use std::fmt::{self, Display};
/// #
/// # struct Timestamp;
@@ -1477,7 +1473,7 @@ pub trait Serializer: Sized {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// # use std::marker::PhantomData;
/// #
/// # struct Vec<T>(PhantomData<T>);
@@ -1490,13 +1486,13 @@ pub trait Serializer: Sized {
/// #
/// # impl<'a, T> IntoIterator for &'a Vec<T> {
/// # type Item = &'a T;
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
/// # fn into_iter(self) -> Self::IntoIter {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
/// use serde::ser::{Serialize, SerializeSeq, Serializer};
///
/// impl<T> Serialize for Vec<T>
/// where
@@ -1541,8 +1537,8 @@ pub trait SerializeSeq {
///
/// # Example use
///
/// ```edition2018
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
///
/// # mod fool {
/// # trait Serialize {}
@@ -1571,7 +1567,7 @@ pub trait SerializeSeq {
/// }
/// ```
///
/// ```edition2018
/// ```edition2021
/// # use std::marker::PhantomData;
/// #
/// # struct Array<T>(PhantomData<T>);
@@ -1584,13 +1580,13 @@ pub trait SerializeSeq {
/// #
/// # impl<'a, T> IntoIterator for &'a Array<T> {
/// # type Item = &'a T;
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
/// # fn into_iter(self) -> Self::IntoIter {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
///
/// # mod fool {
/// # trait Serialize {}
@@ -1641,7 +1637,7 @@ pub trait SerializeTuple {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
///
/// struct Rgb(u8, u8, u8);
@@ -1686,7 +1682,7 @@ pub trait SerializeTupleStruct {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
///
/// enum E {
@@ -1744,7 +1740,7 @@ pub trait SerializeTupleVariant {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// # use std::marker::PhantomData;
/// #
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
@@ -1757,14 +1753,14 @@ pub trait SerializeTupleVariant {
/// #
/// # impl<'a, K, V> IntoIterator for &'a HashMap<K, V> {
/// # type Item = (&'a K, &'a V);
/// # type IntoIter = Box<Iterator<Item = (&'a K, &'a V)>>;
/// # type IntoIter = Box<dyn Iterator<Item = (&'a K, &'a V)>>;
/// #
/// # fn into_iter(self) -> Self::IntoIter {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use serde::ser::{Serialize, Serializer, SerializeMap};
/// use serde::ser::{Serialize, SerializeMap, Serializer};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where
@@ -1855,7 +1851,7 @@ pub trait SerializeMap {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
///
/// struct Rgb {
@@ -1915,7 +1911,7 @@ pub trait SerializeStruct {
///
/// # Example use
///
/// ```edition2018
/// ```edition2021
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
///
/// enum E {
+3 -3
View File
@@ -9,7 +9,7 @@ use lib::{Debug, Display};
/// generally provide their error types with a `std::error::Error` impl
/// directly:
///
/// ```edition2018
/// ```edition2021
/// #[derive(Debug)]
/// struct MySerError {...}
///
@@ -29,7 +29,7 @@ use lib::{Debug, Display};
/// std = ["serde/std"]
/// ```
///
/// ```edition2018
/// ```edition2021
/// #[cfg(feature = "std")]
/// impl std::error::Error for MySerError {}
/// ```
@@ -37,7 +37,7 @@ use lib::{Debug, Display};
/// ... or else provide the std Error impl unconditionally via Serde's
/// re-export:
///
/// ```edition2018
/// ```edition2021
/// impl serde::ser::StdError for MySerError {}
/// ```
pub trait Error: Debug + Display {
+2 -2
View File
@@ -1,8 +1,8 @@
[package]
name = "serde_derive"
version = "1.0.166" # remember to update html_root_url
version = "1.0.167" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std"]
categories = ["no-std", "no-std::no-alloc"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
documentation = "https://serde.rs/derive.html"
homepage = "https://serde.rs"
+175 -188
View File
@@ -287,10 +287,10 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
match &cont.data {
Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, fields) => {
deserialize_struct(None, params, fields, &cont.attrs, None, &Untagged::No)
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
}
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple(None, params, fields, &cont.attrs, None)
deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
}
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
}
@@ -438,12 +438,20 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
}
}
enum TupleForm<'a> {
Tuple,
/// Contains a variant name
ExternallyTagged(&'a syn::Ident),
/// Contains a variant name and an intermediate deserializer from which actual
/// deserialization will be performed
Untagged(&'a syn::Ident, TokenStream),
}
fn deserialize_tuple(
variant_ident: Option<&syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
form: TupleForm,
) -> Fragment {
assert!(!cattrs.has_flatten());
@@ -468,23 +476,27 @@ fn deserialize_tuple(
quote!(#this_value)
};
let is_enum = variant_ident.is_some();
let type_path = match variant_ident {
Some(variant_ident) => quote!(#construct::#variant_ident),
None => construct,
let type_path = match form {
TupleForm::Tuple => construct,
TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => {
quote!(#construct::#variant_ident)
}
};
let expecting = match variant_ident {
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
None => format!("tuple struct {}", params.type_name()),
let expecting = match form {
TupleForm::Tuple => format!("tuple struct {}", params.type_name()),
TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => {
format!("tuple variant {}::{}", params.type_name(), variant_ident)
}
};
let expecting = cattrs.expecting().unwrap_or(&expecting);
let nfields = fields.len();
let visit_newtype_struct = if !is_enum && nfields == 1 {
Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
} else {
None
let visit_newtype_struct = match form {
TupleForm::Tuple if nfields == 1 => {
Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
}
_ => None,
};
let visit_seq = Stmts(deserialize_seq(
@@ -497,16 +509,25 @@ fn deserialize_tuple(
lifetime: _serde::__private::PhantomData,
}
};
let dispatch = if let Some(deserializer) = deserializer {
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr))
} else if is_enum {
quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr))
} else if nfields == 1 {
let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
} else {
let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr))
let dispatch = match form {
TupleForm::Tuple if nfields == 1 => {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)
}
}
TupleForm::Tuple => {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)
}
}
TupleForm::ExternallyTagged(_) => quote! {
_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)
},
TupleForm::Untagged(_, deserializer) => quote! {
_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)
},
};
let visitor_var = if field_count == 0 {
@@ -901,21 +922,24 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
}
}
enum Untagged {
Yes,
No,
enum StructForm<'a> {
Struct,
/// Contains a variant name
ExternallyTagged(&'a syn::Ident),
/// Contains a variant name and an intermediate deserializer from which actual
/// deserialization will be performed
InternallyTagged(&'a syn::Ident, TokenStream),
/// Contains a variant name and an intermediate deserializer from which actual
/// deserialization will be performed
Untagged(&'a syn::Ident, TokenStream),
}
fn deserialize_struct(
variant_ident: Option<&syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
untagged: &Untagged,
form: StructForm,
) -> Fragment {
let is_enum = variant_ident.is_some();
let this_type = &params.this_type;
let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
@@ -932,83 +956,74 @@ fn deserialize_struct(
quote!(#this_value)
};
let type_path = match variant_ident {
Some(variant_ident) => quote!(#construct::#variant_ident),
None => construct,
let type_path = match form {
StructForm::Struct => construct,
StructForm::ExternallyTagged(variant_ident)
| StructForm::InternallyTagged(variant_ident, _)
| StructForm::Untagged(variant_ident, _) => quote!(#construct::#variant_ident),
};
let expecting = match variant_ident {
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", params.type_name()),
let expecting = match form {
StructForm::Struct => format!("struct {}", params.type_name()),
StructForm::ExternallyTagged(variant_ident)
| StructForm::InternallyTagged(variant_ident, _)
| StructForm::Untagged(variant_ident, _) => {
format!("struct variant {}::{}", params.type_name(), variant_ident)
}
};
let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq(
&type_path, params, fields, true, cattrs, expecting,
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
// Skip fields that shouldn't be deserialized or that were flattened,
// so they don't appear in the storage in their literal form
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let field_visitor = Stmts(deserialize_generated_identifier(
&field_names_idents,
cattrs,
false,
None,
));
let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
deserialize_struct_as_map_visitor(&type_path, params, fields, cattrs)
} else {
deserialize_struct_as_struct_visitor(&type_path, params, fields, cattrs)
};
let field_visitor = Stmts(field_visitor);
let fields_stmt = fields_stmt.map(Stmts);
let visit_map = Stmts(visit_map);
let visitor_expr = quote! {
__Visitor {
marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
}
};
let need_seed = deserializer.is_none();
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
}
} else if is_enum && cattrs.has_flatten() {
quote! {
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
}
} else if cattrs.has_flatten() {
quote! {
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
}
} else {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
quote!(_)
} else {
quote!(mut __seq)
};
// untagged struct variants do not get a visit_seq method. The same applies to
// structs that only have a map representation.
let visit_seq = match *untagged {
Untagged::No if !cattrs.has_flatten() => Some(quote! {
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
}),
_ => None,
};
let visit_seq = match form {
StructForm::Untagged(..) => None,
_ if cattrs.has_flatten() => None,
_ => {
let mut_seq = if field_names_idents.is_empty() {
quote!(_)
} else {
quote!(mut __seq)
};
let visitor_seed = if need_seed && is_enum && cattrs.has_flatten() {
Some(quote! {
let visit_seq = Stmts(deserialize_seq(
&type_path, params, fields, true, cattrs, expecting,
));
Some(quote! {
#[inline]
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
})
}
};
let visit_map = Stmts(deserialize_map(&type_path, params, fields, cattrs));
let visitor_seed = match form {
StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! {
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -1019,9 +1034,51 @@ fn deserialize_struct(
_serde::Deserializer::deserialize_map(__deserializer, self)
}
}
})
} else {
}),
_ => None,
};
let fields_stmt = if cattrs.has_flatten() {
None
} else {
let field_names = field_names_idents
.iter()
.flat_map(|(_, _, aliases)| aliases);
Some(quote! {
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
})
};
let visitor_expr = quote! {
__Visitor {
marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
}
};
let dispatch = match form {
StructForm::Struct if cattrs.has_flatten() => quote! {
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
},
StructForm::Struct => {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
}
StructForm::ExternallyTagged(_) if cattrs.has_flatten() => quote! {
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
},
StructForm::ExternallyTagged(_) => quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
},
StructForm::InternallyTagged(_, deserializer) => quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
},
StructForm::Untagged(_, deserializer) => quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
},
};
quote_block! {
@@ -1356,9 +1413,7 @@ fn deserialize_internally_tagged_enum(
params,
variant,
cattrs,
quote! {
_serde::__private::de::ContentDeserializer::<__D::Error>::new(__tagged.content)
},
quote!(__deserializer),
));
quote! {
@@ -1374,11 +1429,12 @@ fn deserialize_internally_tagged_enum(
#variants_stmt
let __tagged = try!(_serde::Deserializer::deserialize_any(
let (__tag, __content) = try!(_serde::Deserializer::deserialize_any(
__deserializer,
_serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting)));
let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content);
match __tagged.tag {
match __tag {
#(#variant_arms)*
}
}
@@ -1769,16 +1825,17 @@ fn deserialize_externally_tagged_variant(
&variant.fields[0],
cattrs,
),
Style::Tuple => {
deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None)
}
Style::Struct => deserialize_struct(
Some(variant_ident),
Style::Tuple => deserialize_tuple(
params,
&variant.fields,
cattrs,
None,
&Untagged::No,
TupleForm::ExternallyTagged(variant_ident),
),
Style::Struct => deserialize_struct(
params,
&variant.fields,
cattrs,
StructForm::ExternallyTagged(variant_ident),
),
}
}
@@ -1818,12 +1875,10 @@ fn deserialize_internally_tagged_variant(
&deserializer,
),
Style::Struct => deserialize_struct(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
&Untagged::No,
StructForm::InternallyTagged(variant_ident, deserializer),
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
@@ -1870,19 +1925,16 @@ fn deserialize_untagged_variant(
&deserializer,
),
Style::Tuple => deserialize_tuple(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
TupleForm::Untagged(variant_ident, deserializer),
),
Style::Struct => deserialize_struct(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
&Untagged::Yes,
StructForm::Untagged(variant_ident, deserializer),
),
}
}
@@ -2423,71 +2475,6 @@ fn deserialize_identifier(
}
}
fn deserialize_struct_as_struct_visitor(
struct_path: &TokenStream,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> (Fragment, Option<Fragment>, Fragment) {
assert!(!cattrs.has_flatten());
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let fields_stmt = {
let field_names = field_names_idents
.iter()
.flat_map(|(_, _, aliases)| aliases);
quote_block! {
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
};
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
(field_visitor, Some(fields_stmt), visit_map)
}
fn deserialize_struct_as_map_visitor(
struct_path: &TokenStream,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> (Fragment, Option<Fragment>, Fragment) {
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
(field_visitor, None, visit_map)
}
fn deserialize_map(
struct_path: &TokenStream,
params: &Parameters,
+3 -3
View File
@@ -1,7 +1,7 @@
//! This crate provides Serde's two derive macros.
//!
//! ```edition2018
//! # use serde_derive::{Serialize, Deserialize};
//! ```edition2021
//! # use serde_derive::{Deserialize, Serialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
@@ -13,7 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.166")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.167")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![allow(
+1 -1
View File
@@ -17,7 +17,7 @@ path = "lib.rs"
[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0.21", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
syn = { version = "2.0.21", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.166" # remember to update html_root_url
version = "1.0.167" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["development-tools::testing"]
@@ -18,7 +18,7 @@ rust-version = "1.19"
serde = { version = "1.0.60", path = "../serde" }
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
serde = { version = "1.0", path = "../serde", features = ["rc"] }
serde_derive = { version = "1.0", path = "../serde_derive" }
[lib]
+54 -40
View File
@@ -8,8 +8,8 @@ use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -19,14 +19,17 @@ use std::fmt::Debug;
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// assert_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
@@ -39,8 +42,8 @@ where
/// Asserts that `value` serializes to the given `tokens`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -50,14 +53,17 @@ where
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_ser_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// assert_ser_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
@@ -78,23 +84,24 @@ where
/// Asserts that `value` serializes to the given `tokens`, and then yields
/// `error`.
///
/// ```edition2018
/// ```edition2021
/// use serde_derive::Serialize;
/// use serde_test::{assert_ser_tokens_error, Token};
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// use serde::Serialize;
/// use serde_test::{assert_ser_tokens_error, Token};
///
/// #[derive(Serialize)]
/// struct Example {
/// lock: Arc<Mutex<u32>>,
/// }
///
/// fn main() {
/// let example = Example { lock: Arc::new(Mutex::new(0)) };
/// let example = Example {
/// lock: Arc::new(Mutex::new(0)),
/// };
/// let lock = example.lock.clone();
///
/// let _ = thread::spawn(move || {
/// let thread = thread::spawn(move || {
/// // This thread will acquire the mutex first, unwrapping the result
/// // of `lock` because the lock has not been poisoned.
/// let _guard = lock.lock().unwrap();
@@ -102,10 +109,14 @@ where
/// // This panic while holding the lock (`_guard` is in scope) will
/// // poison the mutex.
/// panic!()
/// }).join();
/// });
/// thread.join();
///
/// let expected = &[
/// Token::Struct { name: "Example", len: 1 },
/// Token::Struct {
/// name: "Example",
/// len: 1,
/// },
/// Token::Str("lock"),
/// ];
/// let error = "lock poison error while serializing";
@@ -130,8 +141,8 @@ where
/// Asserts that the given `tokens` deserialize into `value`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -141,14 +152,17 @@ where
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_de_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// assert_de_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// ```
#[cfg_attr(not(no_track_caller), track_caller)]
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
@@ -184,8 +198,8 @@ where
/// Asserts that the given `tokens` yield `error` when deserializing.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
+1 -1
View File
@@ -14,7 +14,7 @@ pub struct Compact<T: ?Sized>(T);
/// Trait to determine whether a value is represented in human-readable or
/// compact form.
///
/// ```edition2018
/// ```edition2021
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{assert_tokens, Configure, Token};
///
+23 -19
View File
@@ -20,11 +20,11 @@
//!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//!
//! ```edition2018
//! ```edition2021
//! # const IGNORE: &str = stringify! {
//! use linked_hash_map::LinkedHashMap;
//! # };
//! use serde_test::{Token, assert_tokens};
//! use serde_test::{assert_tokens, Token};
//!
//! # use std::fmt;
//! # use std::marker::PhantomData;
@@ -106,10 +106,13 @@
//! fn test_ser_de_empty() {
//! let map = LinkedHashMap::<char, u32>::new();
//!
//! assert_tokens(&map, &[
//! Token::Map { len: Some(0) },
//! Token::MapEnd,
//! ]);
//! assert_tokens(
//! &map,
//! &[
//! Token::Map { len: Some(0) },
//! Token::MapEnd,
//! ],
//! );
//! }
//!
//! #[test]
@@ -120,18 +123,19 @@
//! map.insert('a', 10);
//! map.insert('c', 30);
//!
//! assert_tokens(&map, &[
//! Token::Map { len: Some(3) },
//! Token::Char('b'),
//! Token::I32(20),
//!
//! Token::Char('a'),
//! Token::I32(10),
//!
//! Token::Char('c'),
//! Token::I32(30),
//! Token::MapEnd,
//! ]);
//! assert_tokens(
//! &map,
//! &[
//! Token::Map { len: Some(3) },
//! Token::Char('b'),
//! Token::I32(20),
//! Token::Char('a'),
//! Token::I32(10),
//! Token::Char('c'),
//! Token::I32(30),
//! Token::MapEnd,
//! ],
//! );
//! }
//! #
//! # fn main() {
@@ -140,7 +144,7 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.166")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.167")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
+167 -125
View File
@@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Display};
pub enum Token {
/// A serialized `bool`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&true, &[Token::Bool(true)]);
@@ -13,7 +13,7 @@ pub enum Token {
/// A serialized `i8`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i8, &[Token::I8(0)]);
@@ -22,7 +22,7 @@ pub enum Token {
/// A serialized `i16`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i16, &[Token::I16(0)]);
@@ -31,7 +31,7 @@ pub enum Token {
/// A serialized `i32`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i32, &[Token::I32(0)]);
@@ -40,7 +40,7 @@ pub enum Token {
/// A serialized `i64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0i64, &[Token::I64(0)]);
@@ -49,7 +49,7 @@ pub enum Token {
/// A serialized `u8`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u8, &[Token::U8(0)]);
@@ -58,7 +58,7 @@ pub enum Token {
/// A serialized `u16`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u16, &[Token::U16(0)]);
@@ -67,7 +67,7 @@ pub enum Token {
/// A serialized `u32`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u32, &[Token::U32(0)]);
@@ -76,7 +76,7 @@ pub enum Token {
/// A serialized `u64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0u64, &[Token::U64(0)]);
@@ -85,7 +85,7 @@ pub enum Token {
/// A serialized `f32`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
@@ -94,7 +94,7 @@ pub enum Token {
/// A serialized `f64`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
@@ -103,7 +103,7 @@ pub enum Token {
/// A serialized `char`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&'\n', &[Token::Char('\n')]);
@@ -112,7 +112,7 @@ pub enum Token {
/// A serialized `str`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("transient");
@@ -122,7 +122,7 @@ pub enum Token {
/// A borrowed `str`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s: &str = "borrowed";
@@ -132,7 +132,7 @@ pub enum Token {
/// A serialized `String`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let s = String::from("owned");
@@ -151,7 +151,7 @@ pub enum Token {
/// A serialized `Option<T>` containing none.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = None::<char>;
@@ -163,20 +163,17 @@ pub enum Token {
///
/// The tokens of the value follow after this header.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let opt = Some('c');
/// assert_tokens(&opt, &[
/// Token::Some,
/// Token::Char('c'),
/// ]);
/// assert_tokens(&opt, &[Token::Some, Token::Char('c')]);
/// ```
Some,
/// A serialized `()`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// assert_tokens(&(), &[Token::Unit]);
@@ -185,8 +182,8 @@ pub enum Token {
/// A serialized unit struct of the given name.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -200,8 +197,8 @@ pub enum Token {
/// A unit variant of an enum.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -211,7 +208,13 @@ pub enum Token {
/// }
///
/// let a = E::A;
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
/// assert_tokens(
/// &a,
/// &[Token::UnitVariant {
/// name: "E",
/// variant: "A",
/// }],
/// );
/// # }
/// ```
UnitVariant {
@@ -223,8 +226,8 @@ pub enum Token {
///
/// After this header is the value contained in the newtype struct.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -232,10 +235,10 @@ pub enum Token {
/// struct N(String);
///
/// let n = N("newtype".to_owned());
/// assert_tokens(&n, &[
/// Token::NewtypeStruct { name: "N" },
/// Token::String("newtype"),
/// ]);
/// assert_tokens(
/// &n,
/// &[Token::NewtypeStruct { name: "N" }, Token::String("newtype")],
/// );
/// # }
/// ```
NewtypeStruct { name: &'static str },
@@ -244,8 +247,8 @@ pub enum Token {
///
/// After this header is the value contained in the newtype variant.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -255,10 +258,16 @@ pub enum Token {
/// }
///
/// let b = E::B(0);
/// assert_tokens(&b, &[
/// Token::NewtypeVariant { name: "E", variant: "B" },
/// Token::U8(0),
/// ]);
/// assert_tokens(
/// &b,
/// &[
/// Token::NewtypeVariant {
/// name: "E",
/// variant: "B",
/// },
/// Token::U8(0),
/// ],
/// );
/// # }
/// ```
NewtypeVariant {
@@ -271,17 +280,20 @@ pub enum Token {
/// After this header are the elements of the sequence, followed by
/// `SeqEnd`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let vec = vec!['a', 'b', 'c'];
/// assert_tokens(&vec, &[
/// Token::Seq { len: Some(3) },
/// Token::Char('a'),
/// Token::Char('b'),
/// Token::Char('c'),
/// Token::SeqEnd,
/// ]);
/// assert_tokens(
/// &vec,
/// &[
/// Token::Seq { len: Some(3) },
/// Token::Char('a'),
/// Token::Char('b'),
/// Token::Char('c'),
/// Token::SeqEnd,
/// ],
/// );
/// ```
Seq { len: Option<usize> },
@@ -292,16 +304,19 @@ pub enum Token {
///
/// After this header are the elements of the tuple, followed by `TupleEnd`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// let tuple = ('a', 100);
/// assert_tokens(&tuple, &[
/// Token::Tuple { len: 2 },
/// Token::Char('a'),
/// Token::I32(100),
/// Token::TupleEnd,
/// ]);
/// assert_tokens(
/// &tuple,
/// &[
/// Token::Tuple { len: 2 },
/// Token::Char('a'),
/// Token::I32(100),
/// Token::TupleEnd,
/// ],
/// );
/// ```
Tuple { len: usize },
@@ -313,8 +328,8 @@ pub enum Token {
/// After this header are the fields of the tuple struct, followed by
/// `TupleStructEnd`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -322,12 +337,15 @@ pub enum Token {
/// struct T(u8, u8);
///
/// let t = T(0, 0);
/// assert_tokens(&t, &[
/// Token::TupleStruct { name: "T", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleStructEnd,
/// ]);
/// assert_tokens(
/// &t,
/// &[
/// Token::TupleStruct { name: "T", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleStructEnd,
/// ],
/// );
/// # }
/// ```
TupleStruct { name: &'static str, len: usize },
@@ -340,8 +358,8 @@ pub enum Token {
/// After this header are the fields of the tuple variant, followed by
/// `TupleVariantEnd`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -351,12 +369,19 @@ pub enum Token {
/// }
///
/// let c = E::C(0, 0);
/// assert_tokens(&c, &[
/// Token::TupleVariant { name: "E", variant: "C", len: 2 },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleVariantEnd,
/// ]);
/// assert_tokens(
/// &c,
/// &[
/// Token::TupleVariant {
/// name: "E",
/// variant: "C",
/// len: 2,
/// },
/// Token::U8(0),
/// Token::U8(0),
/// Token::TupleVariantEnd,
/// ],
/// );
/// # }
/// ```
TupleVariant {
@@ -372,7 +397,7 @@ pub enum Token {
///
/// After this header are the entries of the map, followed by `MapEnd`.
///
/// ```edition2018
/// ```edition2021
/// # use serde_test::{assert_tokens, Token};
/// #
/// use std::collections::BTreeMap;
@@ -381,14 +406,17 @@ pub enum Token {
/// map.insert('A', 65);
/// map.insert('Z', 90);
///
/// assert_tokens(&map, &[
/// Token::Map { len: Some(2) },
/// Token::Char('A'),
/// Token::I32(65),
/// Token::Char('Z'),
/// Token::I32(90),
/// Token::MapEnd,
/// ]);
/// assert_tokens(
/// &map,
/// &[
/// Token::Map { len: Some(2) },
/// Token::Char('A'),
/// Token::I32(65),
/// Token::Char('Z'),
/// Token::I32(90),
/// Token::MapEnd,
/// ],
/// );
/// ```
Map { len: Option<usize> },
@@ -399,8 +427,8 @@ pub enum Token {
///
/// After this header are the fields of the struct, followed by `StructEnd`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -411,14 +439,17 @@ pub enum Token {
/// }
///
/// let s = S { a: 0, b: 0 };
/// assert_tokens(&s, &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// assert_tokens(
/// &s,
/// &[
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("a"),
/// Token::U8(0),
/// Token::Str("b"),
/// Token::U8(0),
/// Token::StructEnd,
/// ],
/// );
/// # }
/// ```
Struct { name: &'static str, len: usize },
@@ -431,8 +462,8 @@ pub enum Token {
/// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -442,12 +473,19 @@ pub enum Token {
/// }
///
/// let d = E::D { d: 0 };
/// assert_tokens(&d, &[
/// Token::StructVariant { name: "E", variant: "D", len: 1 },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::StructVariantEnd,
/// ]);
/// assert_tokens(
/// &d,
/// &[
/// Token::StructVariant {
/// name: "E",
/// variant: "D",
/// len: 1,
/// },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::StructVariantEnd,
/// ],
/// );
/// # }
/// ```
StructVariant {
@@ -461,8 +499,8 @@ pub enum Token {
/// The header to an enum of the given name.
///
/// ```edition2018
/// # use serde::{Serialize, Deserialize};
/// ```edition2021
/// # use serde_derive::{Deserialize, Serialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
@@ -475,38 +513,42 @@ pub enum Token {
/// }
///
/// let a = E::A;
/// assert_tokens(&a, &[
/// Token::Enum { name: "E" },
/// Token::Str("A"),
/// Token::Unit,
/// ]);
/// assert_tokens(
/// &a,
/// &[Token::Enum { name: "E" }, Token::Str("A"), Token::Unit],
/// );
///
/// let b = E::B(0);
/// assert_tokens(&b, &[
/// Token::Enum { name: "E" },
/// Token::Str("B"),
/// Token::U8(0),
/// ]);
/// assert_tokens(
/// &b,
/// &[Token::Enum { name: "E" }, Token::Str("B"), Token::U8(0)],
/// );
///
/// let c = E::C(0, 0);
/// assert_tokens(&c, &[
/// Token::Enum { name: "E" },
/// Token::Str("C"),
/// Token::Seq { len: Some(2) },
/// Token::U8(0),
/// Token::U8(0),
/// Token::SeqEnd,
/// ]);
/// assert_tokens(
/// &c,
/// &[
/// Token::Enum { name: "E" },
/// Token::Str("C"),
/// Token::Seq { len: Some(2) },
/// Token::U8(0),
/// Token::U8(0),
/// Token::SeqEnd,
/// ],
/// );
///
/// let d = E::D { d: 0 };
/// assert_tokens(&d, &[
/// Token::Enum { name: "E" },
/// Token::Str("D"),
/// Token::Map { len: Some(1) },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::MapEnd,
/// ]);
/// assert_tokens(
/// &d,
/// &[
/// Token::Enum { name: "E" },
/// Token::Str("D"),
/// Token::Map { len: Some(1) },
/// Token::Str("d"),
/// Token::U8(0),
/// Token::MapEnd,
/// ],
/// );
/// # }
/// ```
Enum { name: &'static str },
+1 -1
View File
@@ -12,7 +12,7 @@ unstable = ["serde/unstable"]
serde = { path = "../serde" }
[dev-dependencies]
automod = "1.0"
automod = "1.0.1"
fnv = "1.0"
rustversion = "1.0"
serde = { path = "../serde", features = ["rc", "derive"] }
+1 -1
View File
@@ -19,7 +19,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
//////////////////////////////////////////////////////////////////////////////
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Unit;
+1 -1
View File
@@ -1,4 +1,4 @@
use serde_derive::{Serialize, Deserialize};
use serde_derive::{Deserialize, Serialize};
mod remote {
pub struct S {
+1 -1
View File
@@ -1,4 +1,4 @@
use serde_derive::{Serialize, Deserialize};
use serde_derive::{Deserialize, Serialize};
mod remote {
pub struct S {