serde_derive-1.0.130/.cargo_vcs_info.json0000644000000001120000000000100136300ustar { "git": { "sha1": "65e1a50749938612cfbdb69b57fc4cf249f87149" } } serde_derive-1.0.130/Cargo.toml0000644000000025010000000000100116320ustar # 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] name = "serde_derive" version = "1.0.130" authors = ["Erick Tryzelaar ", "David Tolnay "] include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] 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"] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [lib] name = "serde_derive" proc-macro = true [dependencies.proc-macro2] version = "1.0" [dependencies.quote] version = "1.0" [dependencies.syn] version = "1.0.60" [dev-dependencies.serde] version = "1.0" [features] default = [] deserialize_in_place = [] serde_derive-1.0.130/Cargo.toml.orig000064400000000000000000000015650072674642500153540ustar 00000000000000[package] name = "serde_derive" version = "1.0.130" # remember to update html_root_url authors = ["Erick Tryzelaar ", "David Tolnay "] license = "MIT OR Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" homepage = "https://serde.rs" repository = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/derive.html" keywords = ["serde", "serialization", "no_std"] readme = "crates-io.md" include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] [features] default = [] deserialize_in_place = [] [lib] name = "serde_derive" proc-macro = true [dependencies] proc-macro2 = "1.0" quote = "1.0" syn = "1.0.60" [dev-dependencies] serde = { version = "1.0", path = "../serde" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] serde_derive-1.0.130/LICENSE-APACHE000064400000000000000000000251370072674642500144120ustar 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 APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. serde_derive-1.0.130/LICENSE-MIT000064400000000000000000000017770072674642500141260ustar 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.130/README.md000064400000000000000000000100520072674642500137330ustar 00000000000000# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31] [Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/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.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg [serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg [Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html [Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.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.serde.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::{Serialize, Deserialize}; #[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 [#general] or [#beginners] channels of the unofficial community Discord, the [#rust-usage] channel of the official Rust Project Discord, 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. [#general]: https://discord.com/channels/273534239310479360/274215136414400513 [#beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [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.130/build.rs000064400000000000000000000022440072674642500141250ustar 00000000000000use std::env; use std::process::Command; use std::str; // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable // these cfgs other than by executing our build script. fn main() { let minor = match rustc_minor_version() { Some(minor) => minor, None => return, }; // Underscore const names stabilized in Rust 1.37: // https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros if minor >= 37 { println!("cargo:rustc-cfg=underscore_consts"); } // The ptr::addr_of! macro stabilized in Rust 1.51: // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis if minor >= 51 { println!("cargo:rustc-cfg=ptr_addr_of"); } } fn rustc_minor_version() -> Option { let rustc = env::var_os("RUSTC")?; let output = Command::new(rustc).arg("--version").output().ok()?; let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() } serde_derive-1.0.130/crates-io.md000064400000000000000000000044340072674642500146730ustar 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.serde.rs/serde/) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action ```rust use serde::{Serialize, Deserialize}; #[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 [#general] or [#beginners] channels of the unofficial community Discord, the [#rust-usage] channel of the official Rust Project Discord, 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. [#general]: https://discord.com/channels/273534239310479360/274215136414400513 [#beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [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.130/src/bound.rs000064400000000000000000000337220072674642500147310ustar 00000000000000use std::collections::HashSet; use syn; use syn::punctuated::{Pair, Punctuated}; use internals::ast::{Container, Data}; use internals::{attr, ungroup}; use proc_macro2::Span; // 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(|predicates| predicates.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(|predicates| predicates.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 { 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(_) => {} #[cfg(test)] syn::Type::__TestExhaustive(_) => unimplemented!(), #[cfg(not(test))] _ => {} } } 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 { syn::GenericArgument::Type(arg) => self.visit_type(arg), syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty), syn::GenericArgument::Lifetime(_) | syn::GenericArgument::Constraint(_) | syn::GenericArgument::Const(_) => {} } } } 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 { syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path), syn::TypeParamBound::Lifetime(_) => {} } } // 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.iter() { 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::LifetimeDef { 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.130/src/de.rs000064400000000000000000003226140072674642500142130ustar 00000000000000use proc_macro2::{Literal, Span, TokenStream}; use quote::ToTokens; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{self, Ident, Index, Member}; use bound; use dummy; use fragment::{Expr, Fragment, Match, Stmts}; use internals::ast::{Container, Data, Field, Style, Variant}; use internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; use pretend; use std::collections::BTreeSet; use std::ptr; pub fn expand_derive_deserialize( input: &mut syn::DeriveInput, ) -> 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(), "DESERIALIZE", ident, 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 or `some::remote::Ident` for remote types. Does not include /// generic parameters. this: 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 = match cont.attrs.remote() { Some(remote) => remote.clone(), None => cont.ident.clone().into(), }; 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, 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.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_def(&self) -> Option { match self { BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeDef { 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(None, params, fields, &cont.attrs, None, &Untagged::No) } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { deserialize_tuple(None, params, fields, &cont.attrs, None) } 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(None, params, fields, &cont.attrs, None)? } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { deserialize_tuple_in_place(None, params, fields, &cont.attrs, None) } 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 = ¶ms.this; 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 { #(#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 = ¶ms.this; let type_name = cattrs.name().deserialize_name(); let expecting = format!("unit struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { struct __Visitor; impl<'de> _serde::de::Visitor<'de> for __Visitor { type Value = #this; 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) } } _serde::Deserializer::deserialize_unit_struct(__deserializer, #type_name, __Visitor) } } fn deserialize_tuple( variant_ident: Option<&syn::Ident>, params: &Parameters, fields: &[Field], cattrs: &attr::Container, deserializer: Option, ) -> Fragment { let this = ¶ms.this; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); assert!(!cattrs.has_flatten()); // 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) }; let is_enum = variant_ident.is_some(); let type_path = match variant_ident { Some(variant_ident) => quote!(#construct::#variant_ident), None => construct, }; let expecting = match variant_ident { Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), None => format!("tuple struct {}", params.type_name()), }; let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = if !is_enum && nfields == 1 { Some(deserialize_newtype_struct(&type_path, params, &fields[0])) } else { None }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, false, cattrs, expecting, )); let visitor_expr = quote! { __Visitor { marker: _serde::__private::PhantomData::<#this #ty_generics>, lifetime: _serde::__private::PhantomData, } }; let dispatch = if let Some(deserializer) = deserializer { quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) } else if is_enum { quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) } else if nfields == 1 { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { quote!(_) } else { quote!(mut __seq) }; quote_block! { struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this #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 #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( variant_ident: Option, params: &Parameters, fields: &[Field], cattrs: &attr::Container, deserializer: Option, ) -> Fragment { let this = ¶ms.this; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); assert!(!cattrs.has_flatten()); let is_enum = variant_ident.is_some(); let expecting = match variant_ident { Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), None => format!("tuple struct {}", params.type_name()), }; let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = if !is_enum && nfields == 1 { Some(deserialize_newtype_struct_in_place(params, &fields[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 dispatch = if let Some(deserializer) = deserializer { quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) } else if is_enum { quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) } else if nfields == 1 { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { 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! { struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this #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!(try!(#func(&mut __seq))) } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper _serde::__private::Option::map( try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)), |__wrap| __wrap.value) }) } }; let value_if_none = match field.attrs.default() { attr::Default::Default => quote!(_serde::__private::Default::default()), attr::Default::Path(path) => quote!(#path()), attr::Default::None => quote!( return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#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 = ¶ms.this; result = quote! { _serde::__private::Into::<#this>::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 = match field.attrs.default() { attr::Default::Default => quote!( self.place.#member = _serde::__private::Default::default(); ), attr::Default::Path(path) => quote!( self.place.#member = #path(); ), attr::Default::None => quote!( return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting)); ), }; let write = match field.attrs.deserialize_with() { None => { quote! { if let _serde::__private::None = try!(_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 try!(_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 = ¶ms.this; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: #this #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! { try!(#func(__e)) } } Some(path) => { quote! { try!(#path(__e)) } } }; let mut result = quote!(#type_path(__field0)); if params.has_getter { let this = ¶ms.this; result = quote! { _serde::__private::Into::<#this>::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) } } } #[cfg(feature = "deserialize_in_place")] fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream { // We do not generate deserialize_in_place if every field has a // deserialize_with. assert!(field.attrs.deserialize_with().is_none()); let delife = params.borrowed.de_lifetime(); 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) } } } enum Untagged { Yes, No, } fn deserialize_struct( variant_ident: Option<&syn::Ident>, params: &Parameters, fields: &[Field], cattrs: &attr::Container, deserializer: Option, untagged: &Untagged, ) -> Fragment { let is_enum = variant_ident.is_some(); let this = ¶ms.this; 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) }; let type_path = match variant_ident { Some(variant_ident) => quote!(#construct::#variant_ident), None => construct, }; let expecting = match variant_ident { Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident), None => format!("struct {}", params.type_name()), }; let expecting = cattrs.expecting().unwrap_or(&expecting); let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, true, cattrs, expecting, )); let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() { deserialize_struct_as_map_visitor(&type_path, params, fields, cattrs) } else { deserialize_struct_as_struct_visitor(&type_path, params, fields, cattrs) }; let field_visitor = Stmts(field_visitor); let fields_stmt = fields_stmt.map(Stmts); let visit_map = Stmts(visit_map); let visitor_expr = quote! { __Visitor { marker: _serde::__private::PhantomData::<#this #ty_generics>, lifetime: _serde::__private::PhantomData, } }; let dispatch = if let Some(deserializer) = deserializer { quote! { _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) } } else if is_enum && cattrs.has_flatten() { quote! { _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) } } else if is_enum { quote! { _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) } } else if cattrs.has_flatten() { quote! { _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) } } else { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { quote!(_) } else { quote!(mut __seq) }; // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. let visit_seq = match *untagged { Untagged::No if !cattrs.has_flatten() => Some(quote! { #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } }), _ => None, }; let visitor_seed = if is_enum && cattrs.has_flatten() { Some(quote! { impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<'de>, { _serde::Deserializer::deserialize_map(__deserializer, self) } } }) } else { None }; quote_block! { #field_visitor struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this #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 #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( variant_ident: Option, params: &Parameters, fields: &[Field], cattrs: &attr::Container, deserializer: Option, ) -> Option { let is_enum = variant_ident.is_some(); // for now we do not support in_place deserialization for structs that // are represented as map. if cattrs.has_flatten() { return None; } let this = ¶ms.this; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let expecting = match variant_ident { Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident), None => format!("struct {}", params.type_name()), }; let expecting = cattrs.expecting().unwrap_or(&expecting); let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let (field_visitor, fields_stmt, visit_map) = deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs); let field_visitor = Stmts(field_visitor); let fields_stmt = Stmts(fields_stmt); let visit_map = Stmts(visit_map); let visitor_expr = quote! { __Visitor { place: __place, lifetime: _serde::__private::PhantomData, } }; let dispatch = if let Some(deserializer) = deserializer { quote! { _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) } } else if is_enum { quote! { _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) } } else { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let visitor_var = if all_skipped { quote!(_) } else { quote!(mut __seq) }; let visit_seq = quote! { #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_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(); Some(quote_block! { #field_visitor struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this #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_seq #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #fields_stmt #dispatch }) } fn deserialize_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 other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other()); let variants_stmt = { let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); quote! { const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; } }; let variant_visitor = Stmts(deserialize_generated_identifier( &variant_names_idents, cattrs, true, other_idx, )); (variants_stmt, variant_visitor) } fn deserialize_externally_tagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let this = ¶ms.this; 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 we drop support for Rust 1.15: // 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 try!(_serde::de::EnumAccess::variant(__data)) { #(#variant_arms)* } } }; quote_block! { #variant_visitor struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this #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 #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 #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! { _serde::__private::de::ContentDeserializer::<__D::Error>::new(__tagged.content) }, )); 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 __tagged = try!(_serde::Deserializer::deserialize_any( __deserializer, _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))); match __tagged.tag { #(#variant_arms)* } } } fn deserialize_adjacently_tagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, tag: &str, content: &str, ) -> Fragment { let this = ¶ms.this; 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 expecting = format!("adjacently tagged enum {}", params.type_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 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::#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::#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! { try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) }; // 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 => { try!(_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 try!(_serde::de::MapAccess::next_value::<__Field>(&mut __map)) {} } } else { quote! { let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __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 struct __Seed #de_impl_generics #where_clause { field: __Field, marker: _serde::__private::PhantomData<#this #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 #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result where __D: _serde::Deserializer<#delife>, { match self.field { #(#variant_arms)* } } } struct __Visitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this #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 #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 = try!(_serde::de::MapAccess::next_value(&mut __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 = try!(_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 = try!(_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 try!(_serde::de::SeqAccess::next_element(&mut __seq)) { _serde::__private::Some(__field) => { // Visit the second element - the content. match try!(_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)) } } } } const FIELDS: &'static [&'static str] = &[#tag, #content]; _serde::Deserializer::deserialize_struct( __deserializer, #type_name, FIELDS, __Visitor { marker: _serde::__private::PhantomData::<#this #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) } } fn deserialize_untagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let attempts = variants .iter() .filter(|variant| !variant.attrs.skip_deserializing()) .map(|variant| { Expr(deserialize_untagged_variant( params, variant, cattrs, quote!( _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content) ), )) }); // 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); quote_block! { let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); #( 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 = ¶ms.this; quote_block! { try!(_serde::de::VariantAccess::unit_variant(__variant)); _serde::__private::Ok(#this::#variant_ident) } } Style::Newtype => deserialize_externally_tagged_newtype_variant( variant_ident, params, &variant.fields[0], cattrs, ), Style::Tuple => { deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None) } Style::Struct => deserialize_struct( Some(variant_ident), params, &variant.fields, cattrs, None, &Untagged::No, ), } } // 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 = ¶ms.this; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.get(0).map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_block! { try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); _serde::__private::Ok(#this::#variant_ident #default) } } Style::Newtype => deserialize_untagged_newtype_variant( variant_ident, params, &variant.fields[0], &deserializer, ), Style::Struct => deserialize_struct( Some(variant_ident), params, &variant.fields, cattrs, Some(deserializer), &Untagged::No, ), 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 = ¶ms.this; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.get(0).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::#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( Some(variant_ident), params, &variant.fields, cattrs, Some(deserializer), ), Style::Struct => deserialize_struct( Some(variant_ident), params, &variant.fields, cattrs, Some(deserializer), &Untagged::Yes, ), } } fn deserialize_externally_tagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment { let this = ¶ms.this; if field.attrs.skip_deserializing() { let this = ¶ms.this; let default = Expr(expr_is_missing(field, cattrs)); return quote_block! { try!(_serde::de::VariantAccess::unit_variant(__variant)); _serde::__private::Ok(#this::#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::#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::#variant_ident(__wrapper.value)) } } } } fn deserialize_untagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, deserializer: &TokenStream, ) -> Fragment { let this = ¶ms.this; 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::#variant_ident) } } Some(path) => { quote_block! { let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer); _serde::__private::Result::map(__value, #this::#variant_ident) } } } } fn deserialize_generated_identifier( fields: &[(String, Ident, Vec)], cattrs: &attr::Container, is_variant: bool, other_idx: Option, ) -> Fragment { let this = quote!(__Field); let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); let (ignore_variant, fallthrough) = if !is_variant && 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 let Some(other_idx) = other_idx { let ignore_variant = fields[other_idx].1.clone(); let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant)); (None, Some(fallthrough)) } else if is_variant || 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)) }; let visitor_impl = Stmts(deserialize_identifier( &this, 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)] enum __Field #lifetime { #(#field_idents,)* #ignore_variant } 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 `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 = ¶ms.this; let this = quote!(#this); 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::#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::#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().map(|(name, _, _)| name); let names_const = if fallthrough.is_some() { None } else if is_variant { let variants = quote! { const VARIANTS: &'static [&'static str] = &[ #(#names),* ]; }; Some(variants) } else { let fields = quote! { 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, &names_idents, is_variant, fallthrough, fallthrough_borrowed, false, cattrs.expecting(), )); quote_block! { #names_const struct __FieldVisitor #de_impl_generics #where_clause { marker: _serde::__private::PhantomData<#this #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 #ty_generics; #visitor_impl } let __visitor = __FieldVisitor { marker: _serde::__private::PhantomData::<#this #ty_generics>, lifetime: _serde::__private::PhantomData, }; _serde::Deserializer::deserialize_identifier(__deserializer, __visitor) } } fn deserialize_identifier( this: &TokenStream, fields: &[(String, Ident, Vec)], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { let mut flat_fields = Vec::new(); for (_, ident, aliases) in fields { flat_fields.extend(aliases.iter().map(|alias| (alias, ident))); } let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect(); let field_bytes: &Vec<_> = &flat_fields .iter() .map(|(name, _)| Literal::byte_string(name.as_bytes())) .collect(); let constructors: &Vec<_> = &flat_fields .iter() .map(|(_, ident)| quote!(#this::#ident)) .collect(); let main_constructors: &Vec<_> = &fields .iter() .map(|(_, ident, _)| quote!(#this::#ident)) .collect(); let expecting = expecting.unwrap_or(if is_variant { "variant identifier" } else { "field identifier" }); let index_expecting = if is_variant { "variant" } else { "field" }; 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 u64_fallthrough_arm_tokens; let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { fallthrough } else { 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 }; let variant_indices = 0_u64..; 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 { quote! { fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #( #variant_indices => _serde::__private::Ok(#main_constructors), )* _ => #u64_fallthrough_arm, } } } }; let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields { 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 { #( #field_strs => _serde::__private::Ok(#constructors), )* _ => { #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 { #( #field_bytes => _serde::__private::Ok(#constructors), )* _ => { #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 { #( #field_strs => _serde::__private::Ok(#constructors), )* _ => { #value_as_str_content #fallthrough_arm } } } fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { #( #field_bytes => _serde::__private::Ok(#constructors), )* _ => { #bytes_to_str #value_as_bytes_content #fallthrough_arm } } } #visit_borrowed } } fn deserialize_struct_as_struct_visitor( struct_path: &TokenStream, params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> (Fragment, Option, Fragment) { assert!(!cattrs.has_flatten()); let field_names_idents: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| { ( field.attrs.name().deserialize_name(), field_i(i), field.attrs.aliases(), ) }) .collect(); let fields_stmt = { let field_names = field_names_idents.iter().map(|(name, _, _)| name); quote_block! { const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; } }; let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); let visit_map = deserialize_map(struct_path, params, fields, cattrs); (field_visitor, Some(fields_stmt), visit_map) } fn deserialize_struct_as_map_visitor( struct_path: &TokenStream, params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> (Fragment, Option, Fragment) { let field_names_idents: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(i, field)| { ( field.attrs.name().deserialize_name(), field_i(i), field.attrs.aliases(), ) }) .collect(); let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); let visit_map = deserialize_map(struct_path, params, fields, cattrs); (field_visitor, None, visit_map) } fn deserialize_map( struct_path: &TokenStream, params: &Parameters, 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! { try!(#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, try!(_serde::de::MapAccess::next_value(&mut __map))))); } }) } else if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = try!(_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 we drop support for Rust 1.15: // let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map)); _serde::__private::Option::map( try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)), |__impossible| match __impossible {}); } } else { quote! { while let _serde::__private::Some(__key) = try!(_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 = try!(#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 = ¶ms.this; result = quote! { _serde::__private::Into::<#this>::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_struct_as_struct_in_place_visitor( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> (Fragment, Fragment, Fragment) { assert!(!cattrs.has_flatten()); let field_names_idents: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| { ( field.attrs.name().deserialize_name(), field_i(i), field.attrs.aliases(), ) }) .collect(); let fields_stmt = { let field_names = field_names_idents.iter().map(|(name, _, _)| name); quote_block! { const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; } }; let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); let visit_map = deserialize_map_in_place(params, fields, cattrs); (field_visitor, fields_stmt, visit_map) } #[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! { try!(_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 _ = try!(_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 we drop support for Rust 1.15: // let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map)); _serde::__private::Option::map( try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)), |__impossible| match __impossible {}); } } else { quote! { while let _serde::__private::Some(__key) = try!(_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 = ¶ms.this; let (_, _, ty_generics, _) = split_with_de_lifetime(params); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( let __default: #this #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 = ¶ms.this; 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! { struct __DeserializeWith #de_impl_generics #where_clause { value: #value_ty, phantom: _serde::__private::PhantomData<#this #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: try!(#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 = ¶ms.this; 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::#variant_ident { #member: #wrapper } } } Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote! { |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* } } } Style::Tuple => quote! { |#arg| #this::#variant_ident(#(#wrapper.#field_access),*) }, Style::Newtype => quote! { |#arg| #this::#variant_ident(#wrapper) }, Style::Unit => quote! { |#arg| #this::#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! { try!(#func(#name)) } } Some(_) => { quote_expr! { return _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#name)) } } } } 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_def() { 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_def() { 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); impl<'a> ToTokens for DeTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); if self.0.borrowed.de_lifetime_def().is_some() { let def = syn::LifetimeDef { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: Punctuated::new(), }; 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); } } #[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(); if self.0.borrowed.de_lifetime_def().is_some() { let def = syn::LifetimeDef { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: Punctuated::new(), }; 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); } } #[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::LifetimeDef { syn::LifetimeDef { 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.130/src/dummy.rs000064400000000000000000000023360072674642500147520ustar 00000000000000use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use syn; use try; pub fn wrap_in_const( serde_path: Option<&syn::Path>, trait_: &str, ty: &Ident, code: TokenStream, ) -> TokenStream { let try_replacement = try::replacement(); let dummy_const = if cfg!(underscore_consts) { format_ident!("_") } else { format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty)) }; 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 #dummy_const: () = { #use_serde #try_replacement #code }; } } #[allow(deprecated)] fn unraw(ident: &Ident) -> String { // str::trim_start_matches was added in 1.30, trim_left_matches deprecated // in 1.33. We currently support rustc back to 1.15 so we need to continue // to use the deprecated one. ident.to_string().trim_left_matches("r#").to_owned() } serde_derive-1.0.130/src/fragment.rs000064400000000000000000000040730072674642500154220ustar 00000000000000use proc_macro2::TokenStream; use quote::ToTokens; use syn::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.130/src/internals/ast.rs000064400000000000000000000135000072674642500164000ustar 00000000000000//! A Serde ast, parsed from the Syn ast and ready to generate Rust code. use internals::attr; use internals::check; use internals::{Ctxt, Derive}; use syn; use syn::punctuated::Punctuated; /// 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()); } } } 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> { 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() } 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.130/src/internals/attr.rs000064400000000000000000002076470072674642500166040ustar 00000000000000use internals::respan::respan; use internals::symbol::*; use internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::borrow::Cow; use std::collections::BTreeSet; use syn; use syn::parse::{self, Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::Ident; use syn::Meta::{List, NameValue, Path}; use syn::NestedMeta::{Lit, Meta}; // 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 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() { self.cx .error_spanned_by(tokens, format!("duplicate serde attribute `{}`", self.name)); } 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) -> Result, ()> { if self.values.len() > 1 { let dup_token = self.first_dup_tokens; self.cx.error_spanned_by( dup_token, format!("duplicate serde attribute `{}`", self.name), ); Err(()) } else { Ok(self.values.pop()) } } fn get(self) -> Vec { self.values } } pub struct Name { serialize: String, serialize_renamed: bool, deserialize: String, deserialize_renamed: bool, deserialize_aliases: Vec, } #[allow(deprecated)] fn unraw(ident: &Ident) -> String { // str::trim_start_matches was added in 1.30, trim_left_matches deprecated // in 1.33. We currently support rustc back to 1.15 so we need to continue // to use the deprecated one. ident.to_string().trim_left_matches("r#").to_owned() } impl Name { fn from_attrs( source_name: String, ser_name: Attr, de_name: Attr, de_aliases: Option>, ) -> Name { let deserialize_aliases = match de_aliases { Some(de_aliases) => { let mut alias_list = BTreeSet::new(); for alias_name in de_aliases.get() { alias_list.insert(alias_name); } alias_list.into_iter().collect() } None => Vec::new(), }; 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, } } /// Return the container name for the container when serializing. pub fn serialize_name(&self) -> String { self.serialize.clone() } /// Return the container name for the container when deserializing. pub fn deserialize_name(&self) -> String { self.deserialize.clone() } fn deserialize_aliases(&self) -> Vec { let mut aliases = self.deserialize_aliases.clone(); let main_name = self.deserialize_name(); if !aliases.contains(&main_name) { aliases.push(main_name); } aliases } } pub struct RenameAllRules { serialize: RenameRule, deserialize: RenameRule, } /// Represents struct or enum attribute information. pub struct Container { name: Name, transparent: bool, deny_unknown_fields: bool, default: Default, rename_all_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, } /// 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 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); for meta_item in item .attrs .iter() .flat_map(|attr| get_serde_meta_items(cx, attr)) .flatten() { match &meta_item { // Parse `#[serde(rename = "foo")]` Meta(NameValue(m)) if m.path == RENAME => { if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { ser_name.set(&m.path, s.value()); de_name.set(&m.path, s.value()); } } // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` Meta(List(m)) if m.path == RENAME => { if let Ok((ser, de)) = get_renames(cx, &m.nested) { ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); de_name.set_opt(&m.path, de.map(syn::LitStr::value)); } } // Parse `#[serde(rename_all = "foo")]` Meta(NameValue(m)) if m.path == RENAME_ALL => { if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) { match RenameRule::from_str(&s.value()) { Ok(rename_rule) => { rename_all_ser_rule.set(&m.path, rename_rule); rename_all_de_rule.set(&m.path, rename_rule); } Err(err) => cx.error_spanned_by(s, err), } } } // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]` Meta(List(m)) if m.path == RENAME_ALL => { if let Ok((ser, de)) = get_renames(cx, &m.nested) { if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&m.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(&m.path, rename_rule), Err(err) => cx.error_spanned_by(de, err), } } } } // Parse `#[serde(transparent)]` Meta(Path(word)) if word == TRANSPARENT => { transparent.set_true(word); } // Parse `#[serde(deny_unknown_fields)]` Meta(Path(word)) if word == DENY_UNKNOWN_FIELDS => { deny_unknown_fields.set_true(word); } // Parse `#[serde(default)]` Meta(Path(word)) if word == DEFAULT => match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) => { default.set(word, Default::Default); } syn::Fields::Unnamed(_) | syn::Fields::Unit => cx.error_spanned_by( fields, "#[serde(default)] can only be used on structs with named fields", ), }, syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx.error_spanned_by( enum_token, "#[serde(default)] can only be used on structs with named fields", ), syn::Data::Union(syn::DataUnion { union_token, .. }) => cx.error_spanned_by( union_token, "#[serde(default)] can only be used on structs with named fields", ), }, // Parse `#[serde(default = "...")]` Meta(NameValue(m)) if m.path == DEFAULT => { if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) { match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => { match fields { syn::Fields::Named(_) => { default.set(&m.path, Default::Path(path)); } syn::Fields::Unnamed(_) | syn::Fields::Unit => cx .error_spanned_by( fields, "#[serde(default = \"...\")] can only be used on structs with named fields", ), } } syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx .error_spanned_by( enum_token, "#[serde(default = \"...\")] can only be used on structs with named fields", ), syn::Data::Union(syn::DataUnion { union_token, .. }) => cx.error_spanned_by( union_token, "#[serde(default = \"...\")] can only be used on structs with named fields", ), } } } // Parse `#[serde(bound = "T: SomeBound")]` Meta(NameValue(m)) if m.path == BOUND => { if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { ser_bound.set(&m.path, where_predicates.clone()); de_bound.set(&m.path, where_predicates); } } // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` Meta(List(m)) if m.path == BOUND => { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { ser_bound.set_opt(&m.path, ser); de_bound.set_opt(&m.path, de); } } // Parse `#[serde(untagged)]` Meta(Path(word)) if word == UNTAGGED => match item.data { syn::Data::Enum(_) => { untagged.set_true(word); } syn::Data::Struct(syn::DataStruct { struct_token, .. }) => { cx.error_spanned_by( struct_token, "#[serde(untagged)] can only be used on enums", ); } syn::Data::Union(syn::DataUnion { union_token, .. }) => { cx.error_spanned_by( union_token, "#[serde(untagged)] can only be used on enums", ); } }, // Parse `#[serde(tag = "type")]` Meta(NameValue(m)) if m.path == TAG => { if let Ok(s) = get_lit_str(cx, TAG, &m.lit) { match &item.data { syn::Data::Enum(_) => { internal_tag.set(&m.path, s.value()); } syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) => { internal_tag.set(&m.path, s.value()); } syn::Fields::Unnamed(_) | syn::Fields::Unit => { cx.error_spanned_by( fields, "#[serde(tag = \"...\")] can only be used on enums and structs with named fields", ); } }, syn::Data::Union(syn::DataUnion { union_token, .. }) => { cx.error_spanned_by( union_token, "#[serde(tag = \"...\")] can only be used on enums and structs with named fields", ); } } } } // Parse `#[serde(content = "c")]` Meta(NameValue(m)) if m.path == CONTENT => { if let Ok(s) = get_lit_str(cx, CONTENT, &m.lit) { match &item.data { syn::Data::Enum(_) => { content.set(&m.path, s.value()); } syn::Data::Struct(syn::DataStruct { struct_token, .. }) => { cx.error_spanned_by( struct_token, "#[serde(content = \"...\")] can only be used on enums", ); } syn::Data::Union(syn::DataUnion { union_token, .. }) => { cx.error_spanned_by( union_token, "#[serde(content = \"...\")] can only be used on enums", ); } } } } // Parse `#[serde(from = "Type")] Meta(NameValue(m)) if m.path == FROM => { if let Ok(from_ty) = parse_lit_into_ty(cx, FROM, &m.lit) { type_from.set_opt(&m.path, Some(from_ty)); } } // Parse `#[serde(try_from = "Type")] Meta(NameValue(m)) if m.path == TRY_FROM => { if let Ok(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &m.lit) { type_try_from.set_opt(&m.path, Some(try_from_ty)); } } // Parse `#[serde(into = "Type")] Meta(NameValue(m)) if m.path == INTO => { if let Ok(into_ty) = parse_lit_into_ty(cx, INTO, &m.lit) { type_into.set_opt(&m.path, Some(into_ty)); } } // Parse `#[serde(remote = "...")]` Meta(NameValue(m)) if m.path == REMOTE => { if let Ok(path) = parse_lit_into_path(cx, REMOTE, &m.lit) { if is_primitive_path(&path, "Self") { remote.set(&m.path, item.ident.clone().into()); } else { remote.set(&m.path, path); } } } // Parse `#[serde(field_identifier)]` Meta(Path(word)) if word == FIELD_IDENTIFIER => { field_identifier.set_true(word); } // Parse `#[serde(variant_identifier)]` Meta(Path(word)) if word == VARIANT_IDENTIFIER => { variant_identifier.set_true(word); } // Parse `#[serde(crate = "foo")]` Meta(NameValue(m)) if m.path == CRATE => { if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) { serde_path.set(&m.path, path); } } // Parse `#[serde(expecting = "a message")]` Meta(NameValue(m)) if m.path == EXPECTING => { if let Ok(s) = get_lit_str(cx, EXPECTING, &m.lit) { expecting.set(&m.path, s.value()); } } Meta(meta_item) => { let path = meta_item .path() .into_token_stream() .to_string() .replace(' ', ""); cx.error_spanned_by( meta_item.path(), format!("unknown serde container attribute `{}`", path), ); } Lit(lit) => { cx.error_spanned_by(lit, "unexpected literal in serde container attribute"); } } } let mut is_packed = false; for attr in &item.attrs { if attr.path.is_ident("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), }, 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(), } } pub fn name(&self) -> &Name { &self.name } pub fn rename_all_rules(&self) -> &RenameAllRules { &self.rename_all_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) } } 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 { cx.error_spanned_by( variant, "#[serde(tag = \"...\")] cannot be used with tuple variants", ); break; } } } } } TagType::Internal { tag } } (Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => { cx.error_spanned_by( untagged_tokens, "enum cannot be both untagged and internally tagged", ); cx.error_spanned_by( tag_tokens, "enum cannot be both untagged and internally tagged", ); TagType::External // doesn't matter, will error } (None, None, Some((content_tokens, _))) => { cx.error_spanned_by( content_tokens, "#[serde(tag = \"...\", content = \"...\")] must be used together", ); TagType::External } (Some((untagged_tokens, _)), None, Some((content_tokens, _))) => { cx.error_spanned_by( untagged_tokens, "untagged enum cannot have #[serde(content = \"...\")]", ); cx.error_spanned_by( content_tokens, "untagged enum cannot have #[serde(content = \"...\")]", ); TagType::External } (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, (Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => { cx.error_spanned_by( untagged_tokens, "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", ); cx.error_spanned_by( tag_tokens, "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", ); cx.error_spanned_by( content_tokens, "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", ); 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, _))) => { cx.error_spanned_by( field_identifier_tokens, "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set", ); cx.error_spanned_by( variant_identifier_tokens, "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set", ); 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) => { cx.error_spanned_by( struct_token, "#[serde(field_identifier)] can only be used on an enum", ); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { cx.error_spanned_by( union_token, "#[serde(field_identifier)] can only be used on an enum", ); Identifier::No } (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { cx.error_spanned_by( struct_token, "#[serde(variant_identifier)] can only be used on an enum", ); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { cx.error_spanned_by( union_token, "#[serde(variant_identifier)] can only be used on an enum", ); 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, } 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); for meta_item in variant .attrs .iter() .flat_map(|attr| get_serde_meta_items(cx, attr)) .flatten() { match &meta_item { // Parse `#[serde(rename = "foo")]` Meta(NameValue(m)) if m.path == RENAME => { if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { ser_name.set(&m.path, s.value()); de_name.set_if_none(s.value()); de_aliases.insert(&m.path, s.value()); } } // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` Meta(List(m)) if m.path == RENAME => { if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) { ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); for de_value in de { de_name.set_if_none(de_value.value()); de_aliases.insert(&m.path, de_value.value()); } } } // Parse `#[serde(alias = "foo")]` Meta(NameValue(m)) if m.path == ALIAS => { if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) { de_aliases.insert(&m.path, s.value()); } } // Parse `#[serde(rename_all = "foo")]` Meta(NameValue(m)) if m.path == RENAME_ALL => { if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) { match RenameRule::from_str(&s.value()) { Ok(rename_rule) => { rename_all_ser_rule.set(&m.path, rename_rule); rename_all_de_rule.set(&m.path, rename_rule); } Err(err) => cx.error_spanned_by(s, err), } } } // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]` Meta(List(m)) if m.path == RENAME_ALL => { if let Ok((ser, de)) = get_renames(cx, &m.nested) { if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&m.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(&m.path, rename_rule), Err(err) => cx.error_spanned_by(de, err), } } } } // Parse `#[serde(skip)]` Meta(Path(word)) if word == SKIP => { skip_serializing.set_true(word); skip_deserializing.set_true(word); } // Parse `#[serde(skip_deserializing)]` Meta(Path(word)) if word == SKIP_DESERIALIZING => { skip_deserializing.set_true(word); } // Parse `#[serde(skip_serializing)]` Meta(Path(word)) if word == SKIP_SERIALIZING => { skip_serializing.set_true(word); } // Parse `#[serde(other)]` Meta(Path(word)) if word == OTHER => { other.set_true(word); } // Parse `#[serde(bound = "T: SomeBound")]` Meta(NameValue(m)) if m.path == BOUND => { if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { ser_bound.set(&m.path, where_predicates.clone()); de_bound.set(&m.path, where_predicates); } } // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` Meta(List(m)) if m.path == BOUND => { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { ser_bound.set_opt(&m.path, ser); de_bound.set_opt(&m.path, de); } } // Parse `#[serde(with = "...")]` Meta(NameValue(m)) if m.path == WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).into()); serialize_with.set(&m.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", Span::call_site()).into()); deserialize_with.set(&m.path, de_path); } } // Parse `#[serde(serialize_with = "...")]` Meta(NameValue(m)) if m.path == SERIALIZE_WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) { serialize_with.set(&m.path, path); } } // Parse `#[serde(deserialize_with = "...")]` Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) { deserialize_with.set(&m.path, path); } } // Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]` Meta(m) if m.path() == BORROW => match &variant.fields { syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { borrow.set(m.path(), m.clone()); } _ => { cx.error_spanned_by( variant, "#[serde(borrow)] may only be used on newtype variants", ); } }, Meta(meta_item) => { let path = meta_item .path() .into_token_stream() .to_string() .replace(' ', ""); cx.error_spanned_by( meta_item.path(), format!("unknown serde variant attribute `{}`", path), ); } Lit(lit) => { cx.error_spanned_by(lit, "unexpected literal in serde variant attribute"); } } } 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(), } } pub fn name(&self) -> &Name { &self.name } pub fn aliases(&self) -> Vec { 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); } } 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() } } /// 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(), }; let variant_borrow = attrs .and_then(|variant| variant.borrow.as_ref()) .map(|borrow| Meta(borrow.clone())); for meta_item in field .attrs .iter() .flat_map(|attr| get_serde_meta_items(cx, attr)) .flatten() .chain(variant_borrow) { match &meta_item { // Parse `#[serde(rename = "foo")]` Meta(NameValue(m)) if m.path == RENAME => { if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { ser_name.set(&m.path, s.value()); de_name.set_if_none(s.value()); de_aliases.insert(&m.path, s.value()); } } // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` Meta(List(m)) if m.path == RENAME => { if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) { ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); for de_value in de { de_name.set_if_none(de_value.value()); de_aliases.insert(&m.path, de_value.value()); } } } // Parse `#[serde(alias = "foo")]` Meta(NameValue(m)) if m.path == ALIAS => { if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) { de_aliases.insert(&m.path, s.value()); } } // Parse `#[serde(default)]` Meta(Path(word)) if word == DEFAULT => { default.set(word, Default::Default); } // Parse `#[serde(default = "...")]` Meta(NameValue(m)) if m.path == DEFAULT => { if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) { default.set(&m.path, Default::Path(path)); } } // Parse `#[serde(skip_serializing)]` Meta(Path(word)) if word == SKIP_SERIALIZING => { skip_serializing.set_true(word); } // Parse `#[serde(skip_deserializing)]` Meta(Path(word)) if word == SKIP_DESERIALIZING => { skip_deserializing.set_true(word); } // Parse `#[serde(skip)]` Meta(Path(word)) if word == SKIP => { skip_serializing.set_true(word); skip_deserializing.set_true(word); } // Parse `#[serde(skip_serializing_if = "...")]` Meta(NameValue(m)) if m.path == SKIP_SERIALIZING_IF => { if let Ok(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &m.lit) { skip_serializing_if.set(&m.path, path); } } // Parse `#[serde(serialize_with = "...")]` Meta(NameValue(m)) if m.path == SERIALIZE_WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) { serialize_with.set(&m.path, path); } } // Parse `#[serde(deserialize_with = "...")]` Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) { deserialize_with.set(&m.path, path); } } // Parse `#[serde(with = "...")]` Meta(NameValue(m)) if m.path == WITH => { if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).into()); serialize_with.set(&m.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", Span::call_site()).into()); deserialize_with.set(&m.path, de_path); } } // Parse `#[serde(bound = "T: SomeBound")]` Meta(NameValue(m)) if m.path == BOUND => { if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { ser_bound.set(&m.path, where_predicates.clone()); de_bound.set(&m.path, where_predicates); } } // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` Meta(List(m)) if m.path == BOUND => { if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { ser_bound.set_opt(&m.path, ser); de_bound.set_opt(&m.path, de); } } // Parse `#[serde(borrow)]` Meta(Path(word)) if word == BORROW => { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { borrowed_lifetimes.set(word, borrowable); } } // Parse `#[serde(borrow = "'a + 'b")]` Meta(NameValue(m)) if m.path == BORROW => { if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, BORROW, &m.lit) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { for lifetime in &lifetimes { if !borrowable.contains(lifetime) { cx.error_spanned_by( field, format!( "field `{}` does not have lifetime {}", ident, lifetime ), ); } } borrowed_lifetimes.set(&m.path, lifetimes); } } } // Parse `#[serde(getter = "...")]` Meta(NameValue(m)) if m.path == GETTER => { if let Ok(path) = parse_lit_into_expr_path(cx, GETTER, &m.lit) { getter.set(&m.path, path); } } // Parse `#[serde(flatten)]` Meta(Path(word)) if word == FLATTEN => { flatten.set_true(word); } Meta(meta_item) => { let path = meta_item .path() .into_token_stream() .to_string() .replace(' ', ""); cx.error_spanned_by( meta_item.path(), format!("unknown serde field attribute `{}`", path), ); } Lit(lit) => { cx.error_spanned_by(lit, "unexpected literal in serde field attribute"); } } } // 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) -> Vec { 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); } } 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<'a, 'b, T, F>( cx: &'b Ctxt, attr_name: Symbol, metas: &'a Punctuated, f: F, ) -> Result<(VecAttr<'b, T>, VecAttr<'b, T>), ()> where T: 'a, F: Fn(&Ctxt, Symbol, Symbol, &'a syn::Lit) -> Result, { let mut ser_meta = VecAttr::none(cx, attr_name); let mut de_meta = VecAttr::none(cx, attr_name); for meta in metas { match meta { Meta(NameValue(meta)) if meta.path == SERIALIZE => { if let Ok(v) = f(cx, attr_name, SERIALIZE, &meta.lit) { ser_meta.insert(&meta.path, v); } } Meta(NameValue(meta)) if meta.path == DESERIALIZE => { if let Ok(v) = f(cx, attr_name, DESERIALIZE, &meta.lit) { de_meta.insert(&meta.path, v); } } _ => { cx.error_spanned_by( meta, format!( "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", attr_name ), ); return Err(()); } } } Ok((ser_meta, de_meta)) } fn get_renames<'a>( cx: &Ctxt, items: &'a Punctuated, ) -> Result, ()> { let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?; Ok((ser.at_most_one()?, de.at_most_one()?)) } fn get_multiple_renames<'a>( cx: &Ctxt, items: &'a Punctuated, ) -> Result<(Option<&'a syn::LitStr>, Vec<&'a syn::LitStr>), ()> { let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?; Ok((ser.at_most_one()?, de.get())) } fn get_where_predicates( cx: &Ctxt, items: &Punctuated, ) -> Result>, ()> { let (ser, de) = get_ser_and_de(cx, BOUND, items, parse_lit_into_where)?; Ok((ser.at_most_one()?, de.at_most_one()?)) } pub fn get_serde_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result, ()> { if attr.path != SERDE { return Ok(Vec::new()); } match attr.parse_meta() { Ok(List(meta)) => Ok(meta.nested.into_iter().collect()), Ok(other) => { cx.error_spanned_by(other, "expected #[serde(...)]"); Err(()) } Err(err) => { cx.syn_error(err); Err(()) } } } fn get_lit_str<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'a syn::LitStr, ()> { get_lit_str2(cx, attr_name, attr_name, lit) } fn get_lit_str2<'a>( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, lit: &'a syn::Lit, ) -> Result<&'a syn::LitStr, ()> { if let syn::Lit::Str(lit) = lit { Ok(lit) } else { cx.error_spanned_by( lit, format!( "expected serde {} attribute to be a string: `{} = \"...\"`", attr_name, meta_item_name ), ); Err(()) } } fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result { let string = get_lit_str(cx, attr_name, lit)?; parse_lit_str(string).map_err(|_| { cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())); }) } fn parse_lit_into_expr_path( cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit, ) -> Result { let string = get_lit_str(cx, attr_name, lit)?; parse_lit_str(string).map_err(|_| { cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())); }) } fn parse_lit_into_where( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, lit: &syn::Lit, ) -> Result, ()> { let string = get_lit_str2(cx, attr_name, meta_item_name, lit)?; if string.value().is_empty() { return Ok(Vec::new()); } let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span()); parse_lit_str::(&where_string) .map(|wh| wh.predicates.into_iter().collect()) .map_err(|err| cx.error_spanned_by(lit, err)) } fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result { let string = get_lit_str(cx, attr_name, lit)?; parse_lit_str(string).map_err(|_| { cx.error_spanned_by( lit, format!("failed to parse type: {} = {:?}", attr_name, string.value()), ); }) } // Parses a string literal like "'a + 'b + 'c" containing a nonempty list of // lifetimes separated by `+`. fn parse_lit_into_lifetimes( cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit, ) -> Result, ()> { let string = get_lit_str(cx, attr_name, lit)?; if string.value().is_empty() { cx.error_spanned_by(lit, "at least one lifetime must be borrowed"); return Err(()); } struct BorrowedLifetimes(Punctuated); impl Parse for BorrowedLifetimes { fn parse(input: ParseStream) -> parse::Result { Punctuated::parse_separated_nonempty(input).map(BorrowedLifetimes) } } if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) { let mut set = BTreeSet::new(); for lifetime in lifetimes { if !set.insert(lifetime.clone()) { cx.error_spanned_by(lit, format!("duplicate borrowed lifetime `{}`", lifetime)); } } return Ok(set); } cx.error_spanned_by( lit, format!("failed to parse borrowed lifetimes: {:?}", string.value()), ); Err(()) } 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() { cx.error_spanned_by( field, format!("field `{}` has no lifetimes to borrow", name), ); Err(()) } else { Ok(lifetimes) } } fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { match ty { 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::Binding(binding) => { collect_lifetimes(&binding.ty, out); } syn::GenericArgument::Constraint(_) | syn::GenericArgument::Const(_) => {} } } } } } 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(_) => {} #[cfg(test)] syn::Type::__TestExhaustive(_) => unimplemented!(), #[cfg(not(test))] _ => {} } } 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); } _ => {} } } } fn parse_lit_str(s: &syn::LitStr) -> parse::Result where T: Parse, { let tokens = spanned_tokens(s)?; syn::parse2(tokens) } fn spanned_tokens(s: &syn::LitStr) -> parse::Result { let stream = syn::parse_str(&s.value())?; Ok(respan(stream, s.span())) } serde_derive-1.0.130/src/internals/case.rs000064400000000000000000000156770072674642500165450ustar 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`). // See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726 #[allow(deprecated, unused_imports)] use std::ascii::AsciiExt; use std::fmt::{self, Debug, Display}; use self::RenameRule::*; /// 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('_', "-"), } } } 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.130/src/internals/check.rs000064400000000000000000000335720072674642500167010ustar 00000000000000use internals::ast::{Container, Data, Field, Style}; use internals::attr::{Identifier, TagType}; use 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_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); } /// 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.iter() { 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 => { for field in &variant.fields { let check_ser = !field.attrs.skip_serializing(); let check_de = !field.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.130/src/internals/ctxt.rs000064400000000000000000000035430072674642500166010ustar 00000000000000use quote::ToTokens; use std::cell::RefCell; use std::fmt::Display; use std::thread; use syn; /// 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) -> Result<(), Vec> { let errors = self.errors.borrow_mut().take().unwrap(); match errors.len() { 0 => Ok(()), _ => Err(errors), } } } 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.130/src/internals/mod.rs000064400000000000000000000005760072674642500164010ustar 00000000000000pub mod ast; pub mod attr; mod ctxt; pub use self::ctxt::Ctxt; mod receiver; pub use self::receiver::replace_receiver; mod case; mod check; mod respan; mod symbol; use syn::Type; #[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.130/src/internals/receiver.rs000064400000000000000000000235760072674642500174330ustar 00000000000000use 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, 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 { 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(_) => {} #[cfg(test)] Type::__TestExhaustive(_) => unimplemented!(), #[cfg(not(test))] _ => {} } } 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 { GenericArgument::Type(arg) => self.visit_type_mut(arg), GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty), GenericArgument::Lifetime(_) | GenericArgument::Constraint(_) | GenericArgument::Const(_) => {} } } } 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 { TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path), TypeParamBound::Lifetime(_) => {} } } 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 { 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(_) | WherePredicate::Eq(_) => {} } } } } 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.130/src/internals/respan.rs000064400000000000000000000007030072674642500171020ustar 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.130/src/internals/symbol.rs000064400000000000000000000044620072674642500171250ustar 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 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 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 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"); pub const EXPECTING: Symbol = Symbol("expecting"); 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.130/src/lib.rs000064400000000000000000000060160072674642500143640ustar 00000000000000//! This crate provides Serde's two derive macros. //! //! ```edition2018 //! # use serde_derive::{Serialize, Deserialize}; //! # //! #[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.130")] #![allow(unknown_lints, bare_trait_objects)] #![deny(clippy::all, clippy::pedantic)] // 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::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_drop, 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::option_if_let_else, 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 )] #[macro_use] extern crate quote; #[macro_use] extern crate syn; extern crate proc_macro; extern crate proc_macro2; mod internals; use proc_macro::TokenStream; use syn::DeriveInput; #[macro_use] mod bound; #[macro_use] mod fragment; mod de; mod dummy; mod pretend; mod ser; mod try; #[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(to_compile_errors) .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(to_compile_errors) .into() } fn to_compile_errors(errors: Vec) -> proc_macro2::TokenStream { let compile_errors = errors.iter().map(syn::Error::to_compile_error); quote!(#(#compile_errors)*) } serde_derive-1.0.130/src/pretend.rs000064400000000000000000000137060072674642500152630ustar 00000000000000use proc_macro2::TokenStream; use quote::format_ident; use internals::ast::{Container, Data, Field, Style, Variant}; // 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, fields) => if is_packed { pretend_fields_used_struct_packed(cont, fields) } else { pretend_fields_used_struct(cont, fields) }, Data::Struct(_, _) => 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::>(); #[cfg(ptr_addr_of)] { quote! { match _serde::__private::None::<&#type_ident #ty_generics> { _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { #( let _ = _serde::__private::ptr::addr_of!(__v.#members); )* } _ => {} } } } #[cfg(not(ptr_addr_of))] { 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_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 => { 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),* })) } _ => 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.130/src/ser.rs000064400000000000000000001263510072674642500144140ustar 00000000000000use proc_macro2::{Span, TokenStream}; use syn::spanned::Spanned; use syn::{self, Ident, Index, Member}; use bound; use dummy; use fragment::{Fragment, Match, Stmts}; use internals::ast::{Container, Data, Field, Style, Variant}; use internals::{attr, replace_receiver, Ctxt, Derive}; use pretend; pub fn expand_derive_serialize( input: &mut syn::DeriveInput, ) -> 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(), "SERIALIZE", ident, 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 or `some::remote::Ident` for remote types. Does not include /// generic parameters. this: 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 = match cont.attrs.remote() { Some(remote) => remote.clone(), None => cont.ident.clone().into(), }; let is_packed = cont.attrs.is_packed(); let generics = build_generics(cont); Parameters { self_var, this, 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.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 = try!(_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! { try!(#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 = try!(_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 = try!(_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 arms: Vec<_> = variants .iter() .enumerate() .map(|(variant_index, variant)| { serialize_variant(params, variant, variant_index as u32, cattrs) }) .collect(); quote_expr! { match *#self_var { #(#arms)* } } } fn serialize_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> TokenStream { let this = ¶ms.this; 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::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped let case = match variant.style { Style::Unit => { quote! { #this::#variant_ident } } Style::Newtype => { quote! { #this::#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::#variant_ident(#(ref #field_names),*) } } Style::Struct => { let members = variant.fields.iter().map(|f| &f.member); quote! { #this::#variant_ident { #(ref #members),* } } } }; let body = Match(match cattrs.tag() { attr::TagType::External => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs) } attr::TagType::Internal { tag } => { serialize_internally_tagged_variant(params, variant, cattrs, tag) } attr::TagType::Adjacent { tag, content } => { serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content) } attr::TagType::None => 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 = try!(_serde::Serializer::serialize_struct( __serializer, #type_name, 1)); try!(_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, tag: &str, content: &str, ) -> Fragment { let this = ¶ms.this; let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_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 = try!(_serde::Serializer::serialize_struct( __serializer, #type_name, 1)); try!(_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::ser::SerializeStruct::serialize_field); return quote_block! { let mut __struct = try!(_serde::Serializer::serialize_struct( __serializer, #type_name, 2)); try!(_serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #variant_name)); try!(#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: &Vec<_> = &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! { struct __AdjacentlyTagged #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::__private::PhantomData<#this #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 = try!(_serde::Serializer::serialize_struct( __serializer, #type_name, 2)); try!(_serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #variant_name)); try!(_serde::ser::SerializeStruct::serialize_field( &mut __struct, #content, &__AdjacentlyTagged { data: (#(#fields_ident,)*), phantom: _serde::__private::PhantomData::<#this #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 { ExternallyTagged { type_name: String, variant_index: u32, variant_name: String, }, 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 = try!(_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 = try!(_serde::Serializer::serialize_tuple( __serializer, #len)); #(#serialize_stmts)* _serde::ser::SerializeTuple::end(__serde_state) } } } } enum StructVariant<'a> { ExternallyTagged { variant_index: u32, variant_name: String, }, InternallyTagged { tag: &'a str, variant_name: String, }, Untagged, } fn serialize_struct_variant<'a>( context: StructVariant<'a>, 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 = try!(_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 = try!(_serde::Serializer::serialize_struct( __serializer, #name, #len + 1, )); try!(_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 = try!(_serde::Serializer::serialize_struct( __serializer, #name, #len, )); #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } } } fn serialize_struct_variant_with_flatten<'a>( context: StructVariant<'a>, 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 = ¶ms.this; 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! { struct __EnumFlatten #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::__private::PhantomData<#this #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 = try!(_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 #ty_generics>, }) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { let #let_mut __serde_state = try!(_serde::Serializer::serialize_map( __serializer, _serde::__private::None)); try!(_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 = try!(_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! { try!(#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! { try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))); } } else { let func = struct_trait.serialize_field(span); quote! { try!(#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 { try!(#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 = ¶ms.this; 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!({ struct __SerializeWith #wrapper_impl_generics #where_clause { values: (#(&'__a #field_tys, )*), phantom: _serde::__private::PhantomData<#this #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 #ty_generics>, } }) } // Serialization of an empty struct results in code like: // // let mut __serde_state = try!(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.130/src/try.rs000064400000000000000000000016200072674642500144300ustar 00000000000000use proc_macro2::{Punct, Spacing, TokenStream}; // None of our generated code requires the `From::from` error conversion // performed by the standard library's `try!` macro. With this simplified macro // we see a significant improvement in type checking and borrow checking time of // the generated code and a slight improvement in binary size. pub fn replacement() -> TokenStream { // Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it. let dollar = Punct::new('$', Spacing::Alone); quote! { #[allow(unused_macros)] macro_rules! try { (#dollar __expr:expr) => { match #dollar __expr { _serde::__private::Ok(__val) => __val, _serde::__private::Err(__err) => { return _serde::__private::Err(__err); } } } } } }