serde_derive-1.0.195/.cargo_vcs_info.json0000644000000001520000000000100136470ustar { "git": { "sha1": "03eec42c3313b36da416be1486e9ecac345784d5" }, "path_in_vcs": "serde_derive" }serde_derive-1.0.195/Cargo.toml0000644000000026120000000000100116500ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] rust-version = "1.56" name = "serde_derive" version = "1.0.195" authors = [ "Erick Tryzelaar ", "David Tolnay ", ] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" homepage = "https://serde.rs" documentation = "https://serde.rs/derive.html" readme = "crates-io.md" keywords = [ "serde", "serialization", "no_std", "derive", ] categories = [ "no-std", "no-std::no-alloc", ] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] name = "serde_derive" proc-macro = true [dependencies.proc-macro2] version = "1.0.74" [dependencies.quote] version = "1.0.35" [dependencies.syn] version = "2.0.46" [dev-dependencies.serde] version = "1" [features] default = [] deserialize_in_place = [] serde_derive-1.0.195/Cargo.toml.orig000064400000000000000000000015571046102023000153400ustar 00000000000000[package] name = "serde_derive" version = "1.0.195" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" documentation = "https://serde.rs/derive.html" homepage = "https://serde.rs" 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" [features] default = [] deserialize_in_place = [] [lib] name = "serde_derive" proc-macro = true [dependencies] proc-macro2 = "1.0.74" quote = "1.0.35" syn = "2.0.46" [dev-dependencies] serde = { version = "1", path = "../serde" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = ["--generate-link-to-definition"] serde_derive-1.0.195/LICENSE-APACHE000064400000000000000000000227731046102023000144000ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS serde_derive-1.0.195/LICENSE-MIT000064400000000000000000000017771046102023000141110ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. serde_derive-1.0.195/README.md000064400000000000000000000104161046102023000137220ustar 00000000000000# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.31+]][Rust 1.31] [![serde_derive: rustc 1.56+]][Rust 1.56] [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 [Latest Version]: https://img.shields.io/crates/v/serde.svg [crates.io]: https://crates.io/crates/serde [serde: rustc 1.31+]: https://img.shields.io/badge/serde-rustc_1.31+-lightgray.svg [serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg [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 **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** --- You may be looking for: - [An overview of Serde](https://serde.rs/) - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) - [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action
Click to show Cargo.toml. Run this code in the playground. ```toml [dependencies] # The core APIs, including the Serialize and Deserialize traits. Always # required when using Serde. The "derive" feature is only required when # using #[derive(Serialize, Deserialize)] to make Serde work with structs # and enums defined in your crate. serde = { version = "1.0", features = ["derive"] } # Each data format lives in its own crate; the sample code below uses JSON # but you may be using a different one. serde_json = "1.0" ```

```rust use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { x: i32, y: i32, } fn main() { let point = Point { x: 1, y: 2 }; // Convert the Point to a JSON string. let serialized = serde_json::to_string(&point).unwrap(); // Prints serialized = {"x":1,"y":2} println!("serialized = {}", serialized); // Convert the JSON string back to a Point. let deserialized: Point = serde_json::from_str(&serialized).unwrap(); // Prints deserialized = Point { x: 1, y: 2 } println!("deserialized = {:?}", deserialized); } ``` ## Getting help Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the [#rust-questions] or [#rust-beginners] channels of the unofficial community Discord (invite: ), the [#rust-usage] or [#beginners] channels of the official Rust Project Discord (invite: ), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust [Discourse forum][discourse]. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time. [#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513 [#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [#beginners]: https://discord.com/channels/442252698964721669/448238009733742612 [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general [stackoverflow]: https://stackoverflow.com/questions/tagged/rust [/r/rust]: https://www.reddit.com/r/rust [discourse]: https://users.rust-lang.org
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. serde_derive-1.0.195/crates-io.md000064400000000000000000000047521046102023000146610ustar 00000000000000 **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** --- You may be looking for: - [An overview of Serde](https://serde.rs/) - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) - [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action ```rust use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { x: i32, y: i32, } fn main() { let point = Point { x: 1, y: 2 }; // Convert the Point to a JSON string. let serialized = serde_json::to_string(&point).unwrap(); // Prints serialized = {"x":1,"y":2} println!("serialized = {}", serialized); // Convert the JSON string back to a Point. let deserialized: Point = serde_json::from_str(&serialized).unwrap(); // Prints deserialized = Point { x: 1, y: 2 } println!("deserialized = {:?}", deserialized); } ``` ## Getting help Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the [#rust-questions] or [#rust-beginners] channels of the unofficial community Discord (invite: , the [#rust-usage] or [#beginners] channels of the official Rust Project Discord (invite: ), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust [Discourse forum][discourse]. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time. [#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513 [#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [#beginners]: https://discord.com/channels/442252698964721669/448238009733742612 [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general [stackoverflow]: https://stackoverflow.com/questions/tagged/rust [/r/rust]: https://www.reddit.com/r/rust [discourse]: https://users.rust-lang.org serde_derive-1.0.195/src/bound.rs000064400000000000000000000344321046102023000147130ustar 00000000000000use crate::internals::ast::{Container, Data}; use crate::internals::{attr, ungroup}; use proc_macro2::Span; use std::collections::HashSet; use syn::punctuated::{Pair, Punctuated}; use syn::Token; // Remove the default from every type parameter because in the generated impls // they look like associated types: "error: associated type bindings are not // allowed here". pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { syn::Generics { params: generics .params .iter() .map(|param| match param { syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam { eq_token: None, default: None, ..param.clone() }), _ => param.clone(), }) .collect(), ..generics.clone() } } pub fn with_where_predicates( generics: &syn::Generics, predicates: &[syn::WherePredicate], ) -> syn::Generics { let mut generics = generics.clone(); generics .make_where_clause() .predicates .extend(predicates.iter().cloned()); generics } pub fn with_where_predicates_from_fields( cont: &Container, generics: &syn::Generics, from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>, ) -> syn::Generics { let predicates = cont .data .all_fields() .filter_map(|field| from_field(&field.attrs)) .flat_map(<[syn::WherePredicate]>::to_vec); let mut generics = generics.clone(); generics.make_where_clause().predicates.extend(predicates); generics } pub fn with_where_predicates_from_variants( cont: &Container, generics: &syn::Generics, from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>, ) -> syn::Generics { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => { return generics.clone(); } }; let predicates = variants .iter() .filter_map(|variant| from_variant(&variant.attrs)) .flat_map(<[syn::WherePredicate]>::to_vec); let mut generics = generics.clone(); generics.make_where_clause().predicates.extend(predicates); generics } // Puts the given bound on any generic type parameters that are used in fields // for which filter returns true. // // For example, the following struct needs the bound `A: Serialize, B: // Serialize`. // // struct S<'b, A, B: 'b, C> { // a: A, // b: Option<&'b B> // #[serde(skip_serializing)] // c: C, // } pub fn with_bound( cont: &Container, generics: &syn::Generics, filter: fn(&attr::Field, Option<&attr::Variant>) -> bool, bound: &syn::Path, ) -> syn::Generics { struct FindTyParams<'ast> { // Set of all generic type parameters on the current struct (A, B, C in // the example). Initialized up front. all_type_params: HashSet, // Set of generic type parameters used in fields for which filter // returns true (A and B in the example). Filled in as the visitor sees // them. relevant_type_params: HashSet, // Fields whose type is an associated type of one of the generic type // parameters. associated_type_usage: Vec<&'ast syn::TypePath>, } impl<'ast> FindTyParams<'ast> { fn visit_field(&mut self, field: &'ast syn::Field) { if let syn::Type::Path(ty) = ungroup(&field.ty) { if let Some(Pair::Punctuated(t, _)) = ty.path.segments.pairs().next() { if self.all_type_params.contains(&t.ident) { self.associated_type_usage.push(ty); } } } self.visit_type(&field.ty); } fn visit_path(&mut self, path: &'ast syn::Path) { if let Some(seg) = path.segments.last() { if seg.ident == "PhantomData" { // Hardcoded exception, because PhantomData implements // Serialize and Deserialize whether or not T implements it. return; } } if path.leading_colon.is_none() && path.segments.len() == 1 { let id = &path.segments[0].ident; if self.all_type_params.contains(id) { self.relevant_type_params.insert(id.clone()); } } for segment in &path.segments { self.visit_path_segment(segment); } } // Everything below is simply traversing the syntax tree. fn visit_type(&mut self, ty: &'ast syn::Type) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Array(ty) => self.visit_type(&ty.elem), syn::Type::BareFn(ty) => { for arg in &ty.inputs { self.visit_type(&arg.ty); } self.visit_return_type(&ty.output); } syn::Type::Group(ty) => self.visit_type(&ty.elem), syn::Type::ImplTrait(ty) => { for bound in &ty.bounds { self.visit_type_param_bound(bound); } } syn::Type::Macro(ty) => self.visit_macro(&ty.mac), syn::Type::Paren(ty) => self.visit_type(&ty.elem), syn::Type::Path(ty) => { if let Some(qself) = &ty.qself { self.visit_type(&qself.ty); } self.visit_path(&ty.path); } syn::Type::Ptr(ty) => self.visit_type(&ty.elem), syn::Type::Reference(ty) => self.visit_type(&ty.elem), syn::Type::Slice(ty) => self.visit_type(&ty.elem), syn::Type::TraitObject(ty) => { for bound in &ty.bounds { self.visit_type_param_bound(bound); } } syn::Type::Tuple(ty) => { for elem in &ty.elems { self.visit_type(elem); } } syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {} _ => {} } } fn visit_path_segment(&mut self, segment: &'ast syn::PathSegment) { self.visit_path_arguments(&segment.arguments); } fn visit_path_arguments(&mut self, arguments: &'ast syn::PathArguments) { match arguments { syn::PathArguments::None => {} syn::PathArguments::AngleBracketed(arguments) => { for arg in &arguments.args { match arg { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::GenericArgument::Type(arg) => self.visit_type(arg), syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty), syn::GenericArgument::Lifetime(_) | syn::GenericArgument::Const(_) | syn::GenericArgument::AssocConst(_) | syn::GenericArgument::Constraint(_) => {} _ => {} } } } syn::PathArguments::Parenthesized(arguments) => { for argument in &arguments.inputs { self.visit_type(argument); } self.visit_return_type(&arguments.output); } } } fn visit_return_type(&mut self, return_type: &'ast syn::ReturnType) { match return_type { syn::ReturnType::Default => {} syn::ReturnType::Type(_, output) => self.visit_type(output), } } fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) { 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(_) => {} _ => {} } } // Type parameter should not be considered used by a macro path. // // struct TypeMacro { // mac: T!(), // marker: PhantomData, // } fn visit_macro(&mut self, _mac: &'ast syn::Macro) {} } let all_type_params = generics .type_params() .map(|param| param.ident.clone()) .collect(); let mut visitor = FindTyParams { all_type_params, relevant_type_params: HashSet::new(), associated_type_usage: Vec::new(), }; match &cont.data { Data::Enum(variants) => { for variant in variants { let relevant_fields = variant .fields .iter() .filter(|field| filter(&field.attrs, Some(&variant.attrs))); for field in relevant_fields { visitor.visit_field(field.original); } } } Data::Struct(_, fields) => { for field in fields.iter().filter(|field| filter(&field.attrs, None)) { visitor.visit_field(field.original); } } } let relevant_type_params = visitor.relevant_type_params; let associated_type_usage = visitor.associated_type_usage; let new_predicates = generics .type_params() .map(|param| param.ident.clone()) .filter(|id| relevant_type_params.contains(id)) .map(|id| syn::TypePath { qself: None, path: id.into(), }) .chain(associated_type_usage.into_iter().cloned()) .map(|bounded_ty| { syn::WherePredicate::Type(syn::PredicateType { lifetimes: None, // the type parameter that is being bounded e.g. T bounded_ty: syn::Type::Path(bounded_ty), colon_token: ::default(), // the bound e.g. Serialize bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None, modifier: syn::TraitBoundModifier::None, lifetimes: None, path: bound.clone(), })] .into_iter() .collect(), }) }); let mut generics = generics.clone(); generics .make_where_clause() .predicates .extend(new_predicates); generics } pub fn with_self_bound( cont: &Container, generics: &syn::Generics, bound: &syn::Path, ) -> syn::Generics { let mut generics = generics.clone(); generics .make_where_clause() .predicates .push(syn::WherePredicate::Type(syn::PredicateType { lifetimes: None, // the type that is being bounded e.g. MyStruct<'a, T> bounded_ty: type_of_item(cont), colon_token: ::default(), // the bound e.g. Default bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None, modifier: syn::TraitBoundModifier::None, lifetimes: None, path: bound.clone(), })] .into_iter() .collect(), })); generics } pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics { let bound = syn::Lifetime::new(lifetime, Span::call_site()); let def = syn::LifetimeParam { attrs: Vec::new(), lifetime: bound.clone(), colon_token: None, bounds: Punctuated::new(), }; let params = Some(syn::GenericParam::Lifetime(def)) .into_iter() .chain(generics.params.iter().cloned().map(|mut param| { match &mut param { syn::GenericParam::Lifetime(param) => { param.bounds.push(bound.clone()); } syn::GenericParam::Type(param) => { param .bounds .push(syn::TypeParamBound::Lifetime(bound.clone())); } syn::GenericParam::Const(_) => {} } param })) .collect(); syn::Generics { params, ..generics.clone() } } fn type_of_item(cont: &Container) -> syn::Type { syn::Type::Path(syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments: vec![syn::PathSegment { ident: cont.ident.clone(), arguments: syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { colon2_token: None, lt_token: ::default(), args: cont .generics .params .iter() .map(|param| match param { syn::GenericParam::Type(param) => { syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { qself: None, path: param.ident.clone().into(), })) } syn::GenericParam::Lifetime(param) => { syn::GenericArgument::Lifetime(param.lifetime.clone()) } syn::GenericParam::Const(_) => { panic!("Serde does not support const generics yet"); } }) .collect(), gt_token: ]>::default(), }, ), }] .into_iter() .collect(), }, }) } serde_derive-1.0.195/src/de.rs000064400000000000000000003262161046102023000142000ustar 00000000000000use crate::fragment::{Expr, Fragment, Match, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; use crate::{bound, dummy, pretend, this}; use proc_macro2::{Literal, Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; use std::collections::BTreeSet; use std::ptr; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{parse_quote, Ident, Index, Member}; pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); let cont = match Container::from_ast(&ctxt, input, Derive::Deserialize) { Some(cont) => cont, None => return Err(ctxt.check().unwrap_err()), }; precondition(&ctxt, &cont); ctxt.check()?; let ident = &cont.ident; let params = Parameters::new(&cont); let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms); let body = Stmts(deserialize_body(&cont, ¶ms)); let delife = params.borrowed.de_lifetime(); let serde = cont.attrs.serde_path(); let impl_block = if let Some(remote) = cont.attrs.remote() { let vis = &input.vis; let used = pretend::pretend_used(&cont, params.is_packed); quote! { impl #de_impl_generics #ident #ty_generics #where_clause { #vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error> where __D: #serde::Deserializer<#delife>, { #used #body } } } } else { let fn_deserialize_in_place = deserialize_in_place_body(&cont, ¶ms); quote! { #[automatically_derived] impl #de_impl_generics #serde::Deserialize<#delife> for #ident #ty_generics #where_clause { fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result where __D: #serde::Deserializer<#delife>, { #body } #fn_deserialize_in_place } } }; Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), impl_block, )) } fn precondition(cx: &Ctxt, cont: &Container) { precondition_sized(cx, cont); precondition_no_de_lifetime(cx, cont); } fn precondition_sized(cx: &Ctxt, cont: &Container) { if let Data::Struct(_, fields) = &cont.data { if let Some(last) = fields.last() { if let syn::Type::Slice(_) = ungroup(last.ty) { cx.error_spanned_by( cont.original, "cannot deserialize a dynamically sized struct", ); } } } } fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) { if let BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) { for param in cont.generics.lifetimes() { if param.lifetime.to_string() == "'de" { cx.error_spanned_by( ¶m.lifetime, "cannot deserialize when there is a lifetime parameter called 'de", ); return; } } } } struct Parameters { /// Name of the type the `derive` is on. local: syn::Ident, /// Path to the type the impl is for. Either a single `Ident` for local /// types (does not include generic parameters) or `some::remote::Path` for /// remote types. this_type: syn::Path, /// Same as `this_type` but using `::` for generic parameters for use in /// expression position. this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, /// Lifetimes borrowed from the deserializer. These will become bounds on /// the `'de` lifetime of the deserializer. borrowed: BorrowedLifetimes, /// At least one field has a serde(getter) attribute, implying that the /// remote type has a private field. has_getter: bool, /// Type has a repr(packed) attribute. is_packed: bool, } impl Parameters { fn new(cont: &Container) -> Self { let local = cont.ident.clone(); let this_type = this::this_type(cont); let this_value = this::this_value(cont); let borrowed = borrowed_lifetimes(cont); let generics = build_generics(cont, &borrowed); let has_getter = cont.data.has_getter(); let is_packed = cont.attrs.is_packed(); Parameters { local, this_type, this_value, generics, borrowed, has_getter, is_packed, } } /// Type name to use in error messages and `&'static str` arguments to /// various Deserializer methods. fn type_name(&self) -> String { self.this_type.segments.last().unwrap().ident.to_string() } } // All the generics in the input, plus a bound `T: Deserialize` for each generic // field type that will be deserialized by us, plus a bound `T: Default` for // each generic field type that will be set to a default value. fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generics { let generics = bound::without_defaults(cont.generics); let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::de_bound); let generics = bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::de_bound); match cont.attrs.de_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => { let generics = match *cont.attrs.default() { attr::Default::Default => bound::with_self_bound( cont, &generics, &parse_quote!(_serde::__private::Default), ), attr::Default::None | attr::Default::Path(_) => generics, }; let delife = borrowed.de_lifetime(); let generics = bound::with_bound( cont, &generics, needs_deserialize_bound, &parse_quote!(_serde::Deserialize<#delife>), ); bound::with_bound( cont, &generics, requires_default, &parse_quote!(_serde::__private::Default), ) } } } // Fields with a `skip_deserializing` or `deserialize_with` attribute, or which // belong to a variant with a `skip_deserializing` or `deserialize_with` // attribute, are not deserialized by us so we do not generate a bound. Fields // with a `bound` attribute specify their own bound so we do not generate one. // All other fields may need a `T: Deserialize` bound where T is the type of the // field. fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { !field.skip_deserializing() && field.deserialize_with().is_none() && field.de_bound().is_none() && variant.map_or(true, |variant| { !variant.skip_deserializing() && variant.deserialize_with().is_none() && variant.de_bound().is_none() }) } // Fields with a `default` attribute (not `default=...`), and fields with a // `skip_deserializing` attribute that do not also have `default=...`. fn requires_default(field: &attr::Field, _variant: Option<&attr::Variant>) -> bool { if let attr::Default::Default = *field.default() { true } else { false } } enum BorrowedLifetimes { Borrowed(BTreeSet), Static, } impl BorrowedLifetimes { fn de_lifetime(&self) -> syn::Lifetime { match *self { BorrowedLifetimes::Borrowed(_) => syn::Lifetime::new("'de", Span::call_site()), BorrowedLifetimes::Static => syn::Lifetime::new("'static", Span::call_site()), } } fn de_lifetime_param(&self) -> Option { match self { BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: bounds.iter().cloned().collect(), }), BorrowedLifetimes::Static => None, } } } // The union of lifetimes borrowed by each field of the container. // // These turn into bounds on the `'de` lifetime of the Deserialize impl. If // lifetimes `'a` and `'b` are borrowed but `'c` is not, the impl is: // // impl<'de: 'a + 'b, 'a, 'b, 'c> Deserialize<'de> for S<'a, 'b, 'c> // // If any borrowed lifetime is `'static`, then `'de: 'static` would be redundant // and we use plain `'static` instead of `'de`. fn borrowed_lifetimes(cont: &Container) -> BorrowedLifetimes { let mut lifetimes = BTreeSet::new(); for field in cont.data.all_fields() { if !field.attrs.skip_deserializing() { lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned()); } } if lifetimes.iter().any(|b| b.to_string() == "'static") { BorrowedLifetimes::Static } else { BorrowedLifetimes::Borrowed(lifetimes) } } fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { if cont.attrs.transparent() { deserialize_transparent(cont, params) } else if let Some(type_from) = cont.attrs.type_from() { deserialize_from(type_from) } else if let Some(type_try_from) = cont.attrs.type_try_from() { deserialize_try_from(type_try_from) } else if let attr::Identifier::No = cont.attrs.identifier() { match &cont.data { Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs), Data::Struct(Style::Struct, fields) => { deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple) } Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), } } else { match &cont.data { Data::Enum(variants) => deserialize_custom_identifier(params, variants, &cont.attrs), Data::Struct(_, _) => unreachable!("checked in serde_derive_internals"), } } } #[cfg(feature = "deserialize_in_place")] fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option { // Only remote derives have getters, and we do not generate // deserialize_in_place for remote derives. assert!(!params.has_getter); if cont.attrs.transparent() || cont.attrs.type_from().is_some() || cont.attrs.type_try_from().is_some() || cont.attrs.identifier().is_some() || cont .data .all_fields() .all(|f| f.attrs.deserialize_with().is_some()) { return None; } let code = match &cont.data { Data::Struct(Style::Struct, fields) => { deserialize_struct_in_place(params, fields, &cont.attrs)? } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { deserialize_tuple_in_place(params, fields, &cont.attrs) } Data::Enum(_) | Data::Struct(Style::Unit, _) => { return None; } }; let delife = params.borrowed.de_lifetime(); let stmts = Stmts(code); let fn_deserialize_in_place = quote_block! { fn deserialize_in_place<__D>(__deserializer: __D, __place: &mut Self) -> _serde::__private::Result<(), __D::Error> where __D: _serde::Deserializer<#delife>, { #stmts } }; Some(Stmts(fn_deserialize_in_place)) } #[cfg(not(feature = "deserialize_in_place"))] fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option { None } fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { let fields = match &cont.data { Data::Struct(_, fields) => fields, Data::Enum(_) => unreachable!(), }; let this_value = ¶ms.this_value; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let path = match transparent_field.attrs.deserialize_with() { Some(path) => quote!(#path), None => { let span = transparent_field.original.span(); quote_spanned!(span=> _serde::Deserialize::deserialize) } }; let assign = fields.iter().map(|field| { let member = &field.member; if ptr::eq(field, transparent_field) { quote!(#member: __transparent) } else { let value = match field.attrs.default() { attr::Default::Default => quote!(_serde::__private::Default::default()), attr::Default::Path(path) => quote!(#path()), attr::Default::None => quote!(_serde::__private::PhantomData), }; quote!(#member: #value) } }); quote_block! { _serde::__private::Result::map( #path(__deserializer), |__transparent| #this_value { #(#assign),* }) } } fn deserialize_from(type_from: &syn::Type) -> Fragment { quote_block! { _serde::__private::Result::map( <#type_from as _serde::Deserialize>::deserialize(__deserializer), _serde::__private::From::from) } } fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment { quote_block! { _serde::__private::Result::and_then( <#type_try_from as _serde::Deserialize>::deserialize(__deserializer), |v| _serde::__private::TryFrom::try_from(v).map_err(_serde::de::Error::custom)) } } fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let type_name = cattrs.name().deserialize_name(); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let expecting = format!("unit struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #[inline] fn visit_unit<__E>(self) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(#this_value) } } _serde::Deserializer::deserialize_unit_struct( __deserializer, #type_name, __Visitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) } } enum TupleForm<'a> { Tuple, /// Contains a variant name ExternallyTagged(&'a syn::Ident), /// Contains a variant name and an intermediate deserializer from which actual /// deserialization will be performed Untagged(&'a syn::Ident, TokenStream), } fn deserialize_tuple( params: &Parameters, fields: &[Field], cattrs: &attr::Container, form: TupleForm, ) -> Fragment { assert!(!cattrs.has_flatten()); let field_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. let construct = if params.has_getter { let local = ¶ms.local; quote!(#local) } else { quote!(#this_value) }; let type_path = match form { TupleForm::Tuple => construct, TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => { quote!(#construct::#variant_ident) } }; let expecting = match form { TupleForm::Tuple => format!("tuple struct {}", params.type_name()), TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => { format!("tuple variant {}::{}", params.type_name(), variant_ident) } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = match form { TupleForm::Tuple if nfields == 1 => { Some(deserialize_newtype_struct(&type_path, params, &fields[0])) } _ => None, }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, false, cattrs, expecting, )); let visitor_expr = quote! { __Visitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, } }; let dispatch = match form { TupleForm::Tuple if nfields == 1 => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr) } } TupleForm::Tuple => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr) } } TupleForm::ExternallyTagged(_) => quote! { _serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr) }, TupleForm::Untagged(_, deserializer) => quote! { _serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr) }, }; let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) }; quote_block! { #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #visit_newtype_struct #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } } #dispatch } } #[cfg(feature = "deserialize_in_place")] fn deserialize_tuple_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { assert!(!cattrs.has_flatten()); let field_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let expecting = format!("tuple struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = if nfields == 1 { // We do not generate deserialize_in_place if every field has a // deserialize_with. assert!(fields[0].attrs.deserialize_with().is_none()); Some(quote! { #[inline] fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result where __E: _serde::Deserializer<#delife>, { _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) } }) } else { None }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visitor_expr = quote! { __Visitor { place: __place, lifetime: _serde::__private::PhantomData, } }; let type_name = cattrs.name().deserialize_name(); let dispatch = if nfields == 1 { quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) }; let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) }; let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); let place_life = place_lifetime(); quote_block! { #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this_type #ty_generics, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #visit_newtype_struct #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } } #dispatch } } fn deserialize_seq( type_path: &TokenStream, params: &Parameters, fields: &[Field], is_struct: bool, cattrs: &attr::Container, expecting: &str, ) -> Fragment { let vars = (0..fields.len()).map(field_i as fn(_) -> _); let deserialized_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let expecting = if deserialized_count == 1 { format!("{} with 1 element", expecting) } else { format!("{} with {} elements", expecting, deserialized_count) }; let expecting = cattrs.expecting().unwrap_or(&expecting); let mut index_in_seq = 0_usize; let let_values = vars.clone().zip(fields).map(|(var, field)| { if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); quote! { let #var = #default; } } else { let visit = match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>); quote!(#func(&mut __seq)?) } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper _serde::__private::Option::map( _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)?, |__wrap| __wrap.value) }) } }; let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting); let assign = quote! { let #var = match #visit { _serde::__private::Some(__value) => __value, _serde::__private::None => #value_if_none, }; }; index_in_seq += 1; assign } }); let mut result = if is_struct { let names = fields.iter().map(|f| &f.member); quote! { #type_path { #( #names: #vars ),* } } } else { quote! { #type_path ( #(#vars),* ) } }; if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: Self::Value = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #let_default #(#let_values)* _serde::__private::Ok(#result) } } #[cfg(feature = "deserialize_in_place")] fn deserialize_seq_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, expecting: &str, ) -> Fragment { let deserialized_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let expecting = if deserialized_count == 1 { format!("{} with 1 element", expecting) } else { format!("{} with {} elements", expecting, deserialized_count) }; let expecting = cattrs.expecting().unwrap_or(&expecting); let mut index_in_seq = 0usize; let write_values = fields.iter().map(|field| { let member = &field.member; if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); quote! { self.place.#member = #default; } } else { let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting); let write = match field.attrs.deserialize_with() { None => { quote! { if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq, _serde::__private::de::InPlaceSeed(&mut self.place.#member))? { #value_if_none; } } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper match _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)? { _serde::__private::Some(__wrap) => { self.place.#member = __wrap.value; } _serde::__private::None => { #value_if_none; } } }) } }; index_in_seq += 1; write } }); let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #let_default #(#write_values)* _serde::__private::Ok(()) } } fn deserialize_newtype_struct( type_path: &TokenStream, params: &Parameters, field: &Field, ) -> TokenStream { let delife = params.borrowed.de_lifetime(); let field_ty = field.ty; 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)? } } Some(path) => { quote! { #path(__e)? } } }; let mut result = quote!(#type_path(__field0)); if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } quote! { #[inline] fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result where __E: _serde::Deserializer<#delife>, { let __field0: #field_ty = #value; _serde::__private::Ok(#result) } } } enum StructForm<'a> { Struct, /// Contains a variant name ExternallyTagged(&'a syn::Ident), /// Contains a variant name and an intermediate deserializer from which actual /// deserialization will be performed InternallyTagged(&'a syn::Ident, TokenStream), /// Contains a variant name and an intermediate deserializer from which actual /// deserialization will be performed Untagged(&'a syn::Ident, TokenStream), } fn deserialize_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, form: StructForm, ) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. let construct = if params.has_getter { let local = ¶ms.local; quote!(#local) } else { quote!(#this_value) }; let type_path = match form { StructForm::Struct => construct, StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident, _) | StructForm::Untagged(variant_ident, _) => quote!(#construct::#variant_ident), }; let expecting = match form { StructForm::Struct => format!("struct {}", params.type_name()), StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident, _) | StructForm::Untagged(variant_ident, _) => { format!("struct variant {}::{}", params.type_name(), variant_ident) } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let field_names_idents: Vec<_> = fields .iter() .enumerate() // Skip fields that shouldn't be deserialized or that were flattened, // so they don't appear in the storage in their literal form .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(i, field)| { ( field.attrs.name().deserialize_name(), field_i(i), field.attrs.aliases(), ) }) .collect(); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. let visit_seq = match form { StructForm::Untagged(..) => None, _ if cattrs.has_flatten() => None, _ => { let mut_seq = if field_names_idents.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, true, cattrs, expecting, )); Some(quote! { #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } }) } }; let visit_map = Stmts(deserialize_map(&type_path, params, fields, cattrs)); let visitor_seed = match form { StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! { impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<#delife>, { _serde::Deserializer::deserialize_map(__deserializer, self) } } }), _ => None, }; let fields_stmt = if cattrs.has_flatten() { None } else { let field_names = field_names_idents .iter() .flat_map(|&(_, _, aliases)| aliases); Some(quote! { #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; }) }; let visitor_expr = quote! { __Visitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, } }; let dispatch = match form { StructForm::Struct if cattrs.has_flatten() => quote! { _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) }, StructForm::Struct => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } } StructForm::ExternallyTagged(_) if cattrs.has_flatten() => quote! { _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) }, StructForm::ExternallyTagged(_) => quote! { _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) }, StructForm::InternallyTagged(_, deserializer) => quote! { _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) }, StructForm::Untagged(_, deserializer) => quote! { _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) }, }; quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #visit_seq #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #visitor_seed #fields_stmt #dispatch } } #[cfg(feature = "deserialize_in_place")] fn deserialize_struct_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Option { // for now we do not support in_place deserialization for structs that // are represented as map. if cattrs.has_flatten() { return None; } let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let field_names_idents: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| { ( field.attrs.name().deserialize_name(), field_i(i), field.attrs.aliases(), ) }) .collect(); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); let mut_seq = if field_names_idents.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 type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); let place_life = place_lifetime(); Some(quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this_type #ty_generics, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { place: __place, lifetime: _serde::__private::PhantomData, }) }) } fn deserialize_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { // The variants have already been checked (in ast.rs) that all untagged variants appear at the end match variants.iter().position(|var| var.attrs.untagged()) { Some(variant_idx) => { let (tagged, untagged) = variants.split_at(variant_idx); let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs)); deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag)) } None => deserialize_homogeneous_enum(params, variants, cattrs), } } fn deserialize_homogeneous_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { match cattrs.tag() { attr::TagType::External => deserialize_externally_tagged_enum(params, variants, cattrs), attr::TagType::Internal { tag } => { deserialize_internally_tagged_enum(params, variants, cattrs, tag) } attr::TagType::Adjacent { tag, content } => { deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content) } attr::TagType::None => deserialize_untagged_enum(params, variants, cattrs), } } fn prepare_enum_variant_enum( variants: &[Variant], cattrs: &attr::Container, ) -> (TokenStream, Stmts) { let mut 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(); let fallthrough = deserialized_variants .position(|(_, variant)| variant.attrs.other()) .map(|other_idx| { let ignore_variant = variant_names_idents[other_idx].1.clone(); quote!(_serde::__private::Ok(__Field::#ignore_variant)) }); let variants_stmt = { let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; } }; let variant_visitor = Stmts(deserialize_generated_identifier( &variant_names_idents, cattrs, true, None, fallthrough, )); (variants_stmt, variant_visitor) } fn deserialize_externally_tagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let type_name = cattrs.name().deserialize_name(); let expecting = format!("enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); // Match arms to extract a variant from a string let variant_arms = variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| { let variant_name = field_i(i); let block = Match(deserialize_externally_tagged_variant( params, variant, cattrs, )); quote! { (__Field::#variant_name, __variant) => #block } }); let all_skipped = variants .iter() .all(|variant| variant.attrs.skip_deserializing()); let match_variant = if all_skipped { // This is an empty enum like `enum Impossible {}` or an enum in which // all variants have `#[serde(skip_deserializing)]`. quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::__private::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data); // _serde::__private::Err(__err) _serde::__private::Result::map( _serde::de::EnumAccess::variant::<__Field>(__data), |(__impossible, _)| match __impossible {}) } } else { quote! { match _serde::de::EnumAccess::variant(__data)? { #(#variant_arms)* } } }; quote_block! { #variant_visitor #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } fn visit_enum<__A>(self, __data: __A) -> _serde::__private::Result where __A: _serde::de::EnumAccess<#delife>, { #match_variant } } #variants_stmt _serde::Deserializer::deserialize_enum( __deserializer, #type_name, VARIANTS, __Visitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) } } fn deserialize_internally_tagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, tag: &str, ) -> Fragment { let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); // Match arms to extract a variant from a string let variant_arms = variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| { let variant_name = field_i(i); let block = Match(deserialize_internally_tagged_variant( params, variant, cattrs, quote!(__deserializer), )); quote! { __Field::#variant_name => #block } }); let expecting = format!("internally tagged enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { #variant_visitor #variants_stmt let (__tag, __content) = _serde::Deserializer::deserialize_any( __deserializer, _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); match __tag { #(#variant_arms)* } } } fn deserialize_adjacently_tagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, tag: &str, content: &str, ) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); let variant_arms: &Vec<_> = &variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| { let variant_index = field_i(i); let block = Match(deserialize_untagged_variant( params, variant, cattrs, quote!(__deserializer), )); quote! { __Field::#variant_index => #block } }) .collect(); let rust_name = params.type_name(); let expecting = format!("adjacently tagged enum {}", rust_name); let expecting = cattrs.expecting().unwrap_or(&expecting); let type_name = cattrs.name().deserialize_name(); let deny_unknown_fields = cattrs.deny_unknown_fields(); // If unknown fields are allowed, we pick the visitor that can step over // those. Otherwise we pick the visitor that fails on unknown keys. let field_visitor_ty = if deny_unknown_fields { quote! { _serde::__private::de::TagOrContentFieldVisitor } } else { quote! { _serde::__private::de::TagContentOtherFieldVisitor } }; let tag_or_content = quote! { #field_visitor_ty { tag: #tag, content: #content, } }; let variant_seed = quote! { _serde::__private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> { enum_name: #rust_name, variants: VARIANTS, fields_enum: _serde::__private::PhantomData } }; let mut missing_content = quote! { _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) }; let mut missing_content_fallthrough = quote!(); let missing_content_arms = variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .filter_map(|(i, variant)| { let variant_index = field_i(i); let variant_ident = &variant.ident; let arm = match variant.style { Style::Unit => quote! { _serde::__private::Ok(#this_value::#variant_ident) }, Style::Newtype if variant.attrs.deserialize_with().is_none() => { let span = variant.original.span(); let func = quote_spanned!(span=> _serde::__private::de::missing_field); quote! { #func(#content).map(#this_value::#variant_ident) } } _ => { missing_content_fallthrough = quote!(_ => #missing_content); return None; } }; Some(quote! { __Field::#variant_index => #arm, }) }) .collect::>(); if !missing_content_arms.is_empty() { missing_content = quote! { match __field { #(#missing_content_arms)* #missing_content_fallthrough } }; } // Advance the map by one key, returning early in case of error. let next_key = quote! { _serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)? }; let variant_from_map = quote! { _serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)? }; // When allowing unknown fields, we want to transparently step through keys // we don't care about until we find `tag`, `content`, or run out of keys. let next_relevant_key = if deny_unknown_fields { next_key } else { quote!({ let mut __rk : _serde::__private::Option<_serde::__private::de::TagOrContentField> = _serde::__private::None; while let _serde::__private::Some(__k) = #next_key { match __k { _serde::__private::de::TagContentOtherField::Other => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; continue; }, _serde::__private::de::TagContentOtherField::Tag => { __rk = _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag); break; } _serde::__private::de::TagContentOtherField::Content => { __rk = _serde::__private::Some(_serde::__private::de::TagOrContentField::Content); break; } } } __rk }) }; // Step through remaining keys, looking for duplicates of previously-seen // keys. When unknown fields are denied, any key that isn't a duplicate will // at this point immediately produce an error. let visit_remaining_keys = quote! { match #next_relevant_key { _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } _serde::__private::None => _serde::__private::Ok(__ret), } }; let finish_content_then_tag = if variant_arms.is_empty() { quote! { match #variant_from_map {} } } else { quote! { let __ret = match #variant_from_map { // Deserialize the buffered content now that we know the variant. #(#variant_arms)* }?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } }; quote_block! { #variant_visitor #variants_stmt #[doc(hidden)] struct __Seed #de_impl_generics #where_clause { field: __Field, marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<#delife>, { match self.field { #(#variant_arms)* } } } #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result where __A: _serde::de::MapAccess<#delife>, { // Visit the first relevant key. match #next_relevant_key { // First key is the tag. _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { // Parse the tag. let __field = #variant_from_map; // Visit the second key. match #next_relevant_key { // Second key is a duplicate of the tag. _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } // Second key is the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { let __ret = _serde::de::MapAccess::next_value_seed(&mut __map, __Seed { field: __field, marker: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, })?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } // There is no second key; might be okay if the we have a unit variant. _serde::__private::None => #missing_content } } // First key is the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { // Buffer up the content. let __content = _serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map)?; // Visit the second key. match #next_relevant_key { // Second key is the tag. _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { let __deserializer = _serde::__private::de::ContentDeserializer::<__A::Error>::new(__content); #finish_content_then_tag } // Second key is a duplicate of the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } // There is no second key. _serde::__private::None => { _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } // There is no first key. _serde::__private::None => { _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } fn visit_seq<__A>(self, mut __seq: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { // Visit the first element - the tag. match _serde::de::SeqAccess::next_element(&mut __seq)? { _serde::__private::Some(__field) => { // Visit the second element - the content. match _serde::de::SeqAccess::next_element_seed( &mut __seq, __Seed { field: __field, marker: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, }, )? { _serde::__private::Some(__ret) => _serde::__private::Ok(__ret), // There is no second element. _serde::__private::None => { _serde::__private::Err(_serde::de::Error::invalid_length(1, &self)) } } } // There is no first element. _serde::__private::None => { _serde::__private::Err(_serde::de::Error::invalid_length(0, &self)) } } } } #[doc(hidden)] const FIELDS: &'static [&'static str] = &[#tag, #content]; _serde::Deserializer::deserialize_struct( __deserializer, #type_name, FIELDS, __Visitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) } } fn deserialize_untagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let first_attempt = None; deserialize_untagged_enum_after(params, variants, cattrs, first_attempt) } fn deserialize_untagged_enum_after( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, first_attempt: Option, ) -> Fragment { let attempts = variants .iter() .filter(|variant| !variant.attrs.skip_deserializing()) .map(|variant| { Expr(deserialize_untagged_variant( params, variant, cattrs, quote!(__deserializer), )) }); // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields // processed before an error, and use the error that happened after the // largest number of fields. I'm not sure I like that. Maybe it would be // better to save all the errors and combine them into one message that // explains why none of the variants matched. let fallthrough_msg = format!( "data did not match any variant of untagged enum {}", params.type_name() ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); // Ignore any error associated with non-untagged deserialization so that we // can fall through to the untagged variants. This may be infallible so we // need to provide the error type. let first_attempt = first_attempt.map(|expr| { quote! { if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() { return _serde::__private::Ok(__ok); } } }); quote_block! { let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); #first_attempt #( if let _serde::__private::Ok(__ok) = #attempts { return _serde::__private::Ok(__ok); } )* _serde::__private::Err(_serde::de::Error::custom(#fallthrough_msg)) } } fn deserialize_externally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.deserialize_with() { let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path); return quote_block! { #wrapper _serde::__private::Result::map( _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn) }; } let variant_ident = &variant.ident; match variant.style { Style::Unit => { let this_value = ¶ms.this_value; quote_block! { _serde::de::VariantAccess::unit_variant(__variant)?; _serde::__private::Ok(#this_value::#variant_ident) } } Style::Newtype => deserialize_externally_tagged_newtype_variant( variant_ident, params, &variant.fields[0], cattrs, ), Style::Tuple => deserialize_tuple( params, &variant.fields, cattrs, TupleForm::ExternallyTagged(variant_ident), ), Style::Struct => deserialize_struct( params, &variant.fields, cattrs, StructForm::ExternallyTagged(variant_ident), ), } } // Generates significant part of the visit_seq and visit_map bodies of visitors // for the variants of internally tagged enum. fn deserialize_internally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, deserializer: TokenStream, ) -> Fragment { if variant.attrs.deserialize_with().is_some() { return deserialize_untagged_variant(params, variant, cattrs, deserializer); } let variant_ident = &variant.ident; match effective_style(variant) { Style::Unit => { let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_block! { _serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?; _serde::__private::Ok(#this_value::#variant_ident #default) } } Style::Newtype => deserialize_untagged_newtype_variant( variant_ident, params, &variant.fields[0], &deserializer, ), Style::Struct => deserialize_struct( params, &variant.fields, cattrs, StructForm::InternallyTagged(variant_ident, deserializer), ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } } fn deserialize_untagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, deserializer: TokenStream, ) -> Fragment { if let Some(path) = variant.attrs.deserialize_with() { let unwrap_fn = unwrap_to_variant_closure(params, variant, false); return quote_block! { _serde::__private::Result::map(#path(#deserializer), #unwrap_fn) }; } let variant_ident = &variant.ident; match effective_style(variant) { Style::Unit => { let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_expr! { match _serde::Deserializer::deserialize_any( #deserializer, _serde::__private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) ) { _serde::__private::Ok(()) => _serde::__private::Ok(#this_value::#variant_ident #default), _serde::__private::Err(__err) => _serde::__private::Err(__err), } } } Style::Newtype => deserialize_untagged_newtype_variant( variant_ident, params, &variant.fields[0], &deserializer, ), Style::Tuple => deserialize_tuple( params, &variant.fields, cattrs, TupleForm::Untagged(variant_ident, deserializer), ), Style::Struct => deserialize_struct( params, &variant.fields, cattrs, StructForm::Untagged(variant_ident, deserializer), ), } } fn deserialize_externally_tagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment { let this_value = ¶ms.this_value; if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); return quote_block! { _serde::de::VariantAccess::unit_variant(__variant)?; _serde::__private::Ok(#this_value::#variant_ident(#default)) }; } match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>); quote_expr! { _serde::__private::Result::map(#func(__variant), #this_value::#variant_ident) } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote_block! { #wrapper _serde::__private::Result::map( _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), |__wrapper| #this_value::#variant_ident(__wrapper.value)) } } } } fn deserialize_untagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, deserializer: &TokenStream, ) -> Fragment { let this_value = ¶ms.this_value; let field_ty = field.ty; match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote_expr! { _serde::__private::Result::map(#func(#deserializer), #this_value::#variant_ident) } } Some(path) => { quote_block! { let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer); _serde::__private::Result::map(__value, #this_value::#variant_ident) } } } } fn deserialize_generated_identifier( fields: &[(&str, Ident, &BTreeSet)], cattrs: &attr::Container, is_variant: bool, ignore_variant: Option, fallthrough: Option, ) -> Fragment { let this_value = quote!(__Field); let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); let visitor_impl = Stmts(deserialize_identifier( &this_value, fields, is_variant, fallthrough, None, !is_variant && cattrs.has_flatten(), None, )); let lifetime = if !is_variant && cattrs.has_flatten() { Some(quote!(<'de>)) } else { None }; quote_block! { #[allow(non_camel_case_types)] #[doc(hidden)] enum __Field #lifetime { #(#field_idents,)* #ignore_variant } #[doc(hidden)] struct __FieldVisitor; impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { type Value = __Field #lifetime; #visitor_impl } impl<'de> _serde::Deserialize<'de> for __Field #lifetime { #[inline] fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<'de>, { _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) } } } } /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( fields: &[(&str, Ident, &BTreeSet)], cattrs: &attr::Container, ) -> Stmts { let (ignore_variant, fallthrough) = if cattrs.has_flatten() { let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),); let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value))); (Some(ignore_variant), Some(fallthrough)) } else if cattrs.deny_unknown_fields() { (None, None) } else { let ignore_variant = quote!(__ignore,); let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore)); (Some(ignore_variant), Some(fallthrough)) }; Stmts(deserialize_generated_identifier( fields, cattrs, false, ignore_variant, fallthrough, )) } // Generates `Deserialize::deserialize` body for an enum with // `serde(field_identifier)` or `serde(variant_identifier)` attribute. fn deserialize_custom_identifier( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let is_variant = match cattrs.identifier() { attr::Identifier::Variant => true, attr::Identifier::Field => false, attr::Identifier::No => unreachable!(), }; let this_type = params.this_type.to_token_stream(); let this_value = params.this_value.to_token_stream(); let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() { let last_ident = &last.ident; if last.attrs.other() { // Process `serde(other)` attribute. It would always be found on the // last variant (checked in `check_identifier`), so all preceding // are ordinary variants. let ordinary = &variants[..variants.len() - 1]; let fallthrough = quote!(_serde::__private::Ok(#this_value::#last_ident)); (ordinary, Some(fallthrough), None) } else if let Style::Newtype = last.style { let ordinary = &variants[..variants.len() - 1]; let fallthrough = |value| { quote! { _serde::__private::Result::map( _serde::Deserialize::deserialize( _serde::__private::de::IdentifierDeserializer::from(#value) ), #this_value::#last_ident) } }; ( ordinary, Some(fallthrough(quote!(__value))), Some(fallthrough(quote!(_serde::__private::de::Borrowed( __value )))), ) } else { (variants, None, None) } } else { (variants, None, None) }; let names_idents: Vec<_> = ordinary .iter() .map(|variant| { ( variant.attrs.name().deserialize_name(), variant.ident.clone(), variant.attrs.aliases(), ) }) .collect(); let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases); let names_const = if fallthrough.is_some() { None } else if is_variant { let variants = quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#names),* ]; }; Some(variants) } else { let fields = quote! { #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#names),* ]; }; Some(fields) }; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let visitor_impl = Stmts(deserialize_identifier( &this_value, &names_idents, is_variant, fallthrough, fallthrough_borrowed, false, cattrs.expecting(), )); quote_block! { #names_const #[doc(hidden)] struct __FieldVisitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; #visitor_impl } let __visitor = __FieldVisitor { marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }; _serde::Deserializer::deserialize_identifier(__deserializer, __visitor) } } fn deserialize_identifier( this_value: &TokenStream, fields: &[(&str, Ident, &BTreeSet)], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { let str_mapping = fields.iter().map(|(_, ident, aliases)| { // `aliases` also contains a main name quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); let bytes_mapping = fields.iter().map(|(_, ident, aliases)| { // `aliases` also contains a main name let aliases = aliases .iter() .map(|alias| Literal::byte_string(alias.as_bytes())); quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); let expecting = expecting.unwrap_or(if is_variant { "variant identifier" } else { "field identifier" }); let bytes_to_str = if fallthrough.is_some() || collect_other_fields { None } else { Some(quote! { let __value = &_serde::__private::from_utf8_lossy(__value); }) }; let ( value_as_str_content, value_as_borrowed_str_content, value_as_bytes_content, value_as_borrowed_bytes_content, ) = if collect_other_fields { ( Some(quote! { let __value = _serde::__private::de::Content::String(_serde::__private::ToString::to_string(__value)); }), Some(quote! { let __value = _serde::__private::de::Content::Str(__value); }), Some(quote! { let __value = _serde::__private::de::Content::ByteBuf(__value.to_vec()); }), Some(quote! { let __value = _serde::__private::de::Content::Bytes(__value); }), ) } else { (None, None, None, None) }; let fallthrough_arm_tokens; let fallthrough_arm = if let Some(fallthrough) = &fallthrough { fallthrough } else if is_variant { fallthrough_arm_tokens = quote! { _serde::__private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS)) }; &fallthrough_arm_tokens } else { fallthrough_arm_tokens = quote! { _serde::__private::Err(_serde::de::Error::unknown_field(__value, FIELDS)) }; &fallthrough_arm_tokens }; let visit_other = if collect_other_fields { quote! { fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::Bool(__value))) } fn visit_i8<__E>(self, __value: i8) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::I8(__value))) } fn visit_i16<__E>(self, __value: i16) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::I16(__value))) } fn visit_i32<__E>(self, __value: i32) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::I32(__value))) } fn visit_i64<__E>(self, __value: i64) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::I64(__value))) } fn visit_u8<__E>(self, __value: u8) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::U8(__value))) } fn visit_u16<__E>(self, __value: u16) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::U16(__value))) } fn visit_u32<__E>(self, __value: u32) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::U32(__value))) } fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::U64(__value))) } fn visit_f32<__E>(self, __value: f32) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::F32(__value))) } fn visit_f64<__E>(self, __value: f64) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::F64(__value))) } fn visit_char<__E>(self, __value: char) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::Char(__value))) } fn visit_unit<__E>(self) -> _serde::__private::Result where __E: _serde::de::Error, { _serde::__private::Ok(__Field::__other(_serde::__private::de::Content::Unit)) } } } else { let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| { let i = i as u64; quote!(#i => _serde::__private::Ok(#this_value::#ident)) }); let u64_fallthrough_arm_tokens; let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { fallthrough } else { let index_expecting = if is_variant { "variant" } else { "field" }; let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len()); u64_fallthrough_arm_tokens = quote! { _serde::__private::Err(_serde::de::Error::invalid_value( _serde::de::Unexpected::Unsigned(__value), &#fallthrough_msg, )) }; &u64_fallthrough_arm_tokens }; quote! { fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #(#u64_mapping,)* _ => #u64_fallthrough_arm, } } } }; let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields { let str_mapping = str_mapping.clone(); let bytes_mapping = bytes_mapping.clone(); let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm); Some(quote! { fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #(#str_mapping,)* _ => { #value_as_borrowed_str_content #fallthrough_borrowed_arm } } } fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #(#bytes_mapping,)* _ => { #bytes_to_str #value_as_borrowed_bytes_content #fallthrough_borrowed_arm } } } }) } else { None }; quote_block! { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) } #visit_other fn visit_str<__E>(self, __value: &str) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #(#str_mapping,)* _ => { #value_as_str_content #fallthrough_arm } } } fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #(#bytes_mapping,)* _ => { #bytes_to_str #value_as_bytes_content #fallthrough_arm } } } #visit_borrowed } } fn deserialize_map( struct_path: &TokenStream, params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // Declare each field that will be deserialized. let let_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let field_ty = field.ty; quote! { let mut #name: _serde::__private::Option<#field_ty> = _serde::__private::None; } }); // Collect contents for flatten fields into a buffer let let_collect = if cattrs.has_flatten() { Some(quote! { let mut __collect = _serde::__private::Vec::<_serde::__private::Option<( _serde::__private::de::Content, _serde::__private::de::Content )>>::new(); }) } else { None }; // Match arms to extract a value for a field. let value_arms = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let visit = match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>); quote! { #func(&mut __map)? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::__private::Ok(__wrapper) => __wrapper.value, _serde::__private::Err(__err) => { return _serde::__private::Err(__err); } } }) } }; quote! { __Field::#name => { if _serde::__private::Option::is_some(&#name) { return _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #name = _serde::__private::Some(#visit); } } }); // Visit ignored values to consume them let ignored_arm = if cattrs.has_flatten() { Some(quote! { __Field::__other(__name) => { __collect.push(_serde::__private::Some(( __name, _serde::de::MapAccess::next_value(&mut __map)?))); } }) } else if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::__private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms)* #ignored_arm } } } }; let extract_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let missing_expr = Match(expr_is_missing(field, cattrs)); quote! { let #name = match #name { _serde::__private::Some(#name) => #name, _serde::__private::None => #missing_expr }; } }); let extract_collected = fields_names .iter() .filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing()) .map(|(field, name)| { let field_ty = field.ty; let func = match field.attrs.deserialize_with() { None => { let span = field.original.span(); quote_spanned!(span=> _serde::de::Deserialize::deserialize) } Some(path) => quote!(#path), }; quote! { let #name: #field_ty = #func( _serde::__private::de::FlatMapDeserializer( &mut __collect, _serde::__private::PhantomData))?; } }); let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() { Some(quote! { if let _serde::__private::Some(_serde::__private::Some((__key, _))) = __collect.into_iter().filter(_serde::__private::Option::is_some).next() { if let _serde::__private::Some(__key) = __key.as_str() { return _serde::__private::Err( _serde::de::Error::custom(format_args!("unknown field `{}`", &__key))); } else { return _serde::__private::Err( _serde::de::Error::custom(format_args!("unexpected map key"))); } } }) } else { None }; let result = fields_names.iter().map(|(field, name)| { let member = &field.member; if field.attrs.skip_deserializing() { let value = Expr(expr_is_missing(field, cattrs)); quote!(#member: #value) } else { quote!(#member: #name) } }); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: Self::Value = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; let mut result = quote!(#struct_path { #(#result),* }); if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } quote_block! { #(#let_values)* #let_collect #match_keys #let_default #(#extract_values)* #(#extract_collected)* #collected_deny_unknown_fields _serde::__private::Ok(#result) } } #[cfg(feature = "deserialize_in_place")] fn deserialize_map_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { assert!(!cattrs.has_flatten()); // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // For deserialize_in_place, declare booleans for each field that will be // deserialized. let let_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(_, name)| { quote! { let mut #name: bool = false; } }); // Match arms to extract a value for a field. let value_arms_from = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let member = &field.member; let visit = match field.attrs.deserialize_with() { None => { quote! { _serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::InPlaceSeed(&mut self.place.#member))? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::__private::Ok(__wrapper) => __wrapper.value, _serde::__private::Err(__err) => { return _serde::__private::Err(__err); } }; }) } }; quote! { __Field::#name => { if #name { return _serde::__private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #visit; #name = true; } } }); // Visit ignored values to consume them let ignored_arm = if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::__private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms_from)* #ignored_arm } } } }; let check_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let missing_expr = expr_is_missing(field, cattrs); // If missing_expr unconditionally returns an error, don't try // to assign its value to self.place. if field.attrs.default().is_none() && cattrs.default().is_none() && field.attrs.deserialize_with().is_some() { let missing_expr = Stmts(missing_expr); quote! { if !#name { #missing_expr; } } } else { let member = &field.member; let missing_expr = Expr(missing_expr); quote! { if !#name { self.place.#member = #missing_expr; }; } } }); let this_type = ¶ms.this_type; let (_, _, ty_generics, _) = split_with_de_lifetime(params); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #(#let_flags)* #match_keys #let_default #(#check_flags)* _serde::__private::Ok(()) } } fn field_i(i: usize) -> Ident { Ident::new(&format!("__field{}", i), Span::call_site()) } /// This function wraps the expression in `#[serde(deserialize_with = "...")]` /// in a trait to prevent it from accessing the internal `Deserialize` state. fn wrap_deserialize_with( params: &Parameters, value_ty: &TokenStream, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream) { let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let wrapper = quote! { #[doc(hidden)] struct __DeserializeWith #de_impl_generics #where_clause { value: #value_ty, phantom: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause { fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<#delife>, { _serde::__private::Ok(__DeserializeWith { value: #deserialize_with(__deserializer)?, phantom: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, }) } } }; let wrapper_ty = quote!(__DeserializeWith #de_ty_generics); (wrapper, wrapper_ty) } fn wrap_deserialize_field_with( params: &Parameters, field_ty: &syn::Type, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream) { wrap_deserialize_with(params, "e!(#field_ty), deserialize_with) } fn wrap_deserialize_variant_with( params: &Parameters, variant: &Variant, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream, TokenStream) { let field_tys = variant.fields.iter().map(|field| field.ty); let (wrapper, wrapper_ty) = wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with); let unwrap_fn = unwrap_to_variant_closure(params, variant, true); (wrapper, wrapper_ty, unwrap_fn) } // Generates closure that converts single input parameter to the final value. fn unwrap_to_variant_closure( params: &Parameters, variant: &Variant, with_wrapper: bool, ) -> TokenStream { let this_value = ¶ms.this_value; let variant_ident = &variant.ident; let (arg, wrapper) = if with_wrapper { (quote! { __wrap }, quote! { __wrap.value }) } else { let field_tys = variant.fields.iter().map(|field| field.ty); (quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap }) }; let field_access = (0..variant.fields.len()).map(|n| { Member::Unnamed(Index { index: n as u32, span: Span::call_site(), }) }); match variant.style { Style::Struct if variant.fields.len() == 1 => { let member = &variant.fields[0].member; quote! { |#arg| #this_value::#variant_ident { #member: #wrapper } } } Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote! { |#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* } } } Style::Tuple => quote! { |#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*) }, Style::Newtype => quote! { |#arg| #this_value::#variant_ident(#wrapper) }, Style::Unit => quote! { |#arg| #this_value::#variant_ident }, } } fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { match field.attrs.default() { attr::Default::Default => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::__private::Default::default); return quote_expr!(#func()); } attr::Default::Path(path) => { return quote_expr!(#path()); } attr::Default::None => { /* below */ } } match *cattrs.default() { attr::Default::Default | attr::Default::Path(_) => { let member = &field.member; return quote_expr!(__default.#member); } attr::Default::None => { /* below */ } } let name = field.attrs.name().deserialize_name(); match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::__private::de::missing_field); quote_expr! { #func(#name)? } } Some(_) => { quote_expr! { return _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#name)) } } } } fn expr_is_missing_seq( assign_to: Option, index: usize, field: &Field, cattrs: &attr::Container, expecting: &str, ) -> TokenStream { match field.attrs.default() { attr::Default::Default => { let span = field.original.span(); return quote_spanned!(span=> #assign_to _serde::__private::Default::default()); } attr::Default::Path(path) => { return quote_spanned!(path.span()=> #assign_to #path()); } attr::Default::None => { /* below */ } } match *cattrs.default() { attr::Default::Default | attr::Default::Path(_) => { let member = &field.member; quote!(#assign_to __default.#member) } attr::Default::None => quote!( return _serde::__private::Err(_serde::de::Error::invalid_length(#index, &#expecting)) ), } } fn effective_style(variant: &Variant) -> Style { match variant.style { Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit, other => other, } } struct DeImplGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceImplGenerics<'a>(&'a Parameters); impl<'a> ToTokens for DeImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) .collect(); } let (impl_generics, _, _) = generics.split_for_impl(); impl_generics.to_tokens(tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> ToTokens for InPlaceImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let place_lifetime = place_lifetime(); let mut generics = self.0.generics.clone(); // Add lifetime for `&'place mut Self, and `'a: 'place` for param in &mut generics.params { match param { syn::GenericParam::Lifetime(param) => { param.bounds.push(place_lifetime.lifetime.clone()); } syn::GenericParam::Type(param) => { param.bounds.push(syn::TypeParamBound::Lifetime( place_lifetime.lifetime.clone(), )); } syn::GenericParam::Const(_) => {} } } generics.params = Some(syn::GenericParam::Lifetime(place_lifetime)) .into_iter() .chain(generics.params) .collect(); if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) .collect(); } let (impl_generics, _, _) = generics.split_for_impl(); impl_generics.to_tokens(tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> DeImplGenerics<'a> { fn in_place(self) -> InPlaceImplGenerics<'a> { InPlaceImplGenerics(self.0) } } struct DeTypeGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceTypeGenerics<'a>(&'a Parameters); fn de_type_generics_to_tokens( mut generics: syn::Generics, borrowed: &BorrowedLifetimes, tokens: &mut TokenStream, ) { if borrowed.de_lifetime_param().is_some() { let def = syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: Punctuated::new(), }; // Prepend 'de lifetime to list of generics generics.params = Some(syn::GenericParam::Lifetime(def)) .into_iter() .chain(generics.params) .collect(); } let (_, ty_generics, _) = generics.split_for_impl(); ty_generics.to_tokens(tokens); } impl<'a> ToTokens for DeTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { de_type_generics_to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> ToTokens for InPlaceTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); generics.params = Some(syn::GenericParam::Lifetime(place_lifetime())) .into_iter() .chain(generics.params) .collect(); de_type_generics_to_tokens(generics, &self.0.borrowed, tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> DeTypeGenerics<'a> { fn in_place(self) -> InPlaceTypeGenerics<'a> { InPlaceTypeGenerics(self.0) } } #[cfg(feature = "deserialize_in_place")] fn place_lifetime() -> syn::LifetimeParam { syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'place", Span::call_site()), colon_token: None, bounds: Punctuated::new(), } } fn split_with_de_lifetime( params: &Parameters, ) -> ( DeImplGenerics, DeTypeGenerics, syn::TypeGenerics, Option<&syn::WhereClause>, ) { let de_impl_generics = DeImplGenerics(params); let de_ty_generics = DeTypeGenerics(params); let (_, ty_generics, where_clause) = params.generics.split_for_impl(); (de_impl_generics, de_ty_generics, ty_generics, where_clause) } serde_derive-1.0.195/src/dummy.rs000064400000000000000000000011431046102023000147300ustar 00000000000000use proc_macro2::TokenStream; use quote::quote; pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream { let use_serde = match serde_path { Some(path) => quote! { use #path as _serde; }, None => quote! { #[allow(unused_extern_crates, clippy::useless_attribute)] extern crate serde as _serde; }, }; quote! { #[doc(hidden)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const _: () = { #use_serde #code }; } } serde_derive-1.0.195/src/fragment.rs000064400000000000000000000041041046102023000154000ustar 00000000000000use proc_macro2::TokenStream; use quote::ToTokens; use syn::{token, Token}; pub enum Fragment { /// Tokens that can be used as an expression. Expr(TokenStream), /// Tokens that can be used inside a block. The surrounding curly braces are /// not part of these tokens. Block(TokenStream), } macro_rules! quote_expr { ($($tt:tt)*) => { $crate::fragment::Fragment::Expr(quote!($($tt)*)) } } macro_rules! quote_block { ($($tt:tt)*) => { $crate::fragment::Fragment::Block(quote!($($tt)*)) } } /// Interpolate a fragment in place of an expression. This involves surrounding /// Block fragments in curly braces. pub struct Expr(pub Fragment); impl ToTokens for Expr { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => expr.to_tokens(out), Fragment::Block(block) => { token::Brace::default().surround(out, |out| block.to_tokens(out)); } } } } /// Interpolate a fragment as the statements of a block. pub struct Stmts(pub Fragment); impl ToTokens for Stmts { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => expr.to_tokens(out), Fragment::Block(block) => block.to_tokens(out), } } } /// Interpolate a fragment as the value part of a `match` expression. This /// involves putting a comma after expressions and curly braces around blocks. pub struct Match(pub Fragment); impl ToTokens for Match { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => { expr.to_tokens(out); ::default().to_tokens(out); } Fragment::Block(block) => { token::Brace::default().surround(out, |out| block.to_tokens(out)); } } } } impl AsRef for Fragment { fn as_ref(&self) -> &TokenStream { match self { Fragment::Expr(expr) => expr, Fragment::Block(block) => block, } } } serde_derive-1.0.195/src/internals/ast.rs000064400000000000000000000147111046102023000163700ustar 00000000000000//! A Serde ast, parsed from the Syn ast and ready to generate Rust code. use crate::internals::{attr, check, Ctxt, Derive}; use syn::punctuated::Punctuated; use syn::Token; /// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`, /// parsed into an internal representation. pub struct Container<'a> { /// The struct or enum name (without generics). pub ident: syn::Ident, /// Attributes on the structure, parsed for Serde. pub attrs: attr::Container, /// The contents of the struct or enum. pub data: Data<'a>, /// Any generics on the struct or enum. pub generics: &'a syn::Generics, /// Original input. pub original: &'a syn::DeriveInput, } /// The fields of a struct or enum. /// /// Analogous to `syn::Data`. pub enum Data<'a> { Enum(Vec>), Struct(Style, Vec>), } /// A variant of an enum. pub struct Variant<'a> { pub ident: syn::Ident, pub attrs: attr::Variant, pub style: Style, pub fields: Vec>, pub original: &'a syn::Variant, } /// A field of a struct. pub struct Field<'a> { pub member: syn::Member, pub attrs: attr::Field, pub ty: &'a syn::Type, pub original: &'a syn::Field, } #[derive(Copy, Clone)] pub enum Style { /// Named fields. Struct, /// Many unnamed fields. Tuple, /// One unnamed field. Newtype, /// No fields. Unit, } impl<'a> Container<'a> { /// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`. pub fn from_ast( cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive, ) -> Option> { let mut attrs = attr::Container::from_ast(cx, item); let mut data = match &item.data { syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())), syn::Data::Struct(data) => { let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default()); Data::Struct(style, fields) } syn::Data::Union(_) => { cx.error_spanned_by(item, "Serde does not support derive for unions"); return None; } }; let mut has_flatten = false; match &mut data { Data::Enum(variants) => { for variant in variants { variant.attrs.rename_by_rules(attrs.rename_all_rules()); for field in &mut variant.fields { if field.attrs.flatten() { has_flatten = true; } field.attrs.rename_by_rules( variant .attrs .rename_all_rules() .or(attrs.rename_all_fields_rules()), ); } } } Data::Struct(_, fields) => { for field in fields { if field.attrs.flatten() { has_flatten = true; } field.attrs.rename_by_rules(attrs.rename_all_rules()); } } } if has_flatten { attrs.mark_has_flatten(); } let mut item = Container { ident: item.ident.clone(), attrs, data, generics: &item.generics, original: item, }; check::check(cx, &mut item, derive); Some(item) } } impl<'a> Data<'a> { pub fn all_fields(&'a self) -> Box> + 'a> { match self { Data::Enum(variants) => { Box::new(variants.iter().flat_map(|variant| variant.fields.iter())) } Data::Struct(_, fields) => Box::new(fields.iter()), } } pub fn has_getter(&self) -> bool { self.all_fields().any(|f| f.attrs.getter().is_some()) } } fn enum_from_ast<'a>( cx: &Ctxt, variants: &'a Punctuated, container_default: &attr::Default, ) -> Vec> { let variants: Vec = variants .iter() .map(|variant| { let attrs = attr::Variant::from_ast(cx, variant); let (style, fields) = struct_from_ast(cx, &variant.fields, Some(&attrs), container_default); Variant { ident: variant.ident.clone(), attrs, style, fields, original: variant, } }) .collect(); let index_of_last_tagged_variant = variants .iter() .rposition(|variant| !variant.attrs.untagged()); if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant { for variant in &variants[..index_of_last_tagged_variant] { if variant.attrs.untagged() { cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum"); } } } variants } fn struct_from_ast<'a>( cx: &Ctxt, fields: &'a syn::Fields, attrs: Option<&attr::Variant>, container_default: &attr::Default, ) -> (Style, Vec>) { match fields { syn::Fields::Named(fields) => ( Style::Struct, fields_from_ast(cx, &fields.named, attrs, container_default), ), syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => ( Style::Newtype, fields_from_ast(cx, &fields.unnamed, attrs, container_default), ), syn::Fields::Unnamed(fields) => ( Style::Tuple, fields_from_ast(cx, &fields.unnamed, attrs, container_default), ), syn::Fields::Unit => (Style::Unit, Vec::new()), } } fn fields_from_ast<'a>( cx: &Ctxt, fields: &'a Punctuated, attrs: Option<&attr::Variant>, container_default: &attr::Default, ) -> Vec> { fields .iter() .enumerate() .map(|(i, field)| Field { member: match &field.ident { Some(ident) => syn::Member::Named(ident.clone()), None => syn::Member::Unnamed(i.into()), }, attrs: attr::Field::from_ast(cx, i, field, attrs, container_default), ty: &field.ty, original: field, }) .collect() } serde_derive-1.0.195/src/internals/attr.rs000064400000000000000000002066061046102023000165610ustar 00000000000000use crate::internals::symbol::*; use crate::internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::borrow::Cow; use std::collections::BTreeSet; use std::iter::FromIterator; use syn::meta::ParseNestedMeta; use syn::parse::ParseStream; use syn::punctuated::Punctuated; use syn::{parse_quote, token, Ident, Lifetime, Token}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and // `attr::Field::from_ast`. Each returns an instance of the corresponding // struct. Note that none of them return a Result. Unrecognized, malformed, or // duplicated attributes result in a span_err but otherwise are ignored. The // user will see errors simultaneously for all bad attributes in the crate // rather than just the first. pub use crate::internals::case::RenameRule; struct Attr<'c, T> { cx: &'c Ctxt, name: Symbol, tokens: TokenStream, value: Option, } impl<'c, T> Attr<'c, T> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { Attr { cx, name, tokens: TokenStream::new(), value: None, } } fn set(&mut self, obj: A, value: T) { let tokens = obj.into_token_stream(); if self.value.is_some() { let msg = format!("duplicate serde attribute `{}`", self.name); self.cx.error_spanned_by(tokens, msg); } else { self.tokens = tokens; self.value = Some(value); } } fn set_opt(&mut self, obj: A, value: Option) { if let Some(value) = value { self.set(obj, value); } } fn set_if_none(&mut self, value: T) { if self.value.is_none() { self.value = Some(value); } } fn get(self) -> Option { self.value } fn get_with_tokens(self) -> Option<(TokenStream, T)> { match self.value { Some(v) => Some((self.tokens, v)), None => None, } } } struct BoolAttr<'c>(Attr<'c, ()>); impl<'c> BoolAttr<'c> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { BoolAttr(Attr::none(cx, name)) } fn set_true(&mut self, obj: A) { self.0.set(obj, ()); } fn get(&self) -> bool { self.0.value.is_some() } } struct VecAttr<'c, T> { cx: &'c Ctxt, name: Symbol, first_dup_tokens: TokenStream, values: Vec, } impl<'c, T> VecAttr<'c, T> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { VecAttr { cx, name, first_dup_tokens: TokenStream::new(), values: Vec::new(), } } fn insert(&mut self, obj: A, value: T) { if self.values.len() == 1 { self.first_dup_tokens = obj.into_token_stream(); } self.values.push(value); } fn at_most_one(mut self) -> Option { if self.values.len() > 1 { let dup_token = self.first_dup_tokens; let msg = format!("duplicate serde attribute `{}`", self.name); self.cx.error_spanned_by(dup_token, msg); None } else { self.values.pop() } } fn get(self) -> Vec { self.values } } pub struct Name { serialize: String, serialize_renamed: bool, deserialize: String, deserialize_renamed: bool, deserialize_aliases: BTreeSet, } 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, de_name: Attr, de_aliases: Option>, ) -> 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 { &self.deserialize_aliases } } #[derive(Copy, Clone)] pub struct RenameAllRules { serialize: RenameRule, deserialize: RenameRule, } impl RenameAllRules { /// Returns a new `RenameAllRules` with the individual rules of `self` and /// `other_rules` joined by `RenameRules::or`. pub fn or(self, other_rules: Self) -> Self { Self { serialize: self.serialize.or(other_rules.serialize), deserialize: self.deserialize.or(other_rules.deserialize), } } } /// Represents struct or enum attribute information. pub struct Container { name: Name, transparent: bool, deny_unknown_fields: bool, default: Default, rename_all_rules: RenameAllRules, rename_all_fields_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, tag: TagType, type_from: Option, type_try_from: Option, type_into: Option, remote: Option, identifier: Identifier, has_flatten: bool, serde_path: Option, is_packed: bool, /// Error message generated when type can't be deserialized expecting: Option, non_exhaustive: bool, } /// Styles of representing an enum. pub enum TagType { /// The default. /// /// ```json /// {"variant1": {"key1": "value1", "key2": "value2"}} /// ``` External, /// `#[serde(tag = "type")]` /// /// ```json /// {"type": "variant1", "key1": "value1", "key2": "value2"} /// ``` Internal { tag: String }, /// `#[serde(tag = "t", content = "c")]` /// /// ```json /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}} /// ``` Adjacent { tag: String, content: String }, /// `#[serde(untagged)]` /// /// ```json /// {"key1": "value1", "key2": "value2"} /// ``` None, } /// Whether this enum represents the fields of a struct or the variants of an /// enum. #[derive(Copy, Clone)] pub enum Identifier { /// It does not. No, /// This enum represents the fields of a struct. All of the variants must be /// unit variants, except possibly one which is annotated with /// `#[serde(other)]` and is a newtype variant. Field, /// This enum represents the variants of an enum. All of the variants must /// be unit variants. Variant, } impl Identifier { #[cfg(feature = "deserialize_in_place")] pub fn is_some(self) -> bool { match self { Identifier::No => false, Identifier::Field | Identifier::Variant => true, } } } impl Container { /// Extract out the `#[serde(...)]` attributes from an item. pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut transparent = BoolAttr::none(cx, TRANSPARENT); let mut deny_unknown_fields = BoolAttr::none(cx, DENY_UNKNOWN_FIELDS); let mut default = Attr::none(cx, DEFAULT); let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS); let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut untagged = BoolAttr::none(cx, UNTAGGED); let mut internal_tag = Attr::none(cx, TAG); let mut content = Attr::none(cx, CONTENT); let mut type_from = Attr::none(cx, FROM); let mut type_try_from = Attr::none(cx, TRY_FROM); let mut type_into = Attr::none(cx, INTO); let mut remote = Attr::none(cx, REMOTE); let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER); let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER); let mut serde_path = Attr::none(cx, CRATE); let mut expecting = Attr::none(cx, EXPECTING); let mut non_exhaustive = false; for attr in &item.attrs { if attr.path() != SERDE { non_exhaustive |= matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE); continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[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)); } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } else if meta.path == RENAME_ALL_FIELDS { // #[serde(rename_all_fields = "foo")] // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?; match item.data { syn::Data::Enum(_) => { if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => { rename_all_fields_ser_rule.set(&meta.path, rename_rule); } Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => { rename_all_fields_de_rule.set(&meta.path, rename_rule); } Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } syn::Data::Struct(_) => { let msg = "#[serde(rename_all_fields)] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(rename_all_fields)] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } else if meta.path == TRANSPARENT { // #[serde(transparent)] transparent.set_true(meta.path); } else if meta.path == DENY_UNKNOWN_FIELDS { // #[serde(deny_unknown_fields)] deny_unknown_fields.set_true(meta.path); } else if meta.path == DEFAULT { if meta.input.peek(Token![=]) { // #[serde(default = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { default.set(&meta.path, Default::Path(path)); } syn::Fields::Unit => { let msg = "#[serde(default = \"...\")] can only be used on structs that have fields"; cx.syn_error(meta.error(msg)); } }, syn::Data::Enum(_) => { let msg = "#[serde(default = \"...\")] can only be used on structs"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(default = \"...\")] can only be used on structs"; cx.syn_error(meta.error(msg)); } } } } else { // #[serde(default)] match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { default.set(meta.path, Default::Default); } syn::Fields::Unit => { let msg = "#[serde(default)] can only be used on structs that have fields"; cx.error_spanned_by(fields, msg); } }, syn::Data::Enum(_) => { let msg = "#[serde(default)] can only be used on structs"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(default)] can only be used on structs"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == UNTAGGED { // #[serde(untagged)] match item.data { syn::Data::Enum(_) => { untagged.set_true(&meta.path); } syn::Data::Struct(_) => { let msg = "#[serde(untagged)] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(untagged)] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } else if meta.path == TAG { // #[serde(tag = "type")] if let Some(s) = get_lit_str(cx, TAG, &meta)? { match &item.data { syn::Data::Enum(_) => { internal_tag.set(&meta.path, s.value()); } syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) => { internal_tag.set(&meta.path, s.value()); } syn::Fields::Unnamed(_) | syn::Fields::Unit => { let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; cx.syn_error(meta.error(msg)); } }, syn::Data::Union(_) => { let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == CONTENT { // #[serde(content = "c")] if let Some(s) = get_lit_str(cx, CONTENT, &meta)? { match &item.data { syn::Data::Enum(_) => { content.set(&meta.path, s.value()); } syn::Data::Struct(_) => { let msg = "#[serde(content = \"...\")] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(content = \"...\")] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == FROM { // #[serde(from = "Type")] if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? { type_from.set_opt(&meta.path, Some(from_ty)); } } else if meta.path == TRY_FROM { // #[serde(try_from = "Type")] if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? { type_try_from.set_opt(&meta.path, Some(try_from_ty)); } } else if meta.path == INTO { // #[serde(into = "Type")] if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? { type_into.set_opt(&meta.path, Some(into_ty)); } } else if meta.path == REMOTE { // #[serde(remote = "...")] if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? { if is_primitive_path(&path, "Self") { remote.set(&meta.path, item.ident.clone().into()); } else { remote.set(&meta.path, path); } } } else if meta.path == FIELD_IDENTIFIER { // #[serde(field_identifier)] field_identifier.set_true(&meta.path); } else if meta.path == VARIANT_IDENTIFIER { // #[serde(variant_identifier)] variant_identifier.set_true(&meta.path); } else if meta.path == CRATE { // #[serde(crate = "foo")] if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? { serde_path.set(&meta.path, path); } } else if meta.path == EXPECTING { // #[serde(expecting = "a message")] if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? { expecting.set(&meta.path, s.value()); } } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde container attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } let mut is_packed = false; for attr in &item.attrs { if attr.path() == REPR { let _ = attr.parse_args_with(|input: ParseStream| { while let Some(token) = input.parse()? { if let TokenTree::Ident(ident) = token { is_packed |= ident == "packed"; } } Ok(()) }); } } Container { name: Name::from_attrs(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), rename_all_rules: RenameAllRules { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), }, rename_all_fields_rules: RenameAllRules { serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None), }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), tag: decide_tag(cx, item, untagged, internal_tag, content), type_from: type_from.get(), type_try_from: type_try_from.get(), type_into: type_into.get(), remote: remote.get(), identifier: decide_identifier(cx, item, field_identifier, variant_identifier), has_flatten: false, serde_path: serde_path.get(), is_packed, expecting: expecting.get(), non_exhaustive, } } pub fn name(&self) -> &Name { &self.name } pub fn rename_all_rules(&self) -> RenameAllRules { self.rename_all_rules } pub fn rename_all_fields_rules(&self) -> RenameAllRules { self.rename_all_fields_rules } pub fn transparent(&self) -> bool { self.transparent } pub fn deny_unknown_fields(&self) -> bool { self.deny_unknown_fields } pub fn default(&self) -> &Default { &self.default } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn tag(&self) -> &TagType { &self.tag } pub fn type_from(&self) -> Option<&syn::Type> { self.type_from.as_ref() } pub fn type_try_from(&self) -> Option<&syn::Type> { self.type_try_from.as_ref() } pub fn type_into(&self) -> Option<&syn::Type> { self.type_into.as_ref() } pub fn remote(&self) -> Option<&syn::Path> { self.remote.as_ref() } pub fn is_packed(&self) -> bool { self.is_packed } pub fn identifier(&self) -> Identifier { self.identifier } pub fn has_flatten(&self) -> bool { self.has_flatten } pub fn mark_has_flatten(&mut self) { self.has_flatten = true; } pub fn custom_serde_path(&self) -> Option<&syn::Path> { self.serde_path.as_ref() } pub fn serde_path(&self) -> Cow { self.custom_serde_path() .map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed) } /// Error message generated when type can't be deserialized. /// If `None`, default message will be used pub fn expecting(&self) -> Option<&str> { self.expecting.as_ref().map(String::as_ref) } pub fn non_exhaustive(&self) -> bool { self.non_exhaustive } } fn decide_tag( cx: &Ctxt, item: &syn::DeriveInput, untagged: BoolAttr, internal_tag: Attr, content: Attr, ) -> TagType { match ( untagged.0.get_with_tokens(), internal_tag.get_with_tokens(), content.get_with_tokens(), ) { (None, None, None) => TagType::External, (Some(_), None, None) => TagType::None, (None, Some((_, tag)), None) => { // Check that there are no tuple variants. if let syn::Data::Enum(data) = &item.data { for variant in &data.variants { match &variant.fields { syn::Fields::Named(_) | syn::Fields::Unit => {} syn::Fields::Unnamed(fields) => { if fields.unnamed.len() != 1 { let msg = "#[serde(tag = \"...\")] cannot be used with tuple variants"; cx.error_spanned_by(variant, msg); break; } } } } } TagType::Internal { tag } } (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => { let msg = "enum cannot be both untagged and internally tagged"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(tag_tokens, msg); TagType::External // doesn't matter, will error } (None, None, Some((content_tokens, _))) => { let msg = "#[serde(tag = \"...\", content = \"...\")] must be used together"; cx.error_spanned_by(content_tokens, msg); TagType::External } (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => { let msg = "untagged enum cannot have #[serde(content = \"...\")]"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(content_tokens, msg); TagType::External } (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => { let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(tag_tokens, msg); cx.error_spanned_by(content_tokens, msg); TagType::External } } } fn decide_identifier( cx: &Ctxt, item: &syn::DeriveInput, field_identifier: BoolAttr, variant_identifier: BoolAttr, ) -> Identifier { match ( &item.data, field_identifier.0.get_with_tokens(), variant_identifier.0.get_with_tokens(), ) { (_, None, None) => Identifier::No, (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => { let msg = "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set"; cx.error_spanned_by(field_identifier_tokens, msg); cx.error_spanned_by(variant_identifier_tokens, msg); Identifier::No } (syn::Data::Enum(_), Some(_), None) => Identifier::Field, (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant, (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => { let msg = "#[serde(field_identifier)] can only be used on an enum"; cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { let msg = "#[serde(field_identifier)] can only be used on an enum"; cx.error_spanned_by(union_token, msg); Identifier::No } (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { let msg = "#[serde(variant_identifier)] can only be used on an enum"; cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { let msg = "#[serde(variant_identifier)] can only be used on an enum"; cx.error_spanned_by(union_token, msg); Identifier::No } } } /// Represents variant attribute information pub struct Variant { name: Name, rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, skip_deserializing: bool, skip_serializing: bool, other: bool, serialize_with: Option, deserialize_with: Option, borrow: Option, untagged: bool, } struct BorrowAttribute { path: syn::Path, lifetimes: Option>, } impl Variant { pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut de_aliases = VecAttr::none(cx, RENAME); let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut other = BoolAttr::none(cx, OTHER); let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut borrow = Attr::none(cx, BORROW); let mut untagged = BoolAttr::none(cx, UNTAGGED); for attr in &variant.attrs { if attr.path() != SERDE { continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[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)); for de_value in de { de_name.set_if_none(de_value.value()); de_aliases.insert(&meta.path, de_value.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()); } } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } else if meta.path == SKIP { // #[serde(skip)] skip_serializing.set_true(&meta.path); skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_DESERIALIZING { // #[serde(skip_deserializing)] skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_SERIALIZING { // #[serde(skip_serializing)] skip_serializing.set_true(&meta.path); } else if meta.path == OTHER { // #[serde(other)] other.set_true(&meta.path); } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == WITH { // #[serde(with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).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()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == SERIALIZE_WITH { // #[serde(serialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { serialize_with.set(&meta.path, path); } } else if meta.path == DESERIALIZE_WITH { // #[serde(deserialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { deserialize_with.set(&meta.path, path); } } else if meta.path == BORROW { let borrow_attribute = if meta.input.peek(Token![=]) { // #[serde(borrow = "'a + 'b")] let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; BorrowAttribute { path: meta.path.clone(), lifetimes: Some(lifetimes), } } else { // #[serde(borrow)] BorrowAttribute { path: meta.path.clone(), lifetimes: None, } }; match &variant.fields { syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { borrow.set(&meta.path, borrow_attribute); } _ => { let msg = "#[serde(borrow)] may only be used on newtype variants"; cx.error_spanned_by(variant, msg); } } } else if meta.path == UNTAGGED { untagged.set_true(&meta.path); } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde variant attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } Variant { name: Name::from_attrs(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), }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), skip_deserializing: skip_deserializing.get(), skip_serializing: skip_serializing.get(), other: other.get(), serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), borrow: borrow.get(), untagged: untagged.get(), } } pub fn name(&self) -> &Name { &self.name } pub fn aliases(&self) -> &BTreeSet { 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); } if !self.name.deserialize_renamed { self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize); } self.name .deserialize_aliases .insert(self.name.deserialize.clone()); } pub fn rename_all_rules(&self) -> RenameAllRules { self.rename_all_rules } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } pub fn skip_serializing(&self) -> bool { self.skip_serializing } pub fn other(&self) -> bool { self.other } pub fn serialize_with(&self) -> Option<&syn::ExprPath> { self.serialize_with.as_ref() } pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } pub fn untagged(&self) -> bool { self.untagged } } /// Represents field attribute information pub struct Field { name: Name, skip_serializing: bool, skip_deserializing: bool, skip_serializing_if: Option, default: Default, serialize_with: Option, deserialize_with: Option, ser_bound: Option>, de_bound: Option>, borrowed_lifetimes: BTreeSet, getter: Option, flatten: bool, transparent: bool, } /// Represents the default to use for a field when deserializing. pub enum Default { /// Field must always be specified because it does not have a default. None, /// The default is given by `std::default::Default::default()`. Default, /// The default is given by this function. Path(syn::ExprPath), } impl Default { pub fn is_none(&self) -> bool { match self { Default::None => true, Default::Default | Default::Path(_) => false, } } } impl Field { /// Extract out the `#[serde(...)]` attributes from a struct field. pub fn from_ast( cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>, container_default: &Default, ) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut de_aliases = VecAttr::none(cx, RENAME); let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); let mut skip_serializing_if = Attr::none(cx, SKIP_SERIALIZING_IF); let mut default = Attr::none(cx, DEFAULT); let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut borrowed_lifetimes = Attr::none(cx, BORROW); let mut getter = Attr::none(cx, GETTER); let mut flatten = BoolAttr::none(cx, FLATTEN); let ident = match &field.ident { Some(ident) => unraw(ident), None => index.to_string(), }; if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { if let Some(lifetimes) = &borrow_attribute.lifetimes { for lifetime in lifetimes { if !borrowable.contains(lifetime) { let msg = format!("field `{}` does not have lifetime {}", ident, lifetime); cx.error_spanned_by(field, msg); } } borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone()); } else { borrowed_lifetimes.set(&borrow_attribute.path, borrowable); } } } for attr in &field.attrs { if attr.path() != SERDE { continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[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)); for de_value in de { de_name.set_if_none(de_value.value()); de_aliases.insert(&meta.path, de_value.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()); } } else if meta.path == DEFAULT { if meta.input.peek(Token![=]) { // #[serde(default = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { default.set(&meta.path, Default::Path(path)); } } else { // #[serde(default)] default.set(&meta.path, Default::Default); } } else if meta.path == SKIP_SERIALIZING { // #[serde(skip_serializing)] skip_serializing.set_true(&meta.path); } else if meta.path == SKIP_DESERIALIZING { // #[serde(skip_deserializing)] skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP { // #[serde(skip)] skip_serializing.set_true(&meta.path); skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_SERIALIZING_IF { // #[serde(skip_serializing_if = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? { skip_serializing_if.set(&meta.path, path); } } else if meta.path == SERIALIZE_WITH { // #[serde(serialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { serialize_with.set(&meta.path, path); } } else if meta.path == DESERIALIZE_WITH { // #[serde(deserialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { deserialize_with.set(&meta.path, path); } } else if meta.path == WITH { // #[serde(with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).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()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == BORROW { if meta.input.peek(Token![=]) { // #[serde(borrow = "'a + 'b")] let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { for lifetime in &lifetimes { if !borrowable.contains(lifetime) { let msg = format!( "field `{}` does not have lifetime {}", ident, lifetime, ); cx.error_spanned_by(field, msg); } } borrowed_lifetimes.set(&meta.path, lifetimes); } } else { // #[serde(borrow)] if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { borrowed_lifetimes.set(&meta.path, borrowable); } } } else if meta.path == GETTER { // #[serde(getter = "...")] if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? { getter.set(&meta.path, path); } } else if meta.path == FLATTEN { // #[serde(flatten)] flatten.set_true(&meta.path); } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde field attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } // Is skip_deserializing, initialize the field to Default::default() unless a // different default is specified by `#[serde(default = "...")]` on // ourselves or our container (e.g. the struct we are in). if let Default::None = *container_default { if skip_deserializing.0.value.is_some() { default.set_if_none(Default::Default); } } let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default(); if !borrowed_lifetimes.is_empty() { // Cow and Cow<[u8]> never borrow by default: // // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> // // A #[serde(borrow)] attribute enables borrowing that corresponds // roughly to these impls: // // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str> // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> if is_cow(&field.ty, is_str) { let mut path = syn::Path { leading_colon: None, segments: Punctuated::new(), }; let span = Span::call_site(); path.segments.push(Ident::new("_serde", span).into()); path.segments.push(Ident::new("__private", span).into()); path.segments.push(Ident::new("de", span).into()); path.segments .push(Ident::new("borrow_cow_str", span).into()); let expr = syn::ExprPath { attrs: Vec::new(), qself: None, path, }; deserialize_with.set_if_none(expr); } else if is_cow(&field.ty, is_slice_u8) { let mut path = syn::Path { leading_colon: None, segments: Punctuated::new(), }; let span = Span::call_site(); path.segments.push(Ident::new("_serde", span).into()); path.segments.push(Ident::new("__private", span).into()); path.segments.push(Ident::new("de", span).into()); path.segments .push(Ident::new("borrow_cow_bytes", span).into()); let expr = syn::ExprPath { attrs: Vec::new(), qself: None, path, }; deserialize_with.set_if_none(expr); } } else if is_implicitly_borrowed(&field.ty) { // Types &str and &[u8] are always implicitly borrowed. No need for // a #[serde(borrow)]. collect_lifetimes(&field.ty, &mut borrowed_lifetimes); } Field { name: Name::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(), default: default.get().unwrap_or(Default::None), serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), ser_bound: ser_bound.get(), de_bound: de_bound.get(), borrowed_lifetimes, getter: getter.get(), flatten: flatten.get(), transparent: false, } } pub fn name(&self) -> &Name { &self.name } pub fn aliases(&self) -> &BTreeSet { 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); } if !self.name.deserialize_renamed { self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize); } self.name .deserialize_aliases .insert(self.name.deserialize.clone()); } pub fn skip_serializing(&self) -> bool { self.skip_serializing } pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> { self.skip_serializing_if.as_ref() } pub fn default(&self) -> &Default { &self.default } pub fn serialize_with(&self) -> Option<&syn::ExprPath> { self.serialize_with.as_ref() } pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn borrowed_lifetimes(&self) -> &BTreeSet { &self.borrowed_lifetimes } pub fn getter(&self) -> Option<&syn::ExprPath> { self.getter.as_ref() } pub fn flatten(&self) -> bool { self.flatten } pub fn transparent(&self) -> bool { self.transparent } pub fn mark_transparent(&mut self) { self.transparent = true; } } type SerAndDe = (Option, Option); fn get_ser_and_de<'c, T, F, R>( cx: &'c Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, f: F, ) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)> where T: Clone, F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result, R: Into>, { let mut ser_meta = VecAttr::none(cx, attr_name); let mut de_meta = VecAttr::none(cx, attr_name); let lookahead = meta.input.lookahead1(); if lookahead.peek(Token![=]) { if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() { ser_meta.insert(&meta.path, both.clone()); de_meta.insert(&meta.path, both); } } else if lookahead.peek(token::Paren) { meta.parse_nested_meta(|meta| { if meta.path == SERIALIZE { if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() { ser_meta.insert(&meta.path, v); } } else if meta.path == DESERIALIZE { if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() { de_meta.insert(&meta.path, v); } } else { return Err(meta.error(format_args!( "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", attr_name, ))); } Ok(()) })?; } else { return Err(lookahead.error()); } Ok((ser_meta, de_meta)) } fn get_renames( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let (ser, de) = get_ser_and_de(cx, attr_name, meta, get_lit_str2)?; Ok((ser.at_most_one(), de.at_most_one())) } fn get_multiple_renames( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result<(Option, Vec)> { let (ser, de) = get_ser_and_de(cx, RENAME, meta, get_lit_str2)?; Ok((ser.at_most_one(), de.get())) } fn get_where_predicates( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result>> { let (ser, de) = get_ser_and_de(cx, BOUND, meta, parse_lit_into_where)?; Ok((ser.at_most_one(), de.at_most_one())) } fn get_lit_str( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { get_lit_str2(cx, attr_name, attr_name, meta) } fn get_lit_str2( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let expr: syn::Expr = meta.value()?.parse()?; let mut value = &expr; while let syn::Expr::Group(e) = value { value = &e.expr; } if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit), .. }) = value { let suffix = lit.suffix(); if !suffix.is_empty() { cx.error_spanned_by( lit, format!("unexpected suffix `{}` on string literal", suffix), ); } Ok(Some(lit.clone())) } else { cx.error_spanned_by( expr, format!( "expected serde {} attribute to be a string: `{} = \"...\"`", attr_name, meta_item_name ), ); Ok(None) } } fn parse_lit_into_path( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let string = match get_lit_str(cx, attr_name, meta)? { Some(string) => string, None => return Ok(None), }; Ok(match string.parse() { Ok(path) => Some(path), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse path: {:?}", string.value()), ); None } }) } fn parse_lit_into_expr_path( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let string = match get_lit_str(cx, attr_name, meta)? { Some(string) => string, None => return Ok(None), }; Ok(match string.parse() { Ok(expr) => Some(expr), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse path: {:?}", string.value()), ); None } }) } fn parse_lit_into_where( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let string = match get_lit_str2(cx, attr_name, meta_item_name, meta)? { Some(string) => string, None => return Ok(Vec::new()), }; Ok( match string.parse_with(Punctuated::::parse_terminated) { Ok(predicates) => Vec::from_iter(predicates), Err(err) => { cx.error_spanned_by(string, err); Vec::new() } }, ) } fn parse_lit_into_ty( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let string = match get_lit_str(cx, attr_name, meta)? { Some(string) => string, None => return Ok(None), }; Ok(match string.parse() { Ok(ty) => Some(ty), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse type: {} = {:?}", attr_name, string.value()), ); None } }) } // Parses a string literal like "'a + 'b + 'c" containing a nonempty list of // lifetimes separated by `+`. fn parse_lit_into_lifetimes( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result> { let string = match get_lit_str(cx, BORROW, meta)? { Some(string) => string, None => return Ok(BTreeSet::new()), }; if let Ok(lifetimes) = string.parse_with(|input: ParseStream| { let mut set = BTreeSet::new(); while !input.is_empty() { let lifetime: Lifetime = input.parse()?; if !set.insert(lifetime.clone()) { cx.error_spanned_by( &string, format!("duplicate borrowed lifetime `{}`", lifetime), ); } if input.is_empty() { break; } input.parse::()?; } Ok(set) }) { if lifetimes.is_empty() { cx.error_spanned_by(string, "at least one lifetime must be borrowed"); } return Ok(lifetimes); } cx.error_spanned_by( &string, format!("failed to parse borrowed lifetimes: {:?}", string.value()), ); Ok(BTreeSet::new()) } fn is_implicitly_borrowed(ty: &syn::Type) -> bool { is_implicitly_borrowed_reference(ty) || is_option(ty, is_implicitly_borrowed_reference) } fn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool { is_reference(ty, is_str) || is_reference(ty, is_slice_u8) } // Whether the type looks like it might be `std::borrow::Cow` where elem="T". // This can have false negatives and false positives. // // False negative: // // use std::borrow::Cow as Pig; // // #[derive(Deserialize)] // struct S<'a> { // #[serde(borrow)] // pig: Pig<'a, str>, // } // // False positive: // // type str = [i16]; // // #[derive(Deserialize)] // struct S<'a> { // #[serde(borrow)] // cow: Cow<'a, str>, // } fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { let path = match ungroup(ty) { syn::Type::Path(ty) => &ty.path, _ => { return false; } }; let seg = match path.segments.last() { Some(seg) => seg, None => { return false; } }; let args = match &seg.arguments { syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, _ => { return false; } }; seg.ident == "Cow" && args.len() == 2 && match (&args[0], &args[1]) { (syn::GenericArgument::Lifetime(_), syn::GenericArgument::Type(arg)) => elem(arg), _ => false, } } fn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { let path = match ungroup(ty) { syn::Type::Path(ty) => &ty.path, _ => { return false; } }; let seg = match path.segments.last() { Some(seg) => seg, None => { return false; } }; let args = match &seg.arguments { syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, _ => { return false; } }; seg.ident == "Option" && args.len() == 1 && match &args[0] { syn::GenericArgument::Type(arg) => elem(arg), _ => false, } } // Whether the type looks like it might be `&T` where elem="T". This can have // false negatives and false positives. // // False negative: // // type Yarn = str; // // #[derive(Deserialize)] // struct S<'a> { // r: &'a Yarn, // } // // False positive: // // type str = [i16]; // // #[derive(Deserialize)] // struct S<'a> { // r: &'a str, // } fn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { match ungroup(ty) { syn::Type::Reference(ty) => ty.mutability.is_none() && elem(&ty.elem), _ => false, } } fn is_str(ty: &syn::Type) -> bool { is_primitive_type(ty, "str") } fn is_slice_u8(ty: &syn::Type) -> bool { match ungroup(ty) { syn::Type::Slice(ty) => is_primitive_type(&ty.elem, "u8"), _ => false, } } fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool { match ungroup(ty) { syn::Type::Path(ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive), _ => false, } } fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == primitive && path.segments[0].arguments.is_empty() } // All lifetimes that this type could borrow from a Deserializer. // // For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand // a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer. // // This is used when there is an explicit or implicit `#[serde(borrow)]` // attribute on the field so there must be at least one borrowable lifetime. fn borrowable_lifetimes( cx: &Ctxt, name: &str, field: &syn::Field, ) -> Result, ()> { let mut lifetimes = BTreeSet::new(); collect_lifetimes(&field.ty, &mut lifetimes); if lifetimes.is_empty() { let msg = format!("field `{}` has no lifetimes to borrow", name); cx.error_spanned_by(field, msg); Err(()) } else { Ok(lifetimes) } } fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Slice(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Array(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Ptr(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Reference(ty) => { out.extend(ty.lifetime.iter().cloned()); collect_lifetimes(&ty.elem, out); } syn::Type::Tuple(ty) => { for elem in &ty.elems { collect_lifetimes(elem, out); } } syn::Type::Path(ty) => { if let Some(qself) = &ty.qself { collect_lifetimes(&qself.ty, out); } for seg in &ty.path.segments { if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments { for arg in &bracketed.args { match arg { syn::GenericArgument::Lifetime(lifetime) => { out.insert(lifetime.clone()); } syn::GenericArgument::Type(ty) => { collect_lifetimes(ty, out); } syn::GenericArgument::AssocType(binding) => { collect_lifetimes(&binding.ty, out); } syn::GenericArgument::Const(_) | syn::GenericArgument::AssocConst(_) | syn::GenericArgument::Constraint(_) | _ => {} } } } } } syn::Type::Paren(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Group(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Macro(ty) => { collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out); } syn::Type::BareFn(_) | syn::Type::Never(_) | syn::Type::TraitObject(_) | syn::Type::ImplTrait(_) | syn::Type::Infer(_) | syn::Type::Verbatim(_) => {} _ => {} } } fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet) { let mut iter = tokens.into_iter(); while let Some(tt) = iter.next() { match &tt { TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { if let Some(TokenTree::Ident(ident)) = iter.next() { out.insert(syn::Lifetime { apostrophe: op.span(), ident, }); } } TokenTree::Group(group) => { let tokens = group.stream(); collect_lifetimes_from_tokens(tokens, out); } _ => {} } } } serde_derive-1.0.195/src/internals/case.rs000064400000000000000000000157211046102023000165160ustar 00000000000000//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the //! case of the source (e.g. `my-field`, `MY_FIELD`). use self::RenameRule::*; use std::fmt::{self, Debug, Display}; /// The different possible ways to change case of fields in a struct, or variants in an enum. #[derive(Copy, Clone, PartialEq)] pub enum RenameRule { /// Don't apply a default rename rule. None, /// Rename direct children to "lowercase" style. LowerCase, /// Rename direct children to "UPPERCASE" style. UpperCase, /// Rename direct children to "PascalCase" style, as typically used for /// enum variants. PascalCase, /// Rename direct children to "camelCase" style. CamelCase, /// Rename direct children to "snake_case" style, as commonly used for /// fields. SnakeCase, /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly /// used for constants. ScreamingSnakeCase, /// Rename direct children to "kebab-case" style. KebabCase, /// Rename direct children to "SCREAMING-KEBAB-CASE" style. ScreamingKebabCase, } static RENAME_RULES: &[(&str, RenameRule)] = &[ ("lowercase", LowerCase), ("UPPERCASE", UpperCase), ("PascalCase", PascalCase), ("camelCase", CamelCase), ("snake_case", SnakeCase), ("SCREAMING_SNAKE_CASE", ScreamingSnakeCase), ("kebab-case", KebabCase), ("SCREAMING-KEBAB-CASE", ScreamingKebabCase), ]; impl RenameRule { pub fn from_str(rename_all_str: &str) -> Result { for (name, rule) in RENAME_RULES { if rename_all_str == *name { return Ok(*rule); } } Err(ParseError { unknown: rename_all_str, }) } /// Apply a renaming rule to an enum variant, returning the version expected in the source. pub fn apply_to_variant(self, variant: &str) -> String { match self { None | PascalCase => variant.to_owned(), LowerCase => variant.to_ascii_lowercase(), UpperCase => variant.to_ascii_uppercase(), CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], SnakeCase => { let mut snake = String::new(); for (i, ch) in variant.char_indices() { if i > 0 && ch.is_uppercase() { snake.push('_'); } snake.push(ch.to_ascii_lowercase()); } snake } ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(), KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"), ScreamingKebabCase => ScreamingSnakeCase .apply_to_variant(variant) .replace('_', "-"), } } /// Apply a renaming rule to a struct field, returning the version expected in the source. pub fn apply_to_field(self, field: &str) -> String { match self { None | LowerCase | SnakeCase => field.to_owned(), UpperCase => field.to_ascii_uppercase(), PascalCase => { let mut pascal = String::new(); let mut capitalize = true; for ch in field.chars() { if ch == '_' { capitalize = true; } else if capitalize { pascal.push(ch.to_ascii_uppercase()); capitalize = false; } else { pascal.push(ch); } } pascal } CamelCase => { let pascal = PascalCase.apply_to_field(field); pascal[..1].to_ascii_lowercase() + &pascal[1..] } ScreamingSnakeCase => field.to_ascii_uppercase(), KebabCase => field.replace('_', "-"), ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"), } } /// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise. pub fn or(self, rule_b: Self) -> Self { match self { None => rule_b, _ => self, } } } pub struct ParseError<'a> { unknown: &'a str, } impl<'a> Display for ParseError<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("unknown rename rule `rename_all = ")?; Debug::fmt(self.unknown, f)?; f.write_str("`, expected one of ")?; for (i, (name, _rule)) in RENAME_RULES.iter().enumerate() { if i > 0 { f.write_str(", ")?; } Debug::fmt(name, f)?; } Ok(()) } } #[test] fn rename_variants() { for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[ ( "Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME", ), ( "VeryTasty", "verytasty", "VERYTASTY", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY", ), ("A", "a", "A", "a", "a", "A", "a", "A"), ("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"), ] { assert_eq!(None.apply_to_variant(original), original); assert_eq!(LowerCase.apply_to_variant(original), lower); assert_eq!(UpperCase.apply_to_variant(original), upper); assert_eq!(PascalCase.apply_to_variant(original), original); assert_eq!(CamelCase.apply_to_variant(original), camel); assert_eq!(SnakeCase.apply_to_variant(original), snake); assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming); assert_eq!(KebabCase.apply_to_variant(original), kebab); assert_eq!( ScreamingKebabCase.apply_to_variant(original), screaming_kebab ); } } #[test] fn rename_fields() { for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[ ( "outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME", ), ( "very_tasty", "VERY_TASTY", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY", ), ("a", "A", "A", "a", "A", "a", "A"), ("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"), ] { assert_eq!(None.apply_to_field(original), original); assert_eq!(UpperCase.apply_to_field(original), upper); assert_eq!(PascalCase.apply_to_field(original), pascal); assert_eq!(CamelCase.apply_to_field(original), camel); assert_eq!(SnakeCase.apply_to_field(original), original); assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming); assert_eq!(KebabCase.apply_to_field(original), kebab); assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab); } } serde_derive-1.0.195/src/internals/check.rs000064400000000000000000000405341046102023000166600ustar 00000000000000use crate::internals::ast::{Container, Data, Field, Style}; use crate::internals::attr::{Default, Identifier, TagType}; use crate::internals::{ungroup, Ctxt, Derive}; use syn::{Member, Type}; // Cross-cutting checks that require looking at more than a single attrs object. // Simpler checks should happen when parsing and building the attrs. pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { check_default_on_tuple(cx, cont); check_remote_generic(cx, cont); check_getter(cx, cont); check_flatten(cx, cont); check_identifier(cx, cont); check_variant_skip_attrs(cx, cont); check_internal_tag_field_name_conflict(cx, cont); check_adjacent_tag_conflict(cx, cont); check_transparent(cx, cont, derive); check_from_and_try_from(cx, cont); } // If some field of a tuple struct is marked #[serde(default)] then all fields // after it must also be marked with that attribute, or the struct must have a // container-level serde(default) attribute. A field's default value is only // used for tuple fields if the sequence is exhausted at that point; that means // all subsequent fields will fail to deserialize if they don't have their own // default. fn check_default_on_tuple(cx: &Ctxt, cont: &Container) { if let Default::None = cont.attrs.default() { if let Data::Struct(Style::Tuple, fields) = &cont.data { let mut first_default_index = None; for (i, field) in fields.iter().enumerate() { // Skipped fields automatically get the #[serde(default)] // attribute. We are interested only on non-skipped fields here. if field.attrs.skip_deserializing() { continue; } if let Default::None = field.attrs.default() { if let Some(first) = first_default_index { cx.error_spanned_by( field.ty, format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first), ); } continue; } if first_default_index.is_none() { first_default_index = Some(i); } } } } } // Remote derive definition type must have either all of the generics of the // remote type: // // #[serde(remote = "Generic")] // struct Generic {…} // // or none of them, i.e. defining impls for one concrete instantiation of the // remote type only: // // #[serde(remote = "Generic")] // struct ConcreteDef {…} // fn check_remote_generic(cx: &Ctxt, cont: &Container) { if let Some(remote) = cont.attrs.remote() { let local_has_generic = !cont.generics.params.is_empty(); let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none(); if local_has_generic && remote_has_generic { cx.error_spanned_by(remote, "remove generic parameters from this path"); } } } // Getters are only allowed inside structs (not enums) with the `remote` // attribute. fn check_getter(cx: &Ctxt, cont: &Container) { match cont.data { Data::Enum(_) => { if cont.data.has_getter() { cx.error_spanned_by( cont.original, "#[serde(getter = \"...\")] is not allowed in an enum", ); } } Data::Struct(_, _) => { if cont.data.has_getter() && cont.attrs.remote().is_none() { cx.error_spanned_by( cont.original, "#[serde(getter = \"...\")] can only be used in structs that have #[serde(remote = \"...\")]", ); } } } } // Flattening has some restrictions we can test. fn check_flatten(cx: &Ctxt, cont: &Container) { match &cont.data { Data::Enum(variants) => { for variant in variants { for field in &variant.fields { check_flatten_field(cx, variant.style, field); } } } Data::Struct(style, fields) => { for field in fields { check_flatten_field(cx, *style, field); } } } } fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) { if !field.attrs.flatten() { return; } match style { Style::Tuple => { cx.error_spanned_by( field.original, "#[serde(flatten)] cannot be used on tuple structs", ); } Style::Newtype => { cx.error_spanned_by( field.original, "#[serde(flatten)] cannot be used on newtype structs", ); } _ => {} } } // The `other` attribute must be used at most once and it must be the last // variant of an enum. // // Inside a `variant_identifier` all variants must be unit variants. Inside a // `field_identifier` all but possibly one variant must be unit variants. The // last variant may be a newtype variant which is an implicit "other" case. fn check_identifier(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; for (i, variant) in variants.iter().enumerate() { match ( variant.style, cont.attrs.identifier(), variant.attrs.other(), cont.attrs.tag(), ) { // The `other` attribute may not be used in a variant_identifier. (_, Identifier::Variant, true, _) => { cx.error_spanned_by( variant.original, "#[serde(other)] may not be used on a variant identifier", ); } // Variant with `other` attribute cannot appear in untagged enum (_, Identifier::No, true, &TagType::None) => { cx.error_spanned_by( variant.original, "#[serde(other)] cannot appear on untagged enum", ); } // Variant with `other` attribute must be the last one. (Style::Unit, Identifier::Field, true, _) | (Style::Unit, Identifier::No, true, _) => { if i < variants.len() - 1 { cx.error_spanned_by( variant.original, "#[serde(other)] must be on the last variant", ); } } // Variant with `other` attribute must be a unit variant. (_, Identifier::Field, true, _) | (_, Identifier::No, true, _) => { cx.error_spanned_by( variant.original, "#[serde(other)] must be on a unit variant", ); } // Any sort of variant is allowed if this is not an identifier. (_, Identifier::No, false, _) => {} // Unit variant without `other` attribute is always fine. (Style::Unit, _, false, _) => {} // The last field is allowed to be a newtype catch-all. (Style::Newtype, Identifier::Field, false, _) => { if i < variants.len() - 1 { cx.error_spanned_by( variant.original, format!("`{}` must be the last variant", variant.ident), ); } } (_, Identifier::Field, false, _) => { cx.error_spanned_by( variant.original, "#[serde(field_identifier)] may only contain unit variants", ); } (_, Identifier::Variant, false, _) => { cx.error_spanned_by( variant.original, "#[serde(variant_identifier)] may only contain unit variants", ); } } } } // Skip-(de)serializing attributes are not allowed on variants marked // (de)serialize_with. fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; for variant in variants { if variant.attrs.serialize_with().is_some() { if variant.attrs.skip_serializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]", variant.ident ), ); } for field in &variant.fields { let member = member_message(&field.member); if field.attrs.skip_serializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing)]", variant.ident, member ), ); } if field.attrs.skip_serializing_if().is_some() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing_if)]", variant.ident, member ), ); } } } if variant.attrs.deserialize_with().is_some() { if variant.attrs.skip_deserializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]", variant.ident ), ); } for field in &variant.fields { if field.attrs.skip_deserializing() { let member = member_message(&field.member); cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(deserialize_with)] and a field {} marked with #[serde(skip_deserializing)]", variant.ident, member ), ); } } } } } // The tag of an internally-tagged struct variant must not be the same as either // one of its fields, as this would result in duplicate keys in the serialized // output and/or ambiguity in the to-be-deserialized input. fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; let tag = match cont.attrs.tag() { TagType::Internal { tag } => tag.as_str(), TagType::External | TagType::Adjacent { .. } | TagType::None => return, }; let diagnose_conflict = || { cx.error_spanned_by( cont.original, format!("variant field name `{}` conflicts with internal tag", tag), ); }; for variant in variants { match variant.style { Style::Struct => { if variant.attrs.untagged() { continue; } for field in &variant.fields { let check_ser = !(field.attrs.skip_serializing() || variant.attrs.skip_serializing()); let check_de = !(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing()); let name = field.attrs.name(); let ser_name = name.serialize_name(); if check_ser && ser_name == tag { diagnose_conflict(); return; } for de_name in field.attrs.aliases() { if check_de && de_name == tag { diagnose_conflict(); return; } } } } Style::Unit | Style::Newtype | Style::Tuple => {} } } } // In the case of adjacently-tagged enums, the type and the contents tag must // differ, for the same reason. fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) { let (type_tag, content_tag) = match cont.attrs.tag() { TagType::Adjacent { tag, content } => (tag, content), TagType::Internal { .. } | TagType::External | TagType::None => return, }; if type_tag == content_tag { cx.error_spanned_by( cont.original, format!( "enum tags `{}` for type and content conflict with each other", type_tag ), ); } } // Enums and unit structs cannot be transparent. fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) { if !cont.attrs.transparent() { return; } if cont.attrs.type_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(from = \"...\")]", ); } if cont.attrs.type_try_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(try_from = \"...\")]", ); } if cont.attrs.type_into().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(into = \"...\")]", ); } let fields = match &mut cont.data { Data::Enum(_) => { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed on an enum", ); return; } Data::Struct(Style::Unit, _) => { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed on a unit struct", ); return; } Data::Struct(_, fields) => fields, }; let mut transparent_field = None; for field in fields { if allow_transparent(field, derive) { if transparent_field.is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires struct to have at most one transparent field", ); return; } transparent_field = Some(field); } } match transparent_field { Some(transparent_field) => transparent_field.attrs.mark_transparent(), None => match derive { Derive::Serialize => { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires at least one field that is not skipped", ); } Derive::Deserialize => { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires at least one field that is neither skipped nor has a default", ); } }, } } fn member_message(member: &Member) -> String { match member { Member::Named(ident) => format!("`{}`", ident), Member::Unnamed(i) => format!("#{}", i.index), } } fn allow_transparent(field: &Field, derive: Derive) -> bool { if let Type::Path(ty) = ungroup(field.ty) { if let Some(seg) = ty.path.segments.last() { if seg.ident == "PhantomData" { return false; } } } match derive { Derive::Serialize => !field.attrs.skip_serializing(), Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(), } } fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { if cont.attrs.type_from().is_some() && cont.attrs.type_try_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(from = \"...\")] and #[serde(try_from = \"...\")] conflict with each other", ); } } serde_derive-1.0.195/src/internals/ctxt.rs000064400000000000000000000037451046102023000165700ustar 00000000000000use quote::ToTokens; use std::cell::RefCell; use std::fmt::Display; use std::thread; /// A type to collect errors together and format them. /// /// Dropping this object will cause a panic. It must be consumed using `check`. /// /// References can be shared since this type uses run-time exclusive mut checking. #[derive(Default)] pub struct Ctxt { // The contents will be set to `None` during checking. This is so that checking can be // enforced. errors: RefCell>>, } impl Ctxt { /// Create a new context object. /// /// This object contains no errors, but will still trigger a panic if it is not `check`ed. pub fn new() -> Self { Ctxt { errors: RefCell::new(Some(Vec::new())), } } /// Add an error to the context object with a tokenenizable object. /// /// The object is used for spanning in error messages. pub fn error_spanned_by(&self, obj: A, msg: T) { self.errors .borrow_mut() .as_mut() .unwrap() // Curb monomorphization from generating too many identical methods. .push(syn::Error::new_spanned(obj.into_token_stream(), msg)); } /// Add one of Syn's parse errors. pub fn syn_error(&self, err: syn::Error) { self.errors.borrow_mut().as_mut().unwrap().push(err); } /// Consume this object, producing a formatted error string if there are errors. pub fn check(self) -> syn::Result<()> { let mut errors = self.errors.borrow_mut().take().unwrap().into_iter(); let mut combined = match errors.next() { Some(first) => first, None => return Ok(()), }; for rest in errors { combined.combine(rest); } Err(combined) } } impl Drop for Ctxt { fn drop(&mut self) { if !thread::panicking() && self.errors.borrow().is_some() { panic!("forgot to check for errors"); } } } serde_derive-1.0.195/src/internals/mod.rs000064400000000000000000000005751046102023000163630ustar 00000000000000pub mod ast; pub mod attr; mod case; mod check; mod ctxt; mod receiver; mod respan; mod symbol; use syn::Type; pub use self::ctxt::Ctxt; pub use self::receiver::replace_receiver; #[derive(Copy, Clone)] pub enum Derive { Serialize, Deserialize, } pub fn ungroup(mut ty: &Type) -> &Type { while let Type::Group(group) = ty { ty = &group.elem; } ty } serde_derive-1.0.195/src/internals/receiver.rs000064400000000000000000000244331046102023000174070ustar 00000000000000use crate::internals::respan::respan; use proc_macro2::Span; use quote::ToTokens; use std::mem; use syn::punctuated::Punctuated; use syn::{ parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro, Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate, }; pub fn replace_receiver(input: &mut DeriveInput) { let self_ty = { let ident = &input.ident; let ty_generics = input.generics.split_for_impl().1; parse_quote!(#ident #ty_generics) }; let mut visitor = ReplaceReceiver(&self_ty); visitor.visit_generics_mut(&mut input.generics); visitor.visit_data_mut(&mut input.data); } struct ReplaceReceiver<'a>(&'a TypePath); impl ReplaceReceiver<'_> { fn self_ty(&self, span: Span) -> TypePath { let tokens = self.0.to_token_stream(); let respanned = respan(tokens, span); syn::parse2(respanned).unwrap() } fn self_to_qself(&self, qself: &mut Option, path: &mut Path) { if path.leading_colon.is_some() || path.segments[0].ident != "Self" { return; } if path.segments.len() == 1 { self.self_to_expr_path(path); return; } let span = path.segments[0].ident.span(); *qself = Some(QSelf { lt_token: Token![<](span), ty: Box::new(Type::Path(self.self_ty(span))), position: 0, as_token: None, gt_token: Token![>](span), }); path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap()); let segments = mem::replace(&mut path.segments, Punctuated::new()); path.segments = segments.into_pairs().skip(1).collect(); } fn self_to_expr_path(&self, path: &mut Path) { let self_ty = self.self_ty(path.segments[0].ident.span()); let variant = mem::replace(path, self_ty.path); for segment in &mut path.segments { if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments { if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() { bracketed.colon2_token = Some(::default()); } } } if variant.segments.len() > 1 { path.segments.push_punct(::default()); path.segments.extend(variant.segments.into_pairs().skip(1)); } } } impl ReplaceReceiver<'_> { // `Self` -> `Receiver` fn visit_type_mut(&mut self, ty: &mut Type) { let span = if let Type::Path(node) = ty { if node.qself.is_none() && node.path.is_ident("Self") { node.path.segments[0].ident.span() } else { self.visit_type_path_mut(node); return; } } else { self.visit_type_mut_impl(ty); return; }; *ty = self.self_ty(span).into(); } // `Self::Assoc` -> `::Assoc` fn visit_type_path_mut(&mut self, ty: &mut TypePath) { if ty.qself.is_none() { self.self_to_qself(&mut ty.qself, &mut ty.path); } self.visit_type_path_mut_impl(ty); } // `Self::method` -> `::method` fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) { if expr.qself.is_none() { self.self_to_qself(&mut expr.qself, &mut expr.path); } self.visit_expr_path_mut_impl(expr); } // Everything below is simply traversing the syntax tree. fn visit_type_mut_impl(&mut self, ty: &mut Type) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Type::Array(ty) => { self.visit_type_mut(&mut ty.elem); self.visit_expr_mut(&mut ty.len); } Type::BareFn(ty) => { for arg in &mut ty.inputs { self.visit_type_mut(&mut arg.ty); } self.visit_return_type_mut(&mut ty.output); } Type::Group(ty) => self.visit_type_mut(&mut ty.elem), Type::ImplTrait(ty) => { for bound in &mut ty.bounds { self.visit_type_param_bound_mut(bound); } } Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac), Type::Paren(ty) => self.visit_type_mut(&mut ty.elem), Type::Path(ty) => { if let Some(qself) = &mut ty.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut ty.path); } Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem), Type::Reference(ty) => self.visit_type_mut(&mut ty.elem), Type::Slice(ty) => self.visit_type_mut(&mut ty.elem), Type::TraitObject(ty) => { for bound in &mut ty.bounds { self.visit_type_param_bound_mut(bound); } } Type::Tuple(ty) => { for elem in &mut ty.elems { self.visit_type_mut(elem); } } Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {} _ => {} } } fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) { if let Some(qself) = &mut ty.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut ty.path); } fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) { if let Some(qself) = &mut expr.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut expr.path); } fn visit_path_mut(&mut self, path: &mut Path) { for segment in &mut path.segments { self.visit_path_arguments_mut(&mut segment.arguments); } } fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) { match arguments { PathArguments::None => {} PathArguments::AngleBracketed(arguments) => { for arg in &mut arguments.args { match arg { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] GenericArgument::Type(arg) => self.visit_type_mut(arg), GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty), GenericArgument::Lifetime(_) | GenericArgument::Const(_) | GenericArgument::AssocConst(_) | GenericArgument::Constraint(_) => {} _ => {} } } } PathArguments::Parenthesized(arguments) => { for argument in &mut arguments.inputs { self.visit_type_mut(argument); } self.visit_return_type_mut(&mut arguments.output); } } } fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) { match return_type { ReturnType::Default => {} ReturnType::Type(_, output) => self.visit_type_mut(output), } } fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) { 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(_) => {} _ => {} } } fn visit_generics_mut(&mut self, generics: &mut Generics) { for param in &mut generics.params { match param { GenericParam::Type(param) => { for bound in &mut param.bounds { self.visit_type_param_bound_mut(bound); } } GenericParam::Lifetime(_) | GenericParam::Const(_) => {} } } if let Some(where_clause) = &mut generics.where_clause { for predicate in &mut where_clause.predicates { match predicate { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] WherePredicate::Type(predicate) => { self.visit_type_mut(&mut predicate.bounded_ty); for bound in &mut predicate.bounds { self.visit_type_param_bound_mut(bound); } } WherePredicate::Lifetime(_) => {} _ => {} } } } } fn visit_data_mut(&mut self, data: &mut Data) { match data { Data::Struct(data) => { for field in &mut data.fields { self.visit_type_mut(&mut field.ty); } } Data::Enum(data) => { for variant in &mut data.variants { for field in &mut variant.fields { self.visit_type_mut(&mut field.ty); } } } Data::Union(_) => {} } } fn visit_expr_mut(&mut self, expr: &mut Expr) { match expr { Expr::Binary(expr) => { self.visit_expr_mut(&mut expr.left); self.visit_expr_mut(&mut expr.right); } Expr::Call(expr) => { self.visit_expr_mut(&mut expr.func); for arg in &mut expr.args { self.visit_expr_mut(arg); } } Expr::Cast(expr) => { self.visit_expr_mut(&mut expr.expr); self.visit_type_mut(&mut expr.ty); } Expr::Field(expr) => self.visit_expr_mut(&mut expr.base), Expr::Index(expr) => { self.visit_expr_mut(&mut expr.expr); self.visit_expr_mut(&mut expr.index); } Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr), Expr::Path(expr) => self.visit_expr_path_mut(expr), Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr), _ => {} } } fn visit_macro_mut(&mut self, _mac: &mut Macro) {} } serde_derive-1.0.195/src/internals/respan.rs000064400000000000000000000007031046102023000170650ustar 00000000000000use proc_macro2::{Group, Span, TokenStream, TokenTree}; pub(crate) fn respan(stream: TokenStream, span: Span) -> TokenStream { stream .into_iter() .map(|token| respan_token(token, span)) .collect() } fn respan_token(mut token: TokenTree, span: Span) -> TokenTree { if let TokenTree::Group(g) = &mut token { *g = Group::new(g.delimiter(), respan(g.stream(), span)); } token.set_span(span); token } serde_derive-1.0.195/src/internals/symbol.rs000064400000000000000000000047331046102023000171110ustar 00000000000000use std::fmt::{self, Display}; use syn::{Ident, Path}; #[derive(Copy, Clone)] pub struct Symbol(&'static str); pub const ALIAS: Symbol = Symbol("alias"); pub const BORROW: Symbol = Symbol("borrow"); pub const BOUND: Symbol = Symbol("bound"); pub const CONTENT: Symbol = Symbol("content"); pub const CRATE: Symbol = Symbol("crate"); pub const DEFAULT: Symbol = Symbol("default"); pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields"); pub const DESERIALIZE: Symbol = Symbol("deserialize"); pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with"); pub const EXPECTING: Symbol = Symbol("expecting"); pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier"); pub const FLATTEN: Symbol = Symbol("flatten"); pub const FROM: Symbol = Symbol("from"); pub const GETTER: Symbol = Symbol("getter"); pub const INTO: Symbol = Symbol("into"); pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive"); pub const OTHER: Symbol = Symbol("other"); pub const REMOTE: Symbol = Symbol("remote"); pub const RENAME: Symbol = Symbol("rename"); pub const RENAME_ALL: Symbol = Symbol("rename_all"); pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields"); pub const REPR: Symbol = Symbol("repr"); pub const SERDE: Symbol = Symbol("serde"); pub const SERIALIZE: Symbol = Symbol("serialize"); pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with"); pub const SKIP: Symbol = Symbol("skip"); pub const SKIP_DESERIALIZING: Symbol = Symbol("skip_deserializing"); pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing"); pub const SKIP_SERIALIZING_IF: Symbol = Symbol("skip_serializing_if"); pub const TAG: Symbol = Symbol("tag"); pub const TRANSPARENT: Symbol = Symbol("transparent"); pub const TRY_FROM: Symbol = Symbol("try_from"); pub const UNTAGGED: Symbol = Symbol("untagged"); pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier"); pub const WITH: Symbol = Symbol("with"); impl PartialEq for Ident { fn eq(&self, word: &Symbol) -> bool { self == word.0 } } impl<'a> PartialEq for &'a Ident { fn eq(&self, word: &Symbol) -> bool { *self == word.0 } } impl PartialEq for Path { fn eq(&self, word: &Symbol) -> bool { self.is_ident(word.0) } } impl<'a> PartialEq for &'a Path { fn eq(&self, word: &Symbol) -> bool { self.is_ident(word.0) } } impl Display for Symbol { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.0) } } serde_derive-1.0.195/src/lib.rs000064400000000000000000000056301046102023000143500ustar 00000000000000//! This crate provides Serde's two derive macros. //! //! ```edition2021 //! # use serde_derive::{Deserialize, Serialize}; //! # //! #[derive(Serialize, Deserialize)] //! # struct S; //! # //! # fn main() {} //! ``` //! //! Please refer to [https://serde.rs/derive.html] for how to set this up. //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.195")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 clippy::branches_sharing_code, clippy::cognitive_complexity, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575 clippy::collapsible_match, clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::match_like_matches_macro, clippy::needless_pass_by_value, clippy::too_many_arguments, clippy::trivially_copy_pass_by_ref, clippy::used_underscore_binding, clippy::wildcard_in_or_patterns, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 clippy::unnested_or_patterns, )] // Ignored clippy_pedantic lints #![allow( clippy::cast_possible_truncation, clippy::checked_conversions, clippy::doc_markdown, clippy::enum_glob_use, clippy::indexing_slicing, clippy::items_after_statements, clippy::let_underscore_untyped, clippy::manual_assert, clippy::map_err_ignore, clippy::match_same_arms, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 clippy::match_wildcard_for_single_variants, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::unseparated_literal_suffix, clippy::unused_self, clippy::use_self, clippy::wildcard_imports )] #![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] extern crate proc_macro2; extern crate quote; extern crate syn; extern crate proc_macro; mod internals; use proc_macro::TokenStream; use syn::parse_macro_input; use syn::DeriveInput; #[macro_use] mod bound; #[macro_use] mod fragment; mod de; mod dummy; mod pretend; mod ser; mod this; #[proc_macro_derive(Serialize, attributes(serde))] pub fn derive_serialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); ser::expand_derive_serialize(&mut input) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(Deserialize, attributes(serde))] pub fn derive_deserialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); de::expand_derive_deserialize(&mut input) .unwrap_or_else(syn::Error::into_compile_error) .into() } serde_derive-1.0.195/src/pretend.rs000064400000000000000000000132521046102023000152420ustar 00000000000000use crate::internals::ast::{Container, Data, Field, Style, Variant}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; // Suppress dead_code warnings that would otherwise appear when using a remote // derive. Other than this pretend code, a struct annotated with remote derive // never has its fields referenced and an enum annotated with remote derive // never has its variants constructed. // // warning: field is never used: `i` // --> src/main.rs:4:20 // | // 4 | struct StructDef { i: i32 } // | ^^^^^^ // // warning: variant is never constructed: `V` // --> src/main.rs:8:16 // | // 8 | enum EnumDef { V } // | ^ // pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream { let pretend_fields = pretend_fields_used(cont, is_packed); let pretend_variants = pretend_variants_used(cont); quote! { #pretend_fields #pretend_variants } } // For structs with named fields, expands to: // // match None::<&T> { // Some(T { a: __v0, b: __v1 }) => {} // _ => {} // } // // For packed structs on sufficiently new rustc, expands to: // // match None::<&T> { // Some(__v @ T { a: _, b: _ }) => { // let _ = addr_of!(__v.a); // let _ = addr_of!(__v.b); // } // _ => {} // } // // For packed structs on older rustc, we assume Sized and !Drop, and expand to: // // match None:: { // Some(T { a: __v0, b: __v1 }) => {} // _ => {} // } // // For enums, expands to the following but only including struct variants: // // match None::<&T> { // Some(T::A { a: __v0 }) => {} // Some(T::B { b: __v0 }) => {} // _ => {} // } // fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream { match &cont.data { Data::Enum(variants) => pretend_fields_used_enum(cont, variants), Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => { if is_packed { pretend_fields_used_struct_packed(cont, fields) } else { pretend_fields_used_struct(cont, fields) } } Data::Struct(Style::Unit, _) => quote!(), } } fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let members = fields.iter().map(|field| &field.member); let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); quote! { match _serde::__private::None::<&#type_ident #ty_generics> { _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {} _ => {} } } } fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let members = fields.iter().map(|field| &field.member).collect::>(); quote! { match _serde::__private::None::<&#type_ident #ty_generics> { _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { #( let _ = _serde::__private::ptr::addr_of!(__v.#members); )* } _ => {} } } } fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let patterns = variants .iter() .filter_map(|variant| match variant.style { Style::Struct | Style::Tuple | Style::Newtype => { let variant_ident = &variant.ident; let members = variant.fields.iter().map(|field| &field.member); let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* })) } Style::Unit => None, }) .collect::>(); quote! { match _serde::__private::None::<&#type_ident #ty_generics> { #( _serde::__private::Some(#patterns) => {} )* _ => {} } } } // Expands to one of these per enum variant: // // match None { // Some((__v0, __v1,)) => { // let _ = E::V { a: __v0, b: __v1 }; // } // _ => {} // } // fn pretend_variants_used(cont: &Container) -> TokenStream { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => { return quote!(); } }; let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let turbofish = ty_generics.as_turbofish(); let cases = variants.iter().map(|variant| { let variant_ident = &variant.ident; let placeholders = &(0..variant.fields.len()) .map(|i| format_ident!("__v{}", i)) .collect::>(); let pat = match variant.style { Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote!({ #(#members: #placeholders),* }) } Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )), Style::Unit => quote!(), }; quote! { match _serde::__private::None { _serde::__private::Some((#(#placeholders,)*)) => { let _ = #type_ident::#variant_ident #turbofish #pat; } _ => {} } } }); quote!(#(#cases)*) } serde_derive-1.0.195/src/ser.rs000064400000000000000000001302311046102023000143670ustar 00000000000000use crate::fragment::{Fragment, Match, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::internals::{attr, replace_receiver, Ctxt, Derive}; use crate::{bound, dummy, pretend, this}; use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::{parse_quote, Ident, Index, Member}; pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) { Some(cont) => cont, None => return Err(ctxt.check().unwrap_err()), }; precondition(&ctxt, &cont); ctxt.check()?; let ident = &cont.ident; let params = Parameters::new(&cont); let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); let body = Stmts(serialize_body(&cont, ¶ms)); let serde = cont.attrs.serde_path(); let impl_block = if let Some(remote) = cont.attrs.remote() { let vis = &input.vis; let used = pretend::pretend_used(&cont, params.is_packed); quote! { impl #impl_generics #ident #ty_generics #where_clause { #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> where __S: #serde::Serializer, { #used #body } } } } else { quote! { #[automatically_derived] impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> where __S: #serde::Serializer, { #body } } } }; Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), impl_block, )) } fn precondition(cx: &Ctxt, cont: &Container) { match cont.attrs.identifier() { attr::Identifier::No => {} attr::Identifier::Field => { cx.error_spanned_by(cont.original, "field identifiers cannot be serialized"); } attr::Identifier::Variant => { cx.error_spanned_by(cont.original, "variant identifiers cannot be serialized"); } } } struct Parameters { /// Variable holding the value being serialized. Either `self` for local /// types or `__self` for remote types. self_var: Ident, /// Path to the type the impl is for. Either a single `Ident` for local /// types (does not include generic parameters) or `some::remote::Path` for /// remote types. this_type: syn::Path, /// Same as `this_type` but using `::` for generic parameters for use in /// expression position. this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, /// Type has a `serde(remote = "...")` attribute. is_remote: bool, /// Type has a repr(packed) attribute. is_packed: bool, } impl Parameters { fn new(cont: &Container) -> Self { let is_remote = cont.attrs.remote().is_some(); let self_var = if is_remote { Ident::new("__self", Span::call_site()) } else { Ident::new("self", Span::call_site()) }; let this_type = this::this_type(cont); let this_value = this::this_value(cont); let is_packed = cont.attrs.is_packed(); let generics = build_generics(cont); Parameters { self_var, this_type, this_value, generics, is_remote, is_packed, } } /// Type name to use in error messages and `&'static str` arguments to /// various Serializer methods. fn type_name(&self) -> String { self.this_type.segments.last().unwrap().ident.to_string() } } // All the generics in the input, plus a bound `T: Serialize` for each generic // field type that will be serialized by us. fn build_generics(cont: &Container) -> syn::Generics { let generics = bound::without_defaults(cont.generics); let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); let generics = bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound); match cont.attrs.ser_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => bound::with_bound( cont, &generics, needs_serialize_bound, &parse_quote!(_serde::Serialize), ), } } // Fields with a `skip_serializing` or `serialize_with` attribute, or which // belong to a variant with a 'skip_serializing` or `serialize_with` attribute, // are not serialized by us so we do not generate a bound. Fields with a `bound` // attribute specify their own bound so we do not generate one. All other fields // may need a `T: Serialize` bound where T is the type of the field. fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { !field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none() && variant.map_or(true, |variant| { !variant.skip_serializing() && variant.serialize_with().is_none() && variant.ser_bound().is_none() }) } fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { if cont.attrs.transparent() { serialize_transparent(cont, params) } else if let Some(type_into) = cont.attrs.type_into() { serialize_into(params, type_into) } else { match &cont.data { Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs), Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs), Data::Struct(Style::Tuple, fields) => { serialize_tuple_struct(params, fields, &cont.attrs) } Data::Struct(Style::Newtype, fields) => { serialize_newtype_struct(params, &fields[0], &cont.attrs) } Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs), } } } fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment { let fields = match &cont.data { Data::Struct(_, fields) => fields, Data::Enum(_) => unreachable!(), }; let self_var = ¶ms.self_var; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let member = &transparent_field.member; let path = match transparent_field.attrs.serialize_with() { Some(path) => quote!(#path), None => { let span = transparent_field.original.span(); quote_spanned!(span=> _serde::Serialize::serialize) } }; quote_block! { #path(&#self_var.#member, __serializer) } } fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { let self_var = ¶ms.self_var; quote_block! { _serde::Serialize::serialize( &_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)), __serializer) } } fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment { let type_name = cattrs.name().serialize_name(); quote_expr! { _serde::Serializer::serialize_unit_struct(__serializer, #type_name) } } fn serialize_newtype_struct( params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let mut field_expr = get_member( params, field, &Member::Unnamed(Index { index: 0, span: Span::call_site(), }), ); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct); quote_expr! { #func(__serializer, #type_name, #field_expr) } } fn serialize_tuple_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_stmts = serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct); let type_name = cattrs.name().serialize_name(); let mut serialized_fields = fields .iter() .enumerate() .filter(|(_, field)| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let index = syn::Index { index: i as u32, span: Span::call_site(), }; let field_expr = get_member(params, field, &Member::Unnamed(index)); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleStruct::end(__serde_state) } } fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { assert!(fields.len() as u64 <= u64::from(u32::max_value())); if cattrs.has_flatten() { serialize_struct_as_map(params, fields, cattrs) } else { serialize_struct_as_struct(params, fields, cattrs) } } fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream { match cattrs.tag() { attr::TagType::Internal { tag } => { let type_name = cattrs.name().serialize_name(); let func = struct_trait.serialize_field(Span::call_site()); quote! { #func(&mut __serde_state, #tag, #type_name)?; } } _ => quote! {}, } } fn serialize_struct_as_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_fields = serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct); let type_name = cattrs.name().serialize_name(); let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct); let tag_field_exists = !tag_field.is_empty(); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); let len = serialized_fields .map(|field| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = get_member(params, field, &field.member); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold( quote!(#tag_field_exists as usize), |sum, expr| quote!(#sum + #expr), ); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } fn serialize_struct_as_map( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_fields = serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap); let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap); let tag_field_exists = !tag_field.is_empty(); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); let len = if cattrs.has_flatten() { quote!(_serde::__private::None) } else { let len = serialized_fields .map(|field| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = get_member(params, field, &field.member); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold( quote!(#tag_field_exists as usize), |sum, expr| quote!(#sum + #expr), ); quote!(_serde::__private::Some(#len)) }; quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { assert!(variants.len() as u64 <= u64::from(u32::max_value())); let self_var = ¶ms.self_var; let mut arms: Vec<_> = variants .iter() .enumerate() .map(|(variant_index, variant)| { serialize_variant(params, variant, variant_index as u32, cattrs) }) .collect(); if cattrs.remote().is_some() && cattrs.non_exhaustive() { arms.push(quote! { ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))), }); } quote_expr! { match *#self_var { #(#arms)* } } } fn serialize_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> TokenStream { let this_value = ¶ms.this_value; let variant_ident = &variant.ident; if variant.attrs.skip_serializing() { let skipped_msg = format!( "the enum variant {}::{} cannot be serialized", params.type_name(), variant_ident ); let skipped_err = quote! { _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg)) }; let fields_pat = match variant.style { Style::Unit => quote!(), Style::Newtype | Style::Tuple => quote!((..)), Style::Struct => quote!({ .. }), }; quote! { #this_value::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped let case = match variant.style { Style::Unit => { quote! { #this_value::#variant_ident } } Style::Newtype => { quote! { #this_value::#variant_ident(ref __field0) } } Style::Tuple => { let field_names = (0..variant.fields.len()) .map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); quote! { #this_value::#variant_ident(#(ref #field_names),*) } } Style::Struct => { let members = variant.fields.iter().map(|f| &f.member); quote! { #this_value::#variant_ident { #(ref #members),* } } } }; let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { (attr::TagType::External, false) => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs) } (attr::TagType::Internal { tag }, false) => { serialize_internally_tagged_variant(params, variant, cattrs, tag) } (attr::TagType::Adjacent { tag, content }, false) => { serialize_adjacently_tagged_variant( params, variant, cattrs, variant_index, tag, content, ) } (attr::TagType::None, _) | (_, true) => { serialize_untagged_variant(params, variant, cattrs) } }); quote! { #case => #body } } } fn serialize_externally_tagged_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::Serializer::serialize_newtype_variant( __serializer, #type_name, #variant_index, #variant_name, #ser, ) }; } match effective_style(variant) { Style::Unit => { quote_expr! { _serde::Serializer::serialize_unit_variant( __serializer, #type_name, #variant_index, #variant_name, ) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant); quote_expr! { #func( __serializer, #type_name, #variant_index, #variant_name, #field_expr, ) } } Style::Tuple => serialize_tuple_variant( TupleVariant::ExternallyTagged { type_name, variant_index, variant_name, }, params, &variant.fields, ), Style::Struct => serialize_struct_variant( StructVariant::ExternallyTagged { variant_index, variant_name, }, params, &variant.fields, type_name, ), } } fn serialize_internally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, tag: &str, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); let enum_ident_str = params.type_name(); let variant_ident_str = variant.ident.to_string(); if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::__private::ser::serialize_tagged_newtype( __serializer, #enum_ident_str, #variant_ident_str, #tag, #variant_name, #ser, ) }; } match effective_style(variant) { Style::Unit => { quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 1)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #variant_name)?; _serde::ser::SerializeStruct::end(__struct) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype); quote_expr! { #func( __serializer, #enum_ident_str, #variant_ident_str, #tag, #variant_name, #field_expr, ) } } Style::Struct => serialize_struct_variant( StructVariant::InternallyTagged { tag, variant_name }, params, &variant.fields, type_name, ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } } fn serialize_adjacently_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, variant_index: u32, tag: &str, content: &str, ) -> Fragment { let this_type = ¶ms.this_type; let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); let serialize_variant = quote! { &_serde::__private::ser::AdjacentlyTaggedEnumVariant { enum_name: #type_name, variant_index: #variant_index, variant_name: #variant_name, } }; let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); quote_expr! { _serde::Serialize::serialize(#ser, __serializer) } } else { match effective_style(variant) { Style::Unit => { return quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 1)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; _serde::ser::SerializeStruct::end(__struct) }; } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field); return quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 2)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; #func( &mut __struct, #content, #field_expr)?; _serde::ser::SerializeStruct::end(__struct) }; } Style::Tuple => { serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) } Style::Struct => serialize_struct_variant( StructVariant::Untagged, params, &variant.fields, variant_name, ), } }); let fields_ty = variant.fields.iter().map(|f| &f.ty); let fields_ident: &[_] = &match variant.style { Style::Unit => { if variant.attrs.serialize_with().is_some() { vec![] } else { unreachable!() } } Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))], Style::Tuple => (0..variant.fields.len()) .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site()))) .collect(), Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(), }; let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = if fields_ident.is_empty() { params.generics.clone() } else { bound::with_lifetime_bound(¶ms.generics, "'__a") }; let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { #[doc(hidden)] struct __AdjacentlyTagged #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { // Elements that have skip_serializing will be unused. #[allow(unused_variables)] let (#(#fields_ident,)*) = self.data; #inner } } let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 2)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #content, &__AdjacentlyTagged { data: (#(#fields_ident,)*), phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, })?; _serde::ser::SerializeStruct::end(__struct) } } fn serialize_untagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::Serialize::serialize(#ser, __serializer) }; } match effective_style(variant) { Style::Unit => { quote_expr! { _serde::Serializer::serialize_unit(__serializer) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serialize::serialize); quote_expr! { #func(#field_expr, __serializer) } } Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), Style::Struct => { let type_name = cattrs.name().serialize_name(); serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name) } } } enum TupleVariant<'a> { ExternallyTagged { type_name: &'a str, variant_index: u32, variant_name: &'a str, }, Untagged, } fn serialize_tuple_variant( context: TupleVariant, params: &Parameters, fields: &[Field], ) -> Fragment { let tuple_trait = match context { TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant, TupleVariant::Untagged => TupleTrait::SerializeTuple, }; let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); let mut serialized_fields = fields .iter() .enumerate() .filter(|(_, field)| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = Ident::new(&format!("__field{}", i), Span::call_site()); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); match context { TupleVariant::ExternallyTagged { type_name, variant_index, variant_name, } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant( __serializer, #type_name, #variant_index, #variant_name, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleVariant::end(__serde_state) } } TupleVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple( __serializer, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTuple::end(__serde_state) } } } } enum StructVariant<'a> { ExternallyTagged { variant_index: u32, variant_name: &'a str, }, InternallyTagged { tag: &'a str, variant_name: &'a str, }, Untagged, } fn serialize_struct_variant( context: StructVariant, params: &Parameters, fields: &[Field], name: &str, ) -> Fragment { if fields.iter().any(|field| field.attrs.flatten()) { return serialize_struct_variant_with_flatten(context, params, fields, name); } let struct_trait = match context { StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant, StructVariant::InternallyTagged { .. } | StructVariant::Untagged => { StructTrait::SerializeStruct } }; let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|field| { let member = &field.member; match field.attrs.skip_serializing_if() { Some(path) => quote!(if #path(#member) { 0 } else { 1 }), None => quote!(1), } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); match context { StructVariant::ExternallyTagged { variant_index, variant_name, } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant( __serializer, #name, #variant_index, #variant_name, #len, )?; #(#serialize_fields)* _serde::ser::SerializeStructVariant::end(__serde_state) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { let mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len + 1, )?; _serde::ser::SerializeStruct::serialize_field( &mut __serde_state, #tag, #variant_name, )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } StructVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len, )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } } } fn serialize_struct_variant_with_flatten( context: StructVariant, params: &Parameters, fields: &[Field], name: &str, ) -> Fragment { let struct_trait = StructTrait::SerializeMap; let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); match context { StructVariant::ExternallyTagged { variant_index, variant_name, } => { let this_type = ¶ms.this_type; let fields_ty = fields.iter().map(|f| &f.ty); let members = &fields.iter().map(|f| &f.member).collect::>(); let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a"); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { #[doc(hidden)] struct __EnumFlatten #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { let (#(#members,)*) = self.data; let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::__private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } _serde::Serializer::serialize_newtype_variant( __serializer, #name, #variant_index, #variant_name, &__EnumFlatten { data: (#(#members,)*), phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, }) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::__private::None)?; _serde::ser::SerializeMap::serialize_entry( &mut __serde_state, #tag, #variant_name, )?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } StructVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::__private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } } } fn serialize_tuple_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, tuple_trait: &TupleTrait, ) -> Vec { fields .iter() .enumerate() .filter(|(_, field)| !field.attrs.skip_serializing()) .map(|(i, field)| { let mut field_expr = if is_enum { let id = Ident::new(&format!("__field{}", i), Span::call_site()); quote!(#id) } else { get_member( params, field, &Member::Unnamed(Index { index: i as u32, span: Span::call_site(), }), ) }; let skip = field .attrs .skip_serializing_if() .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = tuple_trait.serialize_element(span); let ser = quote! { #func(&mut __serde_state, #field_expr)?; }; match skip { None => ser, Some(skip) => quote!(if !#skip { #ser }), } }) .collect() } fn serialize_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, struct_trait: &StructTrait, ) -> Vec { fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .map(|field| { let member = &field.member; let mut field_expr = if is_enum { quote!(#member) } else { get_member(params, field, member) }; let key_expr = field.attrs.name().serialize_name(); let skip = field .attrs .skip_serializing_if() .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let ser = if field.attrs.flatten() { let func = quote_spanned!(span=> _serde::Serialize::serialize); quote! { #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?; } } else { let func = struct_trait.serialize_field(span); quote! { #func(&mut __serde_state, #key_expr, #field_expr)?; } }; match skip { None => ser, Some(skip) => { if let Some(skip_func) = struct_trait.skip_field(span) { quote! { if !#skip { #ser } else { #skip_func(&mut __serde_state, #key_expr)?; } } } else { quote! { if !#skip { #ser } } } } } }) .collect() } fn wrap_serialize_field_with( params: &Parameters, field_ty: &syn::Type, serialize_with: &syn::ExprPath, field_expr: &TokenStream, ) -> TokenStream { wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) } fn wrap_serialize_variant_with( params: &Parameters, serialize_with: &syn::ExprPath, variant: &Variant, ) -> TokenStream { let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_exprs: Vec<_> = variant .fields .iter() .map(|field| { let id = match &field.member { Member::Named(ident) => ident.clone(), Member::Unnamed(member) => { Ident::new(&format!("__field{}", member.index), Span::call_site()) } }; quote!(#id) }) .collect(); wrap_serialize_with( params, serialize_with, field_tys.as_slice(), field_exprs.as_slice(), ) } fn wrap_serialize_with( params: &Parameters, serialize_with: &syn::ExprPath, field_tys: &[&syn::Type], field_exprs: &[TokenStream], ) -> TokenStream { let this_type = ¶ms.this_type; let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = if field_exprs.is_empty() { params.generics.clone() } else { bound::with_lifetime_bound(¶ms.generics, "'__a") }; let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); let field_access = (0..field_exprs.len()).map(|n| { Member::Unnamed(Index { index: n as u32, span: Span::call_site(), }) }); quote!({ #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { values: (#(&'__a #field_tys, )*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } 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> where __S: _serde::Serializer, { #serialize_with(#(self.values.#field_access, )* __s) } } &__SerializeWith { values: (#(#field_exprs, )*), phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, } }) } // Serialization of an empty struct results in code like: // // let mut __serde_state = serializer.serialize_struct("S", 0)?; // _serde::ser::SerializeStruct::end(__serde_state) // // where we want to omit the `mut` to avoid a warning. fn mut_if(is_mut: bool) -> Option { if is_mut { Some(quote!(mut)) } else { None } } fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream { let self_var = ¶ms.self_var; match (params.is_remote, field.attrs.getter()) { (false, None) => { if params.is_packed { quote!(&{#self_var.#member}) } else { quote!(&#self_var.#member) } } (true, None) => { let inner = if params.is_packed { quote!(&{#self_var.#member}) } else { quote!(&#self_var.#member) }; let ty = field.ty; quote!(_serde::__private::ser::constrain::<#ty>(#inner)) } (true, Some(getter)) => { let ty = field.ty; quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var))) } (false, Some(_)) => { unreachable!("getter is only allowed for remote impls"); } } } fn effective_style(variant: &Variant) -> Style { match variant.style { Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit, other => other, } } enum StructTrait { SerializeMap, SerializeStruct, SerializeStructVariant, } impl StructTrait { fn serialize_field(&self, span: Span) -> TokenStream { match *self { StructTrait::SerializeMap => { quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) } StructTrait::SerializeStruct => { quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field) } StructTrait::SerializeStructVariant => { quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field) } } } fn skip_field(&self, span: Span) -> Option { match *self { StructTrait::SerializeMap => None, StructTrait::SerializeStruct => { Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)) } StructTrait::SerializeStructVariant => { Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)) } } } } enum TupleTrait { SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, } impl TupleTrait { fn serialize_element(&self, span: Span) -> TokenStream { match *self { TupleTrait::SerializeTuple => { quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) } TupleTrait::SerializeTupleStruct => { quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field) } TupleTrait::SerializeTupleVariant => { quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field) } } } } serde_derive-1.0.195/src/this.rs000064400000000000000000000017571046102023000145570ustar 00000000000000use crate::internals::ast::Container; use syn::{Path, PathArguments, Token}; pub fn this_type(cont: &Container) -> Path { if let Some(remote) = cont.attrs.remote() { let mut this = remote.clone(); for segment in &mut this.segments { if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { arguments.colon2_token = None; } } this } else { Path::from(cont.ident.clone()) } } pub fn this_value(cont: &Container) -> Path { if let Some(remote) = cont.attrs.remote() { let mut this = remote.clone(); for segment in &mut this.segments { if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { if arguments.colon2_token.is_none() { arguments.colon2_token = Some(Token![::](arguments.lt_token.span)); } } } this } else { Path::from(cont.ident.clone()) } }