mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-22 21:48:02 +00:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8939af48fe | |||
| fa5d58cd00 | |||
| 1a3cf4b3c1 | |||
| 7d96352e96 | |||
| 111ecc5d8c | |||
| edd6fe954b | |||
| a20e9249c5 | |||
| b1353a99cd | |||
| c59e876bb3 | |||
| 7f1e697c0d | |||
| 373edcd055 | |||
| f0b5c4f857 | |||
| 3035d4fa34 | |||
| 60ac737439 | |||
| a95b0d301e | |||
| 951ca5ace0 | |||
| adf05a5bf6 | |||
| 418062165f | |||
| 210373b3b6 | |||
| 5f9fffa53e | |||
| 9cda015733 | |||
| 58a8d22931 | |||
| ef0ed22593 | |||
| 79925ac394 | |||
| b60e4092ec | |||
| fdc36e5c06 | |||
| 49e11ce1ba | |||
| 7ae1b5f8f3 | |||
| 1ac054b34a | |||
| 1e36ef551d | |||
| 0058c7226e | |||
| 29d4f3e887 | |||
| 1b8310d98a | |||
| af4c388dff | |||
| 09f6d9361d | |||
| 1f9eb8300f | |||
| c6a5be7f6a | |||
| 0a06af8d21 | |||
| 3393ad6760 | |||
| 830309fcb5 | |||
| ab4f3f3111 | |||
| 00460b8dee | |||
| d4486be2b9 | |||
| 991e344804 | |||
| 6a7de26e5a | |||
| 5382ef3b0b | |||
| a8cbc9184e | |||
| 966e9ccf0c | |||
| 53ade10137 | |||
| 422c719352 | |||
| 3415619bfd | |||
| 04bb76bc00 | |||
| 8b0f482666 | |||
| 4b3178b053 | |||
| 8e1ae68569 | |||
| 31000e1874 | |||
| 4487cb26c7 | |||
| aba4e18553 | |||
| c82f2580b4 | |||
| 1d7b009aec | |||
| 89c4b02bf3 | |||
| eeb8e44cda | |||
| 785c2d9605 | |||
| d549f048e1 | |||
| 4c0dd63011 | |||
| 26fb134165 | |||
| 07e614b52b | |||
| b1f899fbe8 | |||
| b4f860e627 | |||
| d940fe1b49 | |||
| f2899a9e06 | |||
| 3aca38d2d3 | |||
| 8b769fcc20 | |||
| 9c954264f4 | |||
| 74b538b8ec | |||
| 291ec50d98 | |||
| 21c7fd1bd5 |
@@ -0,0 +1 @@
|
||||
github: dtolnay
|
||||
@@ -21,6 +21,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: Cargo.lock
|
||||
path: Cargo.lock
|
||||
continue-on-error: true
|
||||
|
||||
windows:
|
||||
name: Test suite (windows)
|
||||
@@ -90,13 +96,16 @@ jobs:
|
||||
- run: cd serde && cargo build
|
||||
|
||||
derive:
|
||||
name: Rust 1.56.0
|
||||
name: Rust 1.61.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.56.0
|
||||
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||
- uses: dtolnay/rust-toolchain@1.61.0
|
||||
- run: |
|
||||
sed -i 's/proc-macro2 = { workspace = true/proc-macro2 = { version = "1"/' serde_derive*/Cargo.toml
|
||||
sed -i 's/quote = { workspace = true/quote = { version = "1"/' serde_derive*/Cargo.toml
|
||||
sed -i 's/syn = { workspace = true/syn = { version = "2"/' serde_derive*/Cargo.toml
|
||||
- run: cd serde && cargo check --no-default-features
|
||||
- run: cd serde && cargo check
|
||||
- run: cd serde_derive && cargo check
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ serde = { path = "serde" }
|
||||
[workspace.dependencies]
|
||||
proc-macro2 = { version = "1.0.74", default-features = false }
|
||||
quote = { version = "1.0.35", default-features = false }
|
||||
syn = { version = "2.0.46", default-features = false }
|
||||
syn = { version = "2.0.81", default-features = false }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56]
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.61]
|
||||
|
||||
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
|
||||
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
|
||||
@@ -7,7 +7,7 @@
|
||||
[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray
|
||||
[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray
|
||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
||||
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
|
||||
[Rust 1.61]: https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html
|
||||
|
||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.209"
|
||||
version = "1.0.215"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||
@@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"]
|
||||
# is compatible with exactly one serde release because the generated code
|
||||
# involves nonpublic APIs which are not bound by semver.
|
||||
[target.'cfg(any())'.dependencies]
|
||||
serde_derive = { version = "=1.0.209", path = "../serde_derive" }
|
||||
serde_derive = { version = "=1.0.215", path = "../serde_derive" }
|
||||
|
||||
|
||||
### FEATURES #################################################################
|
||||
|
||||
+19
-5
@@ -15,6 +15,8 @@ fn main() {
|
||||
|
||||
if minor >= 77 {
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_cstr)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_error)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_net)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_try_from)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
|
||||
@@ -48,11 +50,6 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=no_float_copysign");
|
||||
}
|
||||
|
||||
// Current minimum supported version of serde_derive crate is Rust 1.56.
|
||||
if minor < 56 {
|
||||
println!("cargo:rustc-cfg=no_serde_derive");
|
||||
}
|
||||
|
||||
// Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60.
|
||||
if minor < 60 {
|
||||
println!("cargo:rustc-cfg=no_target_has_atomic");
|
||||
@@ -74,6 +71,11 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Current minimum supported version of serde_derive crate is Rust 1.61.
|
||||
if minor < 61 {
|
||||
println!("cargo:rustc-cfg=no_serde_derive");
|
||||
}
|
||||
|
||||
// Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64.
|
||||
// https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc
|
||||
if minor < 64 {
|
||||
@@ -86,11 +88,23 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=no_core_num_saturating");
|
||||
}
|
||||
|
||||
// Support for core::net stabilized in Rust 1.77.
|
||||
// https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html
|
||||
if minor < 77 {
|
||||
println!("cargo:rustc-cfg=no_core_net");
|
||||
}
|
||||
|
||||
// Support for the `#[diagnostic]` tool attribute namespace
|
||||
// https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes
|
||||
if minor < 78 {
|
||||
println!("cargo:rustc-cfg=no_diagnostic_namespace");
|
||||
}
|
||||
|
||||
// The Error trait became available in core in 1.81.
|
||||
// https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror
|
||||
if minor < 81 {
|
||||
println!("cargo:rustc-cfg=no_core_error");
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_minor_version() -> Option<u32> {
|
||||
|
||||
+16
-30
@@ -1583,12 +1583,9 @@ map_impl! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! parse_ip_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ty, $expecting:expr, $size:tt
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
($ty:ty, $expecting:expr, $size:tt) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1604,7 +1601,7 @@ macro_rules! parse_ip_impl {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! variant_identifier {
|
||||
(
|
||||
$name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
|
||||
@@ -1679,7 +1676,7 @@ macro_rules! variant_identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! deserialize_enum {
|
||||
(
|
||||
$name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
|
||||
@@ -1716,8 +1713,7 @@ macro_rules! deserialize_enum {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl<'de> Deserialize<'de> for net::IpAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1736,25 +1732,18 @@ impl<'de> Deserialize<'de> for net::IpAddr {
|
||||
}
|
||||
}
|
||||
|
||||
parse_ip_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
net::Ipv4Addr, "IPv4 address", 4
|
||||
}
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
parse_ip_impl!(net::Ipv4Addr, "IPv4 address", 4);
|
||||
|
||||
parse_ip_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
net::Ipv6Addr, "IPv6 address", 16
|
||||
}
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
parse_ip_impl!(net::Ipv6Addr, "IPv6 address", 16);
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! parse_socket_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ty, $expecting:tt,
|
||||
$new:expr,
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1770,8 +1759,7 @@ macro_rules! parse_socket_impl {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl<'de> Deserialize<'de> for net::SocketAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1790,16 +1778,14 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
parse_socket_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
net::SocketAddrV4, "IPv4 socket address",
|
||||
|(ip, port)| net::SocketAddrV4::new(ip, port),
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
parse_socket_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
net::SocketAddrV6, "IPv6 socket address",
|
||||
|(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0),
|
||||
}
|
||||
@@ -3160,13 +3146,13 @@ atomic_impl! {
|
||||
AtomicU64 "64"
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
struct FromStrVisitor<T> {
|
||||
expecting: &'static str,
|
||||
ty: PhantomData<T>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl<T> FromStrVisitor<T> {
|
||||
fn new(expecting: &'static str) -> Self {
|
||||
FromStrVisitor {
|
||||
@@ -3176,7 +3162,7 @@ impl<T> FromStrVisitor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl<'de, T> Visitor<'de> for FromStrVisitor<T>
|
||||
where
|
||||
T: str::FromStr,
|
||||
|
||||
+8
-9
@@ -118,17 +118,16 @@ use crate::lib::*;
|
||||
|
||||
pub mod value;
|
||||
|
||||
mod format;
|
||||
mod ignored_any;
|
||||
mod impls;
|
||||
pub(crate) mod size_hint;
|
||||
|
||||
pub use self::ignored_any::IgnoredAny;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "unstable")))]
|
||||
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::std_error::Error as StdError;
|
||||
#[cfg(all(feature = "unstable", not(feature = "std")))]
|
||||
#[cfg(not(any(feature = "std", no_core_error)))]
|
||||
#[doc(no_inline)]
|
||||
pub use core::error::Error as StdError;
|
||||
#[cfg(feature = "std")]
|
||||
@@ -487,13 +486,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Expected for &'a str {
|
||||
impl Expected for &str {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Expected + 'a {
|
||||
impl Display for Expected + '_ {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Expected::fmt(self, formatter)
|
||||
}
|
||||
@@ -1374,7 +1373,7 @@ pub trait Visitor<'de>: Sized {
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 58];
|
||||
let mut writer = format::Buf::new(&mut buf);
|
||||
let mut writer = crate::format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
||||
Err(Error::invalid_type(
|
||||
Unexpected::Other(writer.as_str()),
|
||||
@@ -1436,7 +1435,7 @@ pub trait Visitor<'de>: Sized {
|
||||
E: Error,
|
||||
{
|
||||
let mut buf = [0u8; 57];
|
||||
let mut writer = format::Buf::new(&mut buf);
|
||||
let mut writer = crate::format::Buf::new(&mut buf);
|
||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
||||
Err(Error::invalid_type(
|
||||
Unexpected::Other(writer.as_str()),
|
||||
@@ -1742,7 +1741,7 @@ pub trait SeqAccess<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, A> SeqAccess<'de> for &'a mut A
|
||||
impl<'de, A> SeqAccess<'de> for &mut A
|
||||
where
|
||||
A: ?Sized + SeqAccess<'de>,
|
||||
{
|
||||
@@ -1895,7 +1894,7 @@ pub trait MapAccess<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, A> MapAccess<'de> for &'a mut A
|
||||
impl<'de, A> MapAccess<'de> for &mut A
|
||||
where
|
||||
A: ?Sized + MapAccess<'de>,
|
||||
{
|
||||
|
||||
@@ -175,6 +175,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> IntoDeserializer<'de, E> for UnitDeserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Debug for UnitDeserializer<E> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.debug_struct("UnitDeserializer").finish()
|
||||
@@ -225,6 +236,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for NeverDeserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! primitive_deserializer {
|
||||
@@ -279,6 +302,17 @@ macro_rules! primitive_deserializer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> IntoDeserializer<'de, E> for $name<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Debug for $name<E> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -369,6 +403,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> IntoDeserializer<'de, E> for U32Deserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::EnumAccess<'de> for U32Deserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -458,6 +503,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -537,6 +593,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -640,6 +707,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for StringDeserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
|
||||
where
|
||||
@@ -748,6 +827,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for CowStrDeserializer<'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
|
||||
where
|
||||
@@ -825,6 +916,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> Debug for BytesDeserializer<'a, E> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -873,6 +975,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter
|
||||
@@ -952,6 +1065,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer<I, E>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: IntoDeserializer<'de, E>,
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer<I, E>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
@@ -1083,6 +1209,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer<A>
|
||||
where
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer that iterates over a map.
|
||||
@@ -1197,6 +1334,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: private::Pair,
|
||||
First<I::Item>: IntoDeserializer<'de, E>,
|
||||
Second<I::Item>: IntoDeserializer<'de, E>,
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E>
|
||||
where
|
||||
I: Iterator,
|
||||
@@ -1498,6 +1650,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer<A>
|
||||
where
|
||||
A: de::MapAccess<'de>,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
|
||||
where
|
||||
A: de::MapAccess<'de>,
|
||||
@@ -1551,6 +1714,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, A> IntoDeserializer<'de, A::Error> for EnumAccessDeserializer<A>
|
||||
where
|
||||
A: de::EnumAccess<'de>,
|
||||
{
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mod private {
|
||||
|
||||
+11
-3
@@ -95,7 +95,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.209")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.215")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||
@@ -144,6 +144,7 @@
|
||||
clippy::too_many_lines,
|
||||
// preference
|
||||
clippy::doc_markdown,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::unseparated_literal_suffix,
|
||||
// false positive
|
||||
clippy::needless_doctest_main,
|
||||
@@ -238,8 +239,13 @@ mod lib {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::ffi::CString;
|
||||
|
||||
#[cfg(all(not(no_core_net), not(feature = "std")))]
|
||||
pub use self::core::net;
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::{error, net};
|
||||
pub use std::net;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::error;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{HashMap, HashSet};
|
||||
@@ -305,6 +311,8 @@ mod integer128;
|
||||
pub mod de;
|
||||
pub mod ser;
|
||||
|
||||
mod format;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::de::{Deserialize, Deserializer};
|
||||
#[doc(inline)]
|
||||
@@ -318,7 +326,7 @@ pub mod __private;
|
||||
#[path = "de/seed.rs"]
|
||||
mod seed;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "unstable")))]
|
||||
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||
mod std_error;
|
||||
|
||||
// Re-export #[derive(Serialize, Deserialize)].
|
||||
|
||||
+25
-16
@@ -313,6 +313,17 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de, E> de::IntoDeserializer<'de, E> for &'a Content<'de>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Deserializer = ContentRefDeserializer<'a, 'de, E>;
|
||||
|
||||
fn into_deserializer(self) -> Self::Deserializer {
|
||||
ContentRefDeserializer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to capture data in [`Content`] from other deserializers.
|
||||
/// Cannot capture externally tagged enums, `i128` and `u128`.
|
||||
struct ContentVisitor<'de> {
|
||||
@@ -476,14 +487,16 @@ mod content {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v)))
|
||||
let v = tri!(Deserialize::deserialize(deserializer));
|
||||
Ok(Content::Some(Box::new(v)))
|
||||
}
|
||||
|
||||
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v)))
|
||||
let v = tri!(Deserialize::deserialize(deserializer));
|
||||
Ok(Content::Newtype(Box::new(v)))
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||
@@ -1098,8 +1111,7 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.into_iter().map(ContentDeserializer::new);
|
||||
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||
let mut seq_visitor = SeqDeserializer::new(content.into_iter());
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
Ok(value)
|
||||
@@ -1113,10 +1125,7 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let map = content
|
||||
.into_iter()
|
||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let mut map_visitor = MapDeserializer::new(map);
|
||||
let mut map_visitor = MapDeserializer::new(content.into_iter());
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
Ok(value)
|
||||
@@ -1694,8 +1703,7 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.iter().map(ContentRefDeserializer::new);
|
||||
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||
let mut seq_visitor = SeqDeserializer::new(content.iter());
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
Ok(value)
|
||||
@@ -1709,12 +1717,13 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let map = content.iter().map(|(k, v)| {
|
||||
(
|
||||
ContentRefDeserializer::new(k),
|
||||
ContentRefDeserializer::new(v),
|
||||
)
|
||||
});
|
||||
fn content_ref_deserializer_pair<'a, 'de>(
|
||||
(k, v): &'a (Content<'de>, Content<'de>),
|
||||
) -> (&'a Content<'de>, &'a Content<'de>) {
|
||||
(k, v)
|
||||
}
|
||||
|
||||
let map = content.iter().map(content_ref_deserializer_pair);
|
||||
let mut map_visitor = MapDeserializer::new(map);
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
|
||||
@@ -35,7 +35,7 @@ macro_rules! fmt_primitives {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
impl<'a> Serializer for &mut fmt::Formatter<'a> {
|
||||
type Ok = ();
|
||||
type Error = fmt::Error;
|
||||
type SerializeSeq = Impossible<(), fmt::Error>;
|
||||
|
||||
+13
-29
@@ -773,28 +773,17 @@ impl Serialize for SystemTime {
|
||||
/// statically known to never have more than a constant `MAX_LEN` bytes.
|
||||
///
|
||||
/// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
macro_rules! serialize_display_bounded_length {
|
||||
($value:expr, $max:expr, $serializer:expr) => {{
|
||||
let mut buffer = [0u8; $max];
|
||||
let remaining_len = {
|
||||
let mut remaining = &mut buffer[..];
|
||||
write!(remaining, "{}", $value).unwrap();
|
||||
remaining.len()
|
||||
};
|
||||
let written_len = buffer.len() - remaining_len;
|
||||
let written = &buffer[..written_len];
|
||||
|
||||
// write! only provides fmt::Formatter to Display implementations, which
|
||||
// has methods write_str and write_char but no method to write arbitrary
|
||||
// bytes. Therefore `written` must be valid UTF-8.
|
||||
let written_str = str::from_utf8(written).expect("must be valid UTF-8");
|
||||
$serializer.serialize_str(written_str)
|
||||
let mut writer = crate::format::Buf::new(&mut buffer);
|
||||
write!(&mut writer, "{}", $value).unwrap();
|
||||
$serializer.serialize_str(writer.as_str())
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -818,7 +807,7 @@ impl Serialize for net::IpAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
const DEC_DIGITS_LUT: &[u8] = b"\
|
||||
0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
@@ -826,7 +815,7 @@ const DEC_DIGITS_LUT: &[u8] = b"\
|
||||
6061626364656667686970717273747576777879\
|
||||
8081828384858687888990919293949596979899";
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
#[inline]
|
||||
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||
if n >= 100 {
|
||||
@@ -847,7 +836,7 @@ fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
#[test]
|
||||
fn test_format_u8() {
|
||||
let mut i = 0u8;
|
||||
@@ -864,8 +853,7 @@ fn test_format_u8() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -889,8 +877,7 @@ impl Serialize for net::Ipv4Addr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::Ipv6Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -906,8 +893,7 @@ impl Serialize for net::Ipv6Addr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -931,8 +917,7 @@ impl Serialize for net::SocketAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddrV4 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -948,8 +933,7 @@ impl Serialize for net::SocketAddrV4 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[cfg(any(feature = "std", not(no_core_net)))]
|
||||
impl Serialize for net::SocketAddrV6 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
||||
@@ -115,10 +115,10 @@ mod impossible;
|
||||
|
||||
pub use self::impossible::Impossible;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "unstable")))]
|
||||
#[cfg(all(not(feature = "std"), no_core_error))]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::std_error::Error as StdError;
|
||||
#[cfg(all(feature = "unstable", not(feature = "std")))]
|
||||
#[cfg(not(any(feature = "std", no_core_error)))]
|
||||
#[doc(no_inline)]
|
||||
pub use core::error::Error as StdError;
|
||||
#[cfg(feature = "std")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.209"
|
||||
version = "1.0.215"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@@ -12,7 +12,7 @@ keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.61"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -227,7 +227,9 @@ pub fn with_bound(
|
||||
match bound {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
|
||||
syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {}
|
||||
syn::TypeParamBound::Lifetime(_)
|
||||
| syn::TypeParamBound::PreciseCapture(_)
|
||||
| syn::TypeParamBound::Verbatim(_) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
+134
-81
@@ -1,5 +1,6 @@
|
||||
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use crate::internals::name::Name;
|
||||
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
||||
use crate::{bound, dummy, pretend, this};
|
||||
use proc_macro2::{Literal, Span, TokenStream};
|
||||
@@ -371,7 +372,11 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
||||
} else {
|
||||
let value = match field.attrs.default() {
|
||||
attr::Default::Default => quote!(_serde::__private::Default::default()),
|
||||
attr::Default::Path(path) => quote!(#path()),
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
attr::Default::Path(path) => quote_spanned!(path.span()=> #path()),
|
||||
attr::Default::None => quote!(_serde::__private::PhantomData),
|
||||
};
|
||||
quote!(#member: #value)
|
||||
@@ -757,7 +762,11 @@ fn deserialize_seq(
|
||||
attr::Default::Default => Some(quote!(
|
||||
let __default: Self::Value = _serde::__private::Default::default();
|
||||
)),
|
||||
attr::Default::Path(path) => Some(quote!(
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||
let __default: Self::Value = #path();
|
||||
)),
|
||||
attr::Default::None => {
|
||||
@@ -839,7 +848,11 @@ fn deserialize_seq_in_place(
|
||||
attr::Default::Default => Some(quote!(
|
||||
let __default: #this_type #ty_generics = _serde::__private::Default::default();
|
||||
)),
|
||||
attr::Default::Path(path) => Some(quote!(
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||
let __default: #this_type #ty_generics = #path();
|
||||
)),
|
||||
attr::Default::None => {
|
||||
@@ -863,18 +876,23 @@ fn deserialize_newtype_struct(
|
||||
) -> TokenStream {
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
let field_ty = field.ty;
|
||||
let deserializer_var = quote!(__e);
|
||||
|
||||
let value = match field.attrs.deserialize_with() {
|
||||
None => {
|
||||
let span = field.original.span();
|
||||
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
|
||||
quote! {
|
||||
#func(__e)?
|
||||
#func(#deserializer_var)?
|
||||
}
|
||||
}
|
||||
Some(path) => {
|
||||
quote! {
|
||||
#path(__e)?
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(with = "...")]
|
||||
// ^^^^^
|
||||
quote_spanned! {path.span()=>
|
||||
#path(#deserializer_var)?
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -890,7 +908,7 @@ fn deserialize_newtype_struct(
|
||||
|
||||
quote! {
|
||||
#[inline]
|
||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
|
||||
fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::__private::Result<Self::Value, __E::Error>
|
||||
where
|
||||
__E: _serde::Deserializer<#delife>,
|
||||
{
|
||||
@@ -950,23 +968,20 @@ fn deserialize_struct(
|
||||
};
|
||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||
|
||||
let field_names_idents: Vec<_> = fields
|
||||
let deserialized_fields: 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(),
|
||||
)
|
||||
.map(|(i, field)| FieldWithAliases {
|
||||
ident: field_i(i),
|
||||
aliases: field.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let has_flatten = has_flatten(fields);
|
||||
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten);
|
||||
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten);
|
||||
|
||||
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||
// structs that only have a map representation.
|
||||
@@ -974,7 +989,7 @@ fn deserialize_struct(
|
||||
StructForm::Untagged(..) => None,
|
||||
_ if has_flatten => None,
|
||||
_ => {
|
||||
let mut_seq = if field_names_idents.is_empty() {
|
||||
let mut_seq = if deserialized_fields.is_empty() {
|
||||
quote!(_)
|
||||
} else {
|
||||
quote!(mut __seq)
|
||||
@@ -1022,9 +1037,7 @@ fn deserialize_struct(
|
||||
let fields_stmt = if has_flatten {
|
||||
None
|
||||
} else {
|
||||
let field_names = field_names_idents
|
||||
.iter()
|
||||
.flat_map(|&(_, _, aliases)| aliases);
|
||||
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||
|
||||
Some(quote! {
|
||||
#[doc(hidden)]
|
||||
@@ -1117,31 +1130,26 @@ fn deserialize_struct_in_place(
|
||||
let expecting = format!("struct {}", params.type_name());
|
||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||
|
||||
let field_names_idents: Vec<_> = fields
|
||||
let deserialized_fields: Vec<_> = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, field)| !field.attrs.skip_deserializing())
|
||||
.map(|(i, field)| {
|
||||
(
|
||||
field.attrs.name().deserialize_name(),
|
||||
field_i(i),
|
||||
field.attrs.aliases(),
|
||||
)
|
||||
.map(|(i, field)| FieldWithAliases {
|
||||
ident: field_i(i),
|
||||
aliases: field.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, false);
|
||||
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false);
|
||||
|
||||
let mut_seq = if field_names_idents.is_empty() {
|
||||
let mut_seq = if deserialized_fields.is_empty() {
|
||||
quote!(_)
|
||||
} else {
|
||||
quote!(mut __seq)
|
||||
};
|
||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
||||
let field_names = field_names_idents
|
||||
.iter()
|
||||
.flat_map(|&(_, _, aliases)| aliases);
|
||||
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||
let type_name = cattrs.name().deserialize_name();
|
||||
|
||||
let in_place_impl_generics = de_impl_generics.in_place();
|
||||
@@ -1225,39 +1233,38 @@ fn deserialize_homogeneous_enum(
|
||||
}
|
||||
|
||||
fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||
let mut deserialized_variants = variants
|
||||
let deserialized_variants = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, variant)| !variant.attrs.skip_deserializing());
|
||||
|
||||
let variant_names_idents: Vec<_> = deserialized_variants
|
||||
.clone()
|
||||
.map(|(i, variant)| {
|
||||
(
|
||||
variant.attrs.name().deserialize_name(),
|
||||
field_i(i),
|
||||
variant.attrs.aliases(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
|
||||
|
||||
let fallthrough = deserialized_variants
|
||||
.position(|(_, variant)| variant.attrs.other())
|
||||
.map(|other_idx| {
|
||||
let ignore_variant = variant_names_idents[other_idx].1.clone();
|
||||
.clone()
|
||||
.find(|(_i, variant)| variant.attrs.other())
|
||||
.map(|(i, _variant)| {
|
||||
let ignore_variant = field_i(i);
|
||||
quote!(_serde::__private::Ok(__Field::#ignore_variant))
|
||||
});
|
||||
|
||||
let variants_stmt = {
|
||||
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
|
||||
let variant_names = deserialized_variants
|
||||
.clone()
|
||||
.flat_map(|(_i, variant)| variant.attrs.aliases());
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
|
||||
}
|
||||
};
|
||||
|
||||
let deserialized_variants: Vec<_> = deserialized_variants
|
||||
.map(|(i, variant)| FieldWithAliases {
|
||||
ident: field_i(i),
|
||||
aliases: variant.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let variant_visitor = Stmts(deserialize_generated_identifier(
|
||||
&variant_names_idents,
|
||||
&deserialized_variants,
|
||||
false, // variant identifiers do not depend on the presence of flatten fields
|
||||
true,
|
||||
None,
|
||||
@@ -1994,19 +2001,27 @@ fn deserialize_untagged_newtype_variant(
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldWithAliases<'a> {
|
||||
ident: Ident,
|
||||
aliases: &'a BTreeSet<Name>,
|
||||
}
|
||||
|
||||
fn deserialize_generated_identifier(
|
||||
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||
deserialized_fields: &[FieldWithAliases],
|
||||
has_flatten: bool,
|
||||
is_variant: bool,
|
||||
ignore_variant: Option<TokenStream>,
|
||||
fallthrough: Option<TokenStream>,
|
||||
) -> Fragment {
|
||||
let this_value = quote!(__Field);
|
||||
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
|
||||
let field_idents: &Vec<_> = &deserialized_fields
|
||||
.iter()
|
||||
.map(|field| &field.ident)
|
||||
.collect();
|
||||
|
||||
let visitor_impl = Stmts(deserialize_identifier(
|
||||
&this_value,
|
||||
fields,
|
||||
deserialized_fields,
|
||||
is_variant,
|
||||
fallthrough,
|
||||
None,
|
||||
@@ -2052,7 +2067,7 @@ fn deserialize_generated_identifier(
|
||||
/// Generates enum and its `Deserialize` implementation that represents each
|
||||
/// non-skipped field of the struct
|
||||
fn deserialize_field_identifier(
|
||||
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||
deserialized_fields: &[FieldWithAliases],
|
||||
cattrs: &attr::Container,
|
||||
has_flatten: bool,
|
||||
) -> Stmts {
|
||||
@@ -2069,7 +2084,7 @@ fn deserialize_field_identifier(
|
||||
};
|
||||
|
||||
Stmts(deserialize_generated_identifier(
|
||||
fields,
|
||||
deserialized_fields,
|
||||
has_flatten,
|
||||
false,
|
||||
ignore_variant,
|
||||
@@ -2127,18 +2142,15 @@ fn deserialize_custom_identifier(
|
||||
(variants, None, None)
|
||||
};
|
||||
|
||||
let names_idents: Vec<_> = ordinary
|
||||
let idents_aliases: Vec<_> = ordinary
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
(
|
||||
variant.attrs.name().deserialize_name(),
|
||||
variant.ident.clone(),
|
||||
variant.attrs.aliases(),
|
||||
)
|
||||
.map(|variant| FieldWithAliases {
|
||||
ident: variant.ident.clone(),
|
||||
aliases: variant.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases);
|
||||
let names = idents_aliases.iter().flat_map(|variant| variant.aliases);
|
||||
|
||||
let names_const = if fallthrough.is_some() {
|
||||
None
|
||||
@@ -2161,7 +2173,7 @@ fn deserialize_custom_identifier(
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
let visitor_impl = Stmts(deserialize_identifier(
|
||||
&this_value,
|
||||
&names_idents,
|
||||
&idents_aliases,
|
||||
is_variant,
|
||||
fallthrough,
|
||||
fallthrough_borrowed,
|
||||
@@ -2194,23 +2206,35 @@ fn deserialize_custom_identifier(
|
||||
|
||||
fn deserialize_identifier(
|
||||
this_value: &TokenStream,
|
||||
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||
deserialized_fields: &[FieldWithAliases],
|
||||
is_variant: bool,
|
||||
fallthrough: Option<TokenStream>,
|
||||
fallthrough_borrowed: Option<TokenStream>,
|
||||
collect_other_fields: bool,
|
||||
expecting: Option<&str>,
|
||||
) -> Fragment {
|
||||
let str_mapping = fields.iter().map(|(_, ident, aliases)| {
|
||||
let str_mapping = deserialized_fields.iter().map(|field| {
|
||||
let ident = &field.ident;
|
||||
let aliases = field.aliases;
|
||||
// `aliases` also contains a main name
|
||||
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
||||
quote! {
|
||||
#(
|
||||
#aliases => _serde::__private::Ok(#this_value::#ident),
|
||||
)*
|
||||
}
|
||||
});
|
||||
let bytes_mapping = fields.iter().map(|(_, ident, aliases)| {
|
||||
let bytes_mapping = deserialized_fields.iter().map(|field| {
|
||||
let ident = &field.ident;
|
||||
// `aliases` also contains a main name
|
||||
let aliases = aliases
|
||||
let aliases = field
|
||||
.aliases
|
||||
.iter()
|
||||
.map(|alias| Literal::byte_string(alias.as_bytes()));
|
||||
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
||||
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
|
||||
quote! {
|
||||
#(
|
||||
#aliases => _serde::__private::Ok(#this_value::#ident),
|
||||
)*
|
||||
}
|
||||
});
|
||||
|
||||
let expecting = expecting.unwrap_or(if is_variant {
|
||||
@@ -2360,8 +2384,9 @@ fn deserialize_identifier(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| {
|
||||
let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| {
|
||||
let i = i as u64;
|
||||
let ident = &field.ident;
|
||||
quote!(#i => _serde::__private::Ok(#this_value::#ident))
|
||||
});
|
||||
|
||||
@@ -2370,7 +2395,11 @@ fn deserialize_identifier(
|
||||
fallthrough
|
||||
} else {
|
||||
let index_expecting = if is_variant { "variant" } else { "field" };
|
||||
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
|
||||
let fallthrough_msg = format!(
|
||||
"{} index 0 <= i < {}",
|
||||
index_expecting,
|
||||
deserialized_fields.len(),
|
||||
);
|
||||
u64_fallthrough_arm_tokens = quote! {
|
||||
_serde::__private::Err(_serde::de::Error::invalid_value(
|
||||
_serde::de::Unexpected::Unsigned(__value),
|
||||
@@ -2403,7 +2432,7 @@ fn deserialize_identifier(
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
#(#str_mapping,)*
|
||||
#(#str_mapping)*
|
||||
_ => {
|
||||
#value_as_borrowed_str_content
|
||||
#fallthrough_borrowed_arm
|
||||
@@ -2416,7 +2445,7 @@ fn deserialize_identifier(
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
#(#bytes_mapping,)*
|
||||
#(#bytes_mapping)*
|
||||
_ => {
|
||||
#bytes_to_str
|
||||
#value_as_borrowed_bytes_content
|
||||
@@ -2441,7 +2470,7 @@ fn deserialize_identifier(
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
#(#str_mapping,)*
|
||||
#(#str_mapping)*
|
||||
_ => {
|
||||
#value_as_str_content
|
||||
#fallthrough_arm
|
||||
@@ -2454,7 +2483,7 @@ fn deserialize_identifier(
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
match __value {
|
||||
#(#bytes_mapping,)*
|
||||
#(#bytes_mapping)*
|
||||
_ => {
|
||||
#bytes_to_str
|
||||
#value_as_bytes_content
|
||||
@@ -2647,7 +2676,11 @@ fn deserialize_map(
|
||||
attr::Default::Default => Some(quote!(
|
||||
let __default: Self::Value = _serde::__private::Default::default();
|
||||
)),
|
||||
attr::Default::Path(path) => Some(quote!(
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||
let __default: Self::Value = #path();
|
||||
)),
|
||||
attr::Default::None => {
|
||||
@@ -2817,7 +2850,11 @@ fn deserialize_map_in_place(
|
||||
attr::Default::Default => Some(quote!(
|
||||
let __default: #this_type #ty_generics = _serde::__private::Default::default();
|
||||
)),
|
||||
attr::Default::Path(path) => Some(quote!(
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||
let __default: #this_type #ty_generics = #path();
|
||||
)),
|
||||
attr::Default::None => {
|
||||
@@ -2855,7 +2892,15 @@ fn wrap_deserialize_with(
|
||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
||||
split_with_de_lifetime(params);
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
let deserializer_var = quote!(__deserializer);
|
||||
|
||||
// If #deserialize_with returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(with = "...")]
|
||||
// ^^^^^
|
||||
let value = quote_spanned! {deserialize_with.span()=>
|
||||
#deserialize_with(#deserializer_var)?
|
||||
};
|
||||
let wrapper = quote! {
|
||||
#[doc(hidden)]
|
||||
struct __DeserializeWith #de_impl_generics #where_clause {
|
||||
@@ -2865,12 +2910,12 @@ fn wrap_deserialize_with(
|
||||
}
|
||||
|
||||
impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause {
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
fn deserialize<__D>(#deserializer_var: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<#delife>,
|
||||
{
|
||||
_serde::__private::Ok(__DeserializeWith {
|
||||
value: #deserialize_with(__deserializer)?,
|
||||
value: #value,
|
||||
phantom: _serde::__private::PhantomData,
|
||||
lifetime: _serde::__private::PhantomData,
|
||||
})
|
||||
@@ -2961,7 +3006,11 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
|
||||
return quote_expr!(#func());
|
||||
}
|
||||
attr::Default::Path(path) => {
|
||||
return quote_expr!(#path());
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
return Fragment::Expr(quote_spanned!(path.span()=> #path()));
|
||||
}
|
||||
attr::Default::None => { /* below */ }
|
||||
}
|
||||
@@ -3004,6 +3053,10 @@ fn expr_is_missing_seq(
|
||||
return quote_spanned!(span=> #assign_to _serde::__private::Default::default());
|
||||
}
|
||||
attr::Default::Path(path) => {
|
||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||
// We attach span of the path to the function so it will be reported
|
||||
// on the #[serde(default = "...")]
|
||||
// ^^^^^
|
||||
return quote_spanned!(path.span()=> #assign_to #path());
|
||||
}
|
||||
attr::Default::None => { /* below */ }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::internals::name::{MultiName, Name};
|
||||
use crate::internals::symbol::*;
|
||||
use crate::internals::{ungroup, Ctxt};
|
||||
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
|
||||
@@ -8,6 +9,7 @@ use std::iter::FromIterator;
|
||||
use syn::meta::ParseNestedMeta;
|
||||
use syn::parse::ParseStream;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_quote, token, Ident, Lifetime, Token};
|
||||
|
||||
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
||||
@@ -20,7 +22,7 @@ use syn::{parse_quote, token, Ident, Lifetime, Token};
|
||||
|
||||
pub use crate::internals::case::RenameRule;
|
||||
|
||||
struct Attr<'c, T> {
|
||||
pub(crate) struct Attr<'c, T> {
|
||||
cx: &'c Ctxt,
|
||||
name: Symbol,
|
||||
tokens: TokenStream,
|
||||
@@ -61,7 +63,7 @@ impl<'c, T> Attr<'c, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get(self) -> Option<T> {
|
||||
pub(crate) fn get(self) -> Option<T> {
|
||||
self.value
|
||||
}
|
||||
|
||||
@@ -89,7 +91,7 @@ impl<'c> BoolAttr<'c> {
|
||||
}
|
||||
}
|
||||
|
||||
struct VecAttr<'c, T> {
|
||||
pub(crate) struct VecAttr<'c, T> {
|
||||
cx: &'c Ctxt,
|
||||
name: Symbol,
|
||||
first_dup_tokens: TokenStream,
|
||||
@@ -124,63 +126,13 @@ impl<'c, T> VecAttr<'c, T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get(self) -> Vec<T> {
|
||||
pub(crate) fn get(self) -> Vec<T> {
|
||||
self.values
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Name {
|
||||
serialize: String,
|
||||
serialize_renamed: bool,
|
||||
deserialize: String,
|
||||
deserialize_renamed: bool,
|
||||
deserialize_aliases: BTreeSet<String>,
|
||||
}
|
||||
|
||||
fn unraw(ident: &Ident) -> String {
|
||||
ident.to_string().trim_start_matches("r#").to_owned()
|
||||
}
|
||||
|
||||
impl Name {
|
||||
fn from_attrs(
|
||||
source_name: String,
|
||||
ser_name: Attr<String>,
|
||||
de_name: Attr<String>,
|
||||
de_aliases: Option<VecAttr<String>>,
|
||||
) -> Name {
|
||||
let mut alias_set = BTreeSet::new();
|
||||
if let Some(de_aliases) = de_aliases {
|
||||
for alias_name in de_aliases.get() {
|
||||
alias_set.insert(alias_name);
|
||||
}
|
||||
}
|
||||
|
||||
let ser_name = ser_name.get();
|
||||
let ser_renamed = ser_name.is_some();
|
||||
let de_name = de_name.get();
|
||||
let de_renamed = de_name.is_some();
|
||||
Name {
|
||||
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
|
||||
serialize_renamed: ser_renamed,
|
||||
deserialize: de_name.unwrap_or(source_name),
|
||||
deserialize_renamed: de_renamed,
|
||||
deserialize_aliases: alias_set,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the container name for the container when serializing.
|
||||
pub fn serialize_name(&self) -> &str {
|
||||
&self.serialize
|
||||
}
|
||||
|
||||
/// Return the container name for the container when deserializing.
|
||||
pub fn deserialize_name(&self) -> &str {
|
||||
&self.deserialize
|
||||
}
|
||||
|
||||
fn deserialize_aliases(&self) -> &BTreeSet<String> {
|
||||
&self.deserialize_aliases
|
||||
}
|
||||
fn unraw(ident: &Ident) -> Ident {
|
||||
Ident::new(ident.to_string().trim_start_matches("r#"), ident.span())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -202,7 +154,7 @@ impl RenameAllRules {
|
||||
|
||||
/// Represents struct or enum attribute information.
|
||||
pub struct Container {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
transparent: bool,
|
||||
deny_unknown_fields: bool,
|
||||
default: Default,
|
||||
@@ -326,8 +278,8 @@ impl Container {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_renames(cx, RENAME, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
de_name.set_opt(&meta.path, de.as_ref().map(Name::from));
|
||||
} else if meta.path == RENAME_ALL {
|
||||
// #[serde(rename_all = "foo")]
|
||||
// #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
|
||||
@@ -566,7 +518,7 @@ impl Container {
|
||||
}
|
||||
|
||||
Container {
|
||||
name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
|
||||
name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None),
|
||||
transparent: transparent.get(),
|
||||
deny_unknown_fields: deny_unknown_fields.get(),
|
||||
default: default.get().unwrap_or(Default::None),
|
||||
@@ -593,7 +545,7 @@ impl Container {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
@@ -780,7 +732,7 @@ fn decide_identifier(
|
||||
|
||||
/// Represents variant attribute information
|
||||
pub struct Variant {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
rename_all_rules: RenameAllRules,
|
||||
ser_bound: Option<Vec<syn::WherePredicate>>,
|
||||
de_bound: Option<Vec<syn::WherePredicate>>,
|
||||
@@ -831,15 +783,15 @@ impl Variant {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
for de_value in de {
|
||||
de_name.set_if_none(de_value.value());
|
||||
de_aliases.insert(&meta.path, de_value.value());
|
||||
de_name.set_if_none(Name::from(&de_value));
|
||||
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||
}
|
||||
} else if meta.path == ALIAS {
|
||||
// #[serde(alias = "foo")]
|
||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||
de_aliases.insert(&meta.path, s.value());
|
||||
de_aliases.insert(&meta.path, Name::from(&s));
|
||||
}
|
||||
} else if meta.path == RENAME_ALL {
|
||||
// #[serde(rename_all = "foo")]
|
||||
@@ -888,13 +840,13 @@ impl Variant {
|
||||
ser_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("serialize", Span::call_site()).into());
|
||||
.push(Ident::new("serialize", ser_path.span()).into());
|
||||
serialize_with.set(&meta.path, ser_path);
|
||||
let mut de_path = path;
|
||||
de_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("deserialize", Span::call_site()).into());
|
||||
.push(Ident::new("deserialize", de_path.span()).into());
|
||||
deserialize_with.set(&meta.path, de_path);
|
||||
}
|
||||
} else if meta.path == SERIALIZE_WITH {
|
||||
@@ -946,7 +898,12 @@ impl Variant {
|
||||
}
|
||||
|
||||
Variant {
|
||||
name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)),
|
||||
name: MultiName::from_attrs(
|
||||
Name::from(&unraw(&variant.ident)),
|
||||
ser_name,
|
||||
de_name,
|
||||
Some(de_aliases),
|
||||
),
|
||||
rename_all_rules: RenameAllRules {
|
||||
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
|
||||
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
|
||||
@@ -963,20 +920,23 @@ impl Variant {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn aliases(&self) -> &BTreeSet<String> {
|
||||
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||
self.name.deserialize_aliases()
|
||||
}
|
||||
|
||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||
if !self.name.serialize_renamed {
|
||||
self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
|
||||
self.name.serialize.value =
|
||||
rules.serialize.apply_to_variant(&self.name.serialize.value);
|
||||
}
|
||||
if !self.name.deserialize_renamed {
|
||||
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
|
||||
self.name.deserialize.value = rules
|
||||
.deserialize
|
||||
.apply_to_variant(&self.name.deserialize.value);
|
||||
}
|
||||
self.name
|
||||
.deserialize_aliases
|
||||
@@ -1022,7 +982,7 @@ impl Variant {
|
||||
|
||||
/// Represents field attribute information
|
||||
pub struct Field {
|
||||
name: Name,
|
||||
name: MultiName,
|
||||
skip_serializing: bool,
|
||||
skip_deserializing: bool,
|
||||
skip_serializing_if: Option<syn::ExprPath>,
|
||||
@@ -1081,8 +1041,11 @@ impl Field {
|
||||
let mut flatten = BoolAttr::none(cx, FLATTEN);
|
||||
|
||||
let ident = match &field.ident {
|
||||
Some(ident) => unraw(ident),
|
||||
None => index.to_string(),
|
||||
Some(ident) => Name::from(&unraw(ident)),
|
||||
None => Name {
|
||||
value: index.to_string(),
|
||||
span: Span::call_site(),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
|
||||
@@ -1118,15 +1081,15 @@ impl Field {
|
||||
// #[serde(rename = "foo")]
|
||||
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
|
||||
let (ser, de) = get_multiple_renames(cx, &meta)?;
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
|
||||
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
|
||||
for de_value in de {
|
||||
de_name.set_if_none(de_value.value());
|
||||
de_aliases.insert(&meta.path, de_value.value());
|
||||
de_name.set_if_none(Name::from(&de_value));
|
||||
de_aliases.insert(&meta.path, Name::from(&de_value));
|
||||
}
|
||||
} else if meta.path == ALIAS {
|
||||
// #[serde(alias = "foo")]
|
||||
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
|
||||
de_aliases.insert(&meta.path, s.value());
|
||||
de_aliases.insert(&meta.path, Name::from(&s));
|
||||
}
|
||||
} else if meta.path == DEFAULT {
|
||||
if meta.input.peek(Token![=]) {
|
||||
@@ -1170,13 +1133,13 @@ impl Field {
|
||||
ser_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("serialize", Span::call_site()).into());
|
||||
.push(Ident::new("serialize", ser_path.span()).into());
|
||||
serialize_with.set(&meta.path, ser_path);
|
||||
let mut de_path = path;
|
||||
de_path
|
||||
.path
|
||||
.segments
|
||||
.push(Ident::new("deserialize", Span::call_site()).into());
|
||||
.push(Ident::new("deserialize", de_path.span()).into());
|
||||
deserialize_with.set(&meta.path, de_path);
|
||||
}
|
||||
} else if meta.path == BOUND {
|
||||
@@ -1289,7 +1252,7 @@ impl Field {
|
||||
}
|
||||
|
||||
Field {
|
||||
name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
|
||||
name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
|
||||
skip_serializing: skip_serializing.get(),
|
||||
skip_deserializing: skip_deserializing.get(),
|
||||
skip_serializing_if: skip_serializing_if.get(),
|
||||
@@ -1305,20 +1268,22 @@ impl Field {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &Name {
|
||||
pub fn name(&self) -> &MultiName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn aliases(&self) -> &BTreeSet<String> {
|
||||
pub fn aliases(&self) -> &BTreeSet<Name> {
|
||||
self.name.deserialize_aliases()
|
||||
}
|
||||
|
||||
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
|
||||
if !self.name.serialize_renamed {
|
||||
self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
|
||||
self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value);
|
||||
}
|
||||
if !self.name.deserialize_renamed {
|
||||
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
|
||||
self.name.deserialize.value = rules
|
||||
.deserialize
|
||||
.apply_to_field(&self.name.deserialize.value);
|
||||
}
|
||||
self.name
|
||||
.deserialize_aliases
|
||||
@@ -1768,7 +1733,7 @@ fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
|
||||
// attribute on the field so there must be at least one borrowable lifetime.
|
||||
fn borrowable_lifetimes(
|
||||
cx: &Ctxt,
|
||||
name: &str,
|
||||
name: &Name,
|
||||
field: &syn::Field,
|
||||
) -> Result<BTreeSet<syn::Lifetime>, ()> {
|
||||
let mut lifetimes = BTreeSet::new();
|
||||
|
||||
@@ -329,13 +329,13 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
||||
let name = field.attrs.name();
|
||||
let ser_name = name.serialize_name();
|
||||
|
||||
if check_ser && ser_name == tag {
|
||||
if check_ser && ser_name.value == tag {
|
||||
diagnose_conflict();
|
||||
return;
|
||||
}
|
||||
|
||||
for de_name in field.attrs.aliases() {
|
||||
if check_de && de_name == tag {
|
||||
if check_de && de_name.value == tag {
|
||||
diagnose_conflict();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod ast;
|
||||
pub mod attr;
|
||||
pub mod name;
|
||||
|
||||
mod case;
|
||||
mod check;
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
use crate::internals::attr::{Attr, VecAttr};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::ToTokens;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::{self, Display};
|
||||
use syn::LitStr;
|
||||
|
||||
pub struct MultiName {
|
||||
pub(crate) serialize: Name,
|
||||
pub(crate) serialize_renamed: bool,
|
||||
pub(crate) deserialize: Name,
|
||||
pub(crate) deserialize_renamed: bool,
|
||||
pub(crate) deserialize_aliases: BTreeSet<Name>,
|
||||
}
|
||||
|
||||
impl MultiName {
|
||||
pub(crate) fn from_attrs(
|
||||
source_name: Name,
|
||||
ser_name: Attr<Name>,
|
||||
de_name: Attr<Name>,
|
||||
de_aliases: Option<VecAttr<Name>>,
|
||||
) -> Self {
|
||||
let mut alias_set = BTreeSet::new();
|
||||
if let Some(de_aliases) = de_aliases {
|
||||
for alias_name in de_aliases.get() {
|
||||
alias_set.insert(alias_name);
|
||||
}
|
||||
}
|
||||
|
||||
let ser_name = ser_name.get();
|
||||
let ser_renamed = ser_name.is_some();
|
||||
let de_name = de_name.get();
|
||||
let de_renamed = de_name.is_some();
|
||||
MultiName {
|
||||
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
|
||||
serialize_renamed: ser_renamed,
|
||||
deserialize: de_name.unwrap_or(source_name),
|
||||
deserialize_renamed: de_renamed,
|
||||
deserialize_aliases: alias_set,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the container name for the container when serializing.
|
||||
pub fn serialize_name(&self) -> &Name {
|
||||
&self.serialize
|
||||
}
|
||||
|
||||
/// Return the container name for the container when deserializing.
|
||||
pub fn deserialize_name(&self) -> &Name {
|
||||
&self.deserialize
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<Name> {
|
||||
&self.deserialize_aliases
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Name {
|
||||
pub value: String,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl ToTokens for Name {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
LitStr::new(&self.value, self.span).to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Name {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&self.value, &other.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Name {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(Ord::cmp(self, other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Name {}
|
||||
|
||||
impl PartialEq for Name {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Ident> for Name {
|
||||
fn from(ident: &Ident) -> Self {
|
||||
Name {
|
||||
value: ident.to_string(),
|
||||
span: ident.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&LitStr> for Name {
|
||||
fn from(lit: &LitStr) -> Self {
|
||||
Name {
|
||||
value: lit.value(),
|
||||
span: lit.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Name {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.value, formatter)
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,9 @@ impl ReplaceReceiver<'_> {
|
||||
match bound {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
|
||||
TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {}
|
||||
TypeParamBound::Lifetime(_)
|
||||
| TypeParamBound::PreciseCapture(_)
|
||||
| TypeParamBound::Verbatim(_) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ impl PartialEq<Symbol> for Ident {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<Symbol> for &'a Ident {
|
||||
impl PartialEq<Symbol> for &Ident {
|
||||
fn eq(&self, word: &Symbol) -> bool {
|
||||
*self == word.0
|
||||
}
|
||||
@@ -58,7 +58,7 @@ impl PartialEq<Symbol> for Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<Symbol> for &'a Path {
|
||||
impl PartialEq<Symbol> for &Path {
|
||||
fn eq(&self, word: &Symbol) -> bool {
|
||||
self.is_ident(word.0)
|
||||
}
|
||||
|
||||
@@ -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.209")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.215")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
@@ -27,6 +27,7 @@
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::match_like_matches_macro,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::too_many_arguments,
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
@@ -55,6 +56,7 @@
|
||||
clippy::single_match_else,
|
||||
clippy::struct_excessive_bools,
|
||||
clippy::too_many_lines,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unseparated_literal_suffix,
|
||||
clippy::unused_self,
|
||||
clippy::use_self,
|
||||
|
||||
+20
-8
@@ -1,5 +1,6 @@
|
||||
use crate::fragment::{Fragment, Match, Stmts};
|
||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use crate::internals::name::Name;
|
||||
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
|
||||
use crate::{bound, dummy, pretend, this};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
@@ -798,9 +799,9 @@ fn serialize_untagged_variant(
|
||||
|
||||
enum TupleVariant<'a> {
|
||||
ExternallyTagged {
|
||||
type_name: &'a str,
|
||||
type_name: &'a Name,
|
||||
variant_index: u32,
|
||||
variant_name: &'a str,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
@@ -867,11 +868,11 @@ fn serialize_tuple_variant(
|
||||
enum StructVariant<'a> {
|
||||
ExternallyTagged {
|
||||
variant_index: u32,
|
||||
variant_name: &'a str,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
InternallyTagged {
|
||||
tag: &'a str,
|
||||
variant_name: &'a str,
|
||||
variant_name: &'a Name,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
@@ -880,7 +881,7 @@ fn serialize_struct_variant(
|
||||
context: StructVariant,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
name: &Name,
|
||||
) -> Fragment {
|
||||
if fields.iter().any(|field| field.attrs.flatten()) {
|
||||
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
||||
@@ -964,7 +965,7 @@ fn serialize_struct_variant_with_flatten(
|
||||
context: StructVariant,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
name: &Name,
|
||||
) -> Fragment {
|
||||
let struct_trait = StructTrait::SerializeMap;
|
||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||
@@ -1220,6 +1221,17 @@ fn wrap_serialize_with(
|
||||
})
|
||||
});
|
||||
|
||||
let self_var = quote!(self);
|
||||
let serializer_var = quote!(__s);
|
||||
|
||||
// If #serialize_with returns wrong type, error will be reported on here.
|
||||
// We attach span of the path to this piece so error will be reported
|
||||
// on the #[serde(with = "...")]
|
||||
// ^^^^^
|
||||
let wrapper_serialize = quote_spanned! {serialize_with.span()=>
|
||||
#serialize_with(#(#self_var.values.#field_access, )* #serializer_var)
|
||||
};
|
||||
|
||||
quote!({
|
||||
#[doc(hidden)]
|
||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||
@@ -1228,11 +1240,11 @@ fn wrap_serialize_with(
|
||||
}
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
|
||||
fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
|
||||
fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
#serialize_with(#(self.values.#field_access, )* __s)
|
||||
#wrapper_serialize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.61"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::redundant_field_names,
|
||||
clippy::result_unit_err,
|
||||
clippy::should_implement_trait,
|
||||
@@ -35,6 +36,7 @@
|
||||
clippy::single_match_else,
|
||||
clippy::struct_excessive_bools,
|
||||
clippy::too_many_lines,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unused_self,
|
||||
clippy::wildcard_imports
|
||||
)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
@@ -18,11 +18,15 @@ fn simple_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Simple { a: 42 },
|
||||
&[
|
||||
Token::StructVariant { name: "Enum", variant: "Simple", len: 1 },
|
||||
Token::StructVariant {
|
||||
name: "Enum",
|
||||
variant: "Simple",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::StructVariantEnd,
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,11 +35,14 @@ fn flatten_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Flatten { flatten: (), a: 42 },
|
||||
&[
|
||||
Token::NewtypeVariant { name: "Enum", variant: "Flatten" },
|
||||
Token::NewtypeVariant {
|
||||
name: "Enum",
|
||||
variant: "Flatten",
|
||||
},
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::MapEnd,
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
macro_rules! declare_in_macro {
|
||||
($with:literal) => {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct S {
|
||||
#[serde(with = $with)]
|
||||
f: i32,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare_in_macro!("with");
|
||||
|
||||
mod with {
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S>(_: &i32, _: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
macro_rules! declare_in_macro {
|
||||
($with:literal) => {
|
||||
#[derive(Deserialize)]
|
||||
pub struct S(
|
||||
#[serde(with = $with)]
|
||||
#[allow(dead_code)]
|
||||
i32,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
declare_in_macro!("with");
|
||||
|
||||
mod with {
|
||||
use serde::Deserializer;
|
||||
|
||||
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -782,7 +782,7 @@ fn test_unknown_field_rename_enum() {
|
||||
variant: "SailorMoon",
|
||||
len: 3,
|
||||
}],
|
||||
"unknown variant `SailorMoon`, expected `sailor_moon`",
|
||||
"unknown variant `SailorMoon`, expected `sailor_moon` or `usagi_tsukino`",
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<AliasEnum>(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![allow(
|
||||
clippy::extra_unused_type_parameters,
|
||||
clippy::needless_lifetimes,
|
||||
clippy::type_repetition_in_bounds
|
||||
)]
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum E {
|
||||
S1 {
|
||||
#[serde(alias = "a", alias = "b", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "c" and "b"
|
||||
#[serde(alias = "c")]
|
||||
b: (),
|
||||
|
||||
#[serde(skip_deserializing)]
|
||||
c: (),
|
||||
},
|
||||
|
||||
S2 {
|
||||
#[serde(alias = "b", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "c"
|
||||
#[serde(rename = "c")]
|
||||
b: (),
|
||||
},
|
||||
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
S3 {
|
||||
#[serde(alias = "B", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "b" because this collides with the "B" above after
|
||||
// applying rename rules
|
||||
b: (),
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum E1 {
|
||||
#[serde(alias = "a", alias = "b", alias = "c")]
|
||||
a,
|
||||
|
||||
// Warning on "c" and "b"
|
||||
#[serde(alias = "c")]
|
||||
b,
|
||||
|
||||
#[serde(skip_deserializing)]
|
||||
c,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum E2 {
|
||||
#[serde(alias = "b", alias = "c")]
|
||||
a,
|
||||
|
||||
// Warning on "c"
|
||||
#[serde(rename = "c")]
|
||||
b,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
enum E3 {
|
||||
#[serde(alias = "B", alias = "c")]
|
||||
a,
|
||||
|
||||
// Warning on "b" because this collides with the "B" above after applying
|
||||
// rename rules
|
||||
b,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
__FAIL__;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
error[E0425]: cannot find value `__FAIL__` in this scope
|
||||
--> tests/ui/conflict/alias-enum.rs:74:5
|
||||
|
|
||||
74 | __FAIL__;
|
||||
| ^^^^^^^^ not found in this scope
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:13:9
|
||||
|
|
||||
8 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
13 | b: (),
|
||||
| ^ no value can reach this
|
||||
|
|
||||
= note: `#[warn(unreachable_patterns)]` on by default
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:12:25
|
||||
|
|
||||
8 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
12 | #[serde(alias = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:24:26
|
||||
|
|
||||
20 | #[serde(alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
24 | #[serde(rename = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:35:9
|
||||
|
|
||||
30 | #[serde(alias = "B", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
35 | b: (),
|
||||
| ^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:46:5
|
||||
|
|
||||
41 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
46 | b,
|
||||
| ^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:45:21
|
||||
|
|
||||
41 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
45 | #[serde(alias = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:58:22
|
||||
|
|
||||
54 | #[serde(alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
58 | #[serde(rename = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias-enum.rs:70:5
|
||||
|
|
||||
65 | #[serde(alias = "B", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
70 | b,
|
||||
| ^ no value can reach this
|
||||
@@ -0,0 +1,39 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct S1 {
|
||||
#[serde(alias = "a", alias = "b", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "c" and "b"
|
||||
#[serde(alias = "c")]
|
||||
b: (),
|
||||
|
||||
#[serde(skip_deserializing)]
|
||||
c: (),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct S2 {
|
||||
#[serde(alias = "b", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "c"
|
||||
#[serde(rename = "c")]
|
||||
b: (),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
struct S3 {
|
||||
#[serde(alias = "B", alias = "c")]
|
||||
a: (),
|
||||
|
||||
// Warning on "b" because this collides with the "B" above after applying
|
||||
// rename rules
|
||||
b: (),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
__FAIL__;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
error[E0425]: cannot find value `__FAIL__` in this scope
|
||||
--> tests/ui/conflict/alias.rs:38:5
|
||||
|
|
||||
38 | __FAIL__;
|
||||
| ^^^^^^^^ not found in this scope
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias.rs:10:5
|
||||
|
|
||||
5 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
10 | b: (),
|
||||
| ^ no value can reach this
|
||||
|
|
||||
= note: `#[warn(unreachable_patterns)]` on by default
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias.rs:9:21
|
||||
|
|
||||
5 | #[serde(alias = "a", alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
9 | #[serde(alias = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias.rs:22:22
|
||||
|
|
||||
18 | #[serde(alias = "b", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
22 | #[serde(rename = "c")]
|
||||
| ^^^ no value can reach this
|
||||
|
||||
warning: unreachable pattern
|
||||
--> tests/ui/conflict/alias.rs:34:5
|
||||
|
|
||||
29 | #[serde(alias = "B", alias = "c")]
|
||||
| --- matches all the relevant values
|
||||
...
|
||||
34 | b: (),
|
||||
| ^ no value can reach this
|
||||
@@ -0,0 +1,20 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
enum Enum {
|
||||
// Newtype variants do not use the provided path, so it is forbidden here
|
||||
// Newtype(#[serde(default = "main")] u8),
|
||||
Tuple(u8, #[serde(default = "main")] i8),
|
||||
Struct {
|
||||
#[serde(default = "main")]
|
||||
f1: u8,
|
||||
f2: u8,
|
||||
#[serde(default = "main")]
|
||||
f3: i8,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:10:33
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
10 | Tuple(u8, #[serde(default = "main")] i8),
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:12:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
12 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:15:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
15 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,19 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum Enum {
|
||||
// Newtype variants do not use the provided path, so it is forbidden here
|
||||
// Newtype(#[serde(default = "main")] u8),
|
||||
Tuple(u8, #[serde(default = "main")] i8),
|
||||
Struct {
|
||||
#[serde(default = "main")]
|
||||
f1: u8,
|
||||
f2: u8,
|
||||
#[serde(default = "main")]
|
||||
f3: i8,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:9:33
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
9 | Tuple(u8, #[serde(default = "main")] i8),
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:11:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
11 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:14:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
14 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,20 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag")]
|
||||
enum Enum {
|
||||
// Newtype variants do not use the provided path, so it is forbidden here
|
||||
// Newtype(#[serde(default = "main")] u8),
|
||||
// Tuple variants are not supported in internally tagged enums
|
||||
Struct {
|
||||
#[serde(default = "main")]
|
||||
f1: u8,
|
||||
f2: u8,
|
||||
#[serde(default = "main")]
|
||||
f3: i8,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,23 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:12:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
12 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:15:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
15 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,20 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Enum {
|
||||
// Newtype variants do not use the provided path, so it is forbidden here
|
||||
// Newtype(#[serde(default = "main")] u8),
|
||||
Tuple(u8, #[serde(default = "main")] i8),
|
||||
Struct {
|
||||
#[serde(default = "main")]
|
||||
f1: u8,
|
||||
f2: u8,
|
||||
#[serde(default = "main")]
|
||||
f3: i8,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:10:33
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
10 | Tuple(u8, #[serde(default = "main")] i8),
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:12:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
12 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:15:27
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
15 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,9 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default = "main")]
|
||||
struct Newtype(#[serde(default = "main")] u8);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^
|
||||
| |
|
||||
| expected `Newtype`, found `()`
|
||||
| expected due to this
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
6 | #[serde(default = "main")]
|
||||
7 | struct Newtype(#[serde(default = "main")] u8);
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `Newtype`, found `()`
|
||||
7 | struct Newtype(#[serde(default = "main")] u8);
|
||||
| ------- expected due to this
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| ----------- expected due to the type of this binding
|
||||
6 | #[serde(default = "main")]
|
||||
7 | struct Newtype(#[serde(default = "main")] u8);
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
@@ -0,0 +1,15 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default = "main")]
|
||||
struct Struct {
|
||||
#[serde(default = "main")]
|
||||
f1: u8,
|
||||
f2: u8,
|
||||
#[serde(default = "main")]
|
||||
f3: i8,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,58 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^
|
||||
| |
|
||||
| expected `Struct`, found `()`
|
||||
| expected due to this
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:8:23
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `u8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
8 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:11:23
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
...
|
||||
11 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `Struct`, found `()`
|
||||
7 | struct Struct {
|
||||
| ------ expected due to this
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:8:23
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| ----------- expected due to the type of this binding
|
||||
...
|
||||
8 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `u8`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_struct.rs:11:23
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| ----------- expected due to the type of this binding
|
||||
...
|
||||
11 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,9 @@
|
||||
// Tests that type error points to the path in attribute
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default = "main")]
|
||||
struct Tuple(u8, #[serde(default = "main")] i8);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,37 @@
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^
|
||||
| |
|
||||
| expected `Tuple`, found `()`
|
||||
| expected due to this
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| -----------
|
||||
| |
|
||||
| this is found to be of type `i8`
|
||||
| `match` arms have incompatible types
|
||||
6 | #[serde(default = "main")]
|
||||
7 | struct Tuple(u8, #[serde(default = "main")] i8);
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19
|
||||
|
|
||||
6 | #[serde(default = "main")]
|
||||
| ^^^^^^ expected `Tuple`, found `()`
|
||||
7 | struct Tuple(u8, #[serde(default = "main")] i8);
|
||||
| ----- expected due to this
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36
|
||||
|
|
||||
5 | #[derive(Deserialize)]
|
||||
| ----------- expected due to the type of this binding
|
||||
6 | #[serde(default = "main")]
|
||||
7 | struct Tuple(u8, #[serde(default = "main")] i8);
|
||||
| ^^^^^^ expected `i8`, found `()`
|
||||
@@ -0,0 +1,9 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default)]
|
||||
union Union {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: #[serde(default)] can only be used on structs
|
||||
--> tests/ui/default-attribute/union.rs:4:9
|
||||
|
|
||||
4 | #[serde(default)]
|
||||
| ^^^^^^^
|
||||
|
||||
error: Serde does not support derive for unions
|
||||
--> tests/ui/default-attribute/union.rs:4:1
|
||||
|
|
||||
4 | / #[serde(default)]
|
||||
5 | | union Union {
|
||||
6 | | f: u8,
|
||||
7 | | }
|
||||
| |_^
|
||||
@@ -0,0 +1,9 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default = "default_u")]
|
||||
union Union {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: #[serde(default = "...")] can only be used on structs
|
||||
--> tests/ui/default-attribute/union_path.rs:4:9
|
||||
|
|
||||
4 | #[serde(default = "default_u")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Serde does not support derive for unions
|
||||
--> tests/ui/default-attribute/union_path.rs:4:1
|
||||
|
|
||||
4 | / #[serde(default = "default_u")]
|
||||
5 | | union Union {
|
||||
6 | | f: u8,
|
||||
7 | | }
|
||||
| |_^
|
||||
@@ -0,0 +1,7 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default)]
|
||||
struct Unit;
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,7 @@
|
||||
error: #[serde(default)] can only be used on structs that have fields
|
||||
--> tests/ui/default-attribute/unit.rs:3:10
|
||||
|
|
||||
3 | #[derive(Deserialize)]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@@ -0,0 +1,7 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(default = "default_u")]
|
||||
struct Unit;
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: #[serde(default = "...")] can only be used on structs that have fields
|
||||
--> tests/ui/default-attribute/unit_path.rs:4:9
|
||||
|
|
||||
4 | #[serde(default = "default_u")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1,23 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
mod w {
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(_: D) -> Result<(), D::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn serialize<T, S: Serializer>(_: S) -> Result<S::Ok, S::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct W(#[serde(with = "w")] u8, u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct S(#[serde(serialize_with = "w::serialize")] u8, u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,101 @@
|
||||
error[E0277]: the trait bound `&u8: Serializer` is not satisfied
|
||||
--> tests/ui/with/incorrect_type.rs:14:10
|
||||
|
|
||||
14 | #[derive(Serialize, Deserialize)]
|
||||
| ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8`
|
||||
15 | struct W(#[serde(with = "w")] u8, u8);
|
||||
| --- required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `Serializer`:
|
||||
&mut Formatter<'a>
|
||||
FlatMapSerializer<'a, M>
|
||||
_::_serde::__private::ser::content::ContentSerializer<E>
|
||||
note: required by a bound in `w::serialize`
|
||||
--> tests/ui/with/incorrect_type.rs:9:28
|
||||
|
|
||||
9 | pub fn serialize<T, S: Serializer>(_: S) -> Result<S::Ok, S::Error> {
|
||||
| ^^^^^^^^^^ required by this bound in `serialize`
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> tests/ui/with/incorrect_type.rs:15:25
|
||||
|
|
||||
14 | #[derive(Serialize, Deserialize)]
|
||||
| --------- unexpected argument #2 of type `__S`
|
||||
15 | struct W(#[serde(with = "w")] u8, u8);
|
||||
| ^^^
|
||||
|
|
||||
note: function defined here
|
||||
--> tests/ui/with/incorrect_type.rs:9:12
|
||||
|
|
||||
9 | pub fn serialize<T, S: Serializer>(_: S) -> Result<S::Ok, S::Error> {
|
||||
| ^^^^^^^^^ ----
|
||||
|
||||
error[E0277]: the trait bound `&u8: Serializer` is not satisfied
|
||||
--> tests/ui/with/incorrect_type.rs:15:25
|
||||
|
|
||||
15 | struct W(#[serde(with = "w")] u8, u8);
|
||||
| ^^^ the trait `Serializer` is not implemented for `&u8`
|
||||
|
|
||||
= help: the following other types implement trait `Serializer`:
|
||||
&mut Formatter<'a>
|
||||
FlatMapSerializer<'a, M>
|
||||
_::_serde::__private::ser::content::ContentSerializer<E>
|
||||
|
||||
error[E0308]: `?` operator has incompatible types
|
||||
--> tests/ui/with/incorrect_type.rs:15:25
|
||||
|
|
||||
15 | struct W(#[serde(with = "w")] u8, u8);
|
||||
| ^^^ expected `u8`, found `()`
|
||||
|
|
||||
= note: `?` operator cannot convert from `()` to `u8`
|
||||
|
||||
error[E0277]: the trait bound `&u8: Serializer` is not satisfied
|
||||
--> tests/ui/with/incorrect_type.rs:17:10
|
||||
|
|
||||
17 | #[derive(Serialize, Deserialize)]
|
||||
| ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8`
|
||||
18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8);
|
||||
| -------------- required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `Serializer`:
|
||||
&mut Formatter<'a>
|
||||
FlatMapSerializer<'a, M>
|
||||
_::_serde::__private::ser::content::ContentSerializer<E>
|
||||
note: required by a bound in `w::serialize`
|
||||
--> tests/ui/with/incorrect_type.rs:9:28
|
||||
|
|
||||
9 | pub fn serialize<T, S: Serializer>(_: S) -> Result<S::Ok, S::Error> {
|
||||
| ^^^^^^^^^^ required by this bound in `serialize`
|
||||
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> tests/ui/with/incorrect_type.rs:18:35
|
||||
|
|
||||
17 | #[derive(Serialize, Deserialize)]
|
||||
| --------- unexpected argument #2 of type `__S`
|
||||
18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: function defined here
|
||||
--> tests/ui/with/incorrect_type.rs:9:12
|
||||
|
|
||||
9 | pub fn serialize<T, S: Serializer>(_: S) -> Result<S::Ok, S::Error> {
|
||||
| ^^^^^^^^^ ----
|
||||
|
||||
error[E0277]: the trait bound `&u8: Serializer` is not satisfied
|
||||
--> tests/ui/with/incorrect_type.rs:18:35
|
||||
|
|
||||
18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8);
|
||||
| ^^^^^^^^^^^^^^ the trait `Serializer` is not implemented for `&u8`
|
||||
|
|
||||
= help: the following other types implement trait `Serializer`:
|
||||
&mut Formatter<'a>
|
||||
FlatMapSerializer<'a, M>
|
||||
_::_serde::__private::ser::content::ContentSerializer<E>
|
||||
|
||||
error[E0308]: `?` operator has incompatible types
|
||||
--> tests/ui/with/incorrect_type.rs:21:37
|
||||
|
|
||||
21 | struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8);
|
||||
| ^^^^^^^^^^^^^^^^ expected `u8`, found `()`
|
||||
|
|
||||
= note: `?` operator cannot convert from `()` to `u8`
|
||||
Reference in New Issue
Block a user