]> git.proxmox.com Git - rustc.git/blame - src/vendor/serde_derive_internals/src/attr.rs
New upstream version 1.27.1+dfsg1
[rustc.git] / src / vendor / serde_derive_internals / src / attr.rs
CommitLineData
3b2f2976
XL
1// Copyright 2017 Serde Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
83c7162d
XL
9use proc_macro2::{Group, Span, TokenStream, TokenTree};
10use std::collections::BTreeSet;
11use std::str::FromStr;
3b2f2976 12use syn;
83c7162d
XL
13use syn::punctuated::Punctuated;
14use syn::synom::{ParseError, Synom};
0531ce1d
XL
15use syn::Ident;
16use syn::Meta::{List, NameValue, Word};
17use syn::NestedMeta::{Literal, Meta};
83c7162d 18use Ctxt;
3b2f2976
XL
19
20// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
21// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
22// `attr::Field::from_ast`. Each returns an instance of the corresponding
23// struct. Note that none of them return a Result. Unrecognized, malformed, or
24// duplicated attributes result in a span_err but otherwise are ignored. The
25// user will see errors simultaneously for all bad attributes in the crate
26// rather than just the first.
27
28pub use case::RenameRule;
29
0531ce1d 30#[derive(Copy, Clone)]
3b2f2976
XL
31struct Attr<'c, T> {
32 cx: &'c Ctxt,
33 name: &'static str,
34 value: Option<T>,
35}
36
37impl<'c, T> Attr<'c, T> {
38 fn none(cx: &'c Ctxt, name: &'static str) -> Self {
39 Attr {
40 cx: cx,
41 name: name,
42 value: None,
43 }
44 }
45
46 fn set(&mut self, value: T) {
47 if self.value.is_some() {
48 self.cx
49 .error(format!("duplicate serde attribute `{}`", self.name));
50 } else {
51 self.value = Some(value);
52 }
53 }
54
55 fn set_opt(&mut self, value: Option<T>) {
56 if let Some(value) = value {
57 self.set(value);
58 }
59 }
60
61 fn set_if_none(&mut self, value: T) {
62 if self.value.is_none() {
63 self.value = Some(value);
64 }
65 }
66
67 fn get(self) -> Option<T> {
68 self.value
69 }
70}
71
72struct BoolAttr<'c>(Attr<'c, ()>);
73
74impl<'c> BoolAttr<'c> {
75 fn none(cx: &'c Ctxt, name: &'static str) -> Self {
76 BoolAttr(Attr::none(cx, name))
77 }
78
79 fn set_true(&mut self) {
80 self.0.set(());
81 }
82
83 fn get(&self) -> bool {
84 self.0.value.is_some()
85 }
86}
87
3b2f2976
XL
88pub struct Name {
89 serialize: String,
90 deserialize: String,
91}
92
93impl Name {
94 /// Return the container name for the container when serializing.
95 pub fn serialize_name(&self) -> String {
96 self.serialize.clone()
97 }
98
99 /// Return the container name for the container when deserializing.
100 pub fn deserialize_name(&self) -> String {
101 self.deserialize.clone()
102 }
103}
104
105/// Represents container (e.g. struct) attribute information
3b2f2976
XL
106pub struct Container {
107 name: Name,
108 deny_unknown_fields: bool,
109 default: Default,
110 rename_all: RenameRule,
111 ser_bound: Option<Vec<syn::WherePredicate>>,
112 de_bound: Option<Vec<syn::WherePredicate>>,
113 tag: EnumTag,
0531ce1d
XL
114 type_from: Option<syn::Type>,
115 type_into: Option<syn::Type>,
3b2f2976
XL
116 remote: Option<syn::Path>,
117 identifier: Identifier,
0531ce1d 118 has_flatten: bool,
3b2f2976
XL
119}
120
121/// Styles of representing an enum.
3b2f2976
XL
122pub enum EnumTag {
123 /// The default.
124 ///
125 /// ```json
126 /// {"variant1": {"key1": "value1", "key2": "value2"}}
127 /// ```
128 External,
129
130 /// `#[serde(tag = "type")]`
131 ///
132 /// ```json
133 /// {"type": "variant1", "key1": "value1", "key2": "value2"}
134 /// ```
135 Internal { tag: String },
136
137 /// `#[serde(tag = "t", content = "c")]`
138 ///
139 /// ```json
140 /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
141 /// ```
142 Adjacent { tag: String, content: String },
143
144 /// `#[serde(untagged)]`
145 ///
146 /// ```json
147 /// {"key1": "value1", "key2": "value2"}
148 /// ```
149 None,
150}
151
152/// Whether this enum represents the fields of a struct or the variants of an
153/// enum.
0531ce1d 154#[derive(Copy, Clone)]
3b2f2976
XL
155pub enum Identifier {
156 /// It does not.
157 No,
158
159 /// This enum represents the fields of a struct. All of the variants must be
160 /// unit variants, except possibly one which is annotated with
161 /// `#[serde(other)]` and is a newtype variant.
162 Field,
163
164 /// This enum represents the variants of an enum. All of the variants must
165 /// be unit variants.
166 Variant,
167}
168
ff7c6d11
XL
169impl Identifier {
170 pub fn is_some(self) -> bool {
171 match self {
172 Identifier::No => false,
173 Identifier::Field | Identifier::Variant => true,
174 }
175 }
176}
177
3b2f2976
XL
178impl Container {
179 /// Extract out the `#[serde(...)]` attributes from an item.
180 pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
181 let mut ser_name = Attr::none(cx, "rename");
182 let mut de_name = Attr::none(cx, "rename");
183 let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
184 let mut default = Attr::none(cx, "default");
185 let mut rename_all = Attr::none(cx, "rename_all");
186 let mut ser_bound = Attr::none(cx, "bound");
187 let mut de_bound = Attr::none(cx, "bound");
188 let mut untagged = BoolAttr::none(cx, "untagged");
189 let mut internal_tag = Attr::none(cx, "tag");
190 let mut content = Attr::none(cx, "content");
0531ce1d
XL
191 let mut type_from = Attr::none(cx, "from");
192 let mut type_into = Attr::none(cx, "into");
3b2f2976
XL
193 let mut remote = Attr::none(cx, "remote");
194 let mut field_identifier = BoolAttr::none(cx, "field_identifier");
195 let mut variant_identifier = BoolAttr::none(cx, "variant_identifier");
196
197 for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
198 for meta_item in meta_items {
199 match meta_item {
200 // Parse `#[serde(rename = "foo")]`
0531ce1d
XL
201 Meta(NameValue(ref m)) if m.ident == "rename" => {
202 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
203 ser_name.set(s.value());
204 de_name.set(s.value());
3b2f2976
XL
205 }
206 }
207
208 // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
0531ce1d
XL
209 Meta(List(ref m)) if m.ident == "rename" => {
210 if let Ok((ser, de)) = get_renames(cx, &m.nested) {
211 ser_name.set_opt(ser.map(syn::LitStr::value));
212 de_name.set_opt(de.map(syn::LitStr::value));
3b2f2976
XL
213 }
214 }
215
216 // Parse `#[serde(rename_all = "foo")]`
0531ce1d
XL
217 Meta(NameValue(ref m)) if m.ident == "rename_all" => {
218 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
219 match RenameRule::from_str(&s.value()) {
3b2f2976 220 Ok(rename_rule) => rename_all.set(rename_rule),
ff7c6d11
XL
221 Err(()) => cx.error(format!(
222 "unknown rename rule for #[serde(rename_all \
223 = {:?})]",
0531ce1d 224 s.value()
ff7c6d11 225 )),
3b2f2976
XL
226 }
227 }
228 }
229
230 // Parse `#[serde(deny_unknown_fields)]`
0531ce1d 231 Meta(Word(word)) if word == "deny_unknown_fields" => {
3b2f2976
XL
232 deny_unknown_fields.set_true();
233 }
234
235 // Parse `#[serde(default)]`
0531ce1d 236 Meta(Word(word)) if word == "default" => match item.data {
83c7162d
XL
237 syn::Data::Struct(syn::DataStruct {
238 fields: syn::Fields::Named(_),
239 ..
240 }) => {
ff7c6d11 241 default.set(Default::Default);
3b2f2976 242 }
ff7c6d11
XL
243 _ => cx.error(
244 "#[serde(default)] can only be used on structs \
245 with named fields",
246 ),
247 },
3b2f2976
XL
248
249 // Parse `#[serde(default = "...")]`
0531ce1d
XL
250 Meta(NameValue(ref m)) if m.ident == "default" => {
251 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
252 match item.data {
83c7162d
XL
253 syn::Data::Struct(syn::DataStruct {
254 fields: syn::Fields::Named(_),
255 ..
256 }) => {
3b2f2976
XL
257 default.set(Default::Path(path));
258 }
ff7c6d11
XL
259 _ => cx.error(
260 "#[serde(default = \"...\")] can only be used \
261 on structs with named fields",
262 ),
3b2f2976
XL
263 }
264 }
265 }
266
267 // Parse `#[serde(bound = "D: Serialize")]`
0531ce1d 268 Meta(NameValue(ref m)) if m.ident == "bound" => {
3b2f2976 269 if let Ok(where_predicates) =
0531ce1d 270 parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit)
ff7c6d11 271 {
3b2f2976
XL
272 ser_bound.set(where_predicates.clone());
273 de_bound.set(where_predicates);
274 }
275 }
276
277 // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
0531ce1d
XL
278 Meta(List(ref m)) if m.ident == "bound" => {
279 if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
3b2f2976
XL
280 ser_bound.set_opt(ser);
281 de_bound.set_opt(de);
282 }
283 }
284
285 // Parse `#[serde(untagged)]`
0531ce1d
XL
286 Meta(Word(word)) if word == "untagged" => match item.data {
287 syn::Data::Enum(_) => {
ff7c6d11 288 untagged.set_true();
3b2f2976 289 }
0531ce1d 290 syn::Data::Struct(_) | syn::Data::Union(_) => {
ff7c6d11
XL
291 cx.error("#[serde(untagged)] can only be used on enums")
292 }
293 },
3b2f2976
XL
294
295 // Parse `#[serde(tag = "type")]`
0531ce1d
XL
296 Meta(NameValue(ref m)) if m.ident == "tag" => {
297 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
298 match item.data {
299 syn::Data::Enum(_) => {
300 internal_tag.set(s.value());
3b2f2976 301 }
0531ce1d 302 syn::Data::Struct(_) | syn::Data::Union(_) => {
3b2f2976
XL
303 cx.error("#[serde(tag = \"...\")] can only be used on enums")
304 }
305 }
306 }
307 }
308
309 // Parse `#[serde(content = "c")]`
0531ce1d
XL
310 Meta(NameValue(ref m)) if m.ident == "content" => {
311 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
312 match item.data {
313 syn::Data::Enum(_) => {
314 content.set(s.value());
3b2f2976 315 }
0531ce1d 316 syn::Data::Struct(_) | syn::Data::Union(_) => cx.error(
ff7c6d11
XL
317 "#[serde(content = \"...\")] can only be used on \
318 enums",
319 ),
3b2f2976
XL
320 }
321 }
322 }
323
324 // Parse `#[serde(from = "Type")]
0531ce1d
XL
325 Meta(NameValue(ref m)) if m.ident == "from" => {
326 if let Ok(from_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) {
327 type_from.set_opt(Some(from_ty));
3b2f2976
XL
328 }
329 }
330
331 // Parse `#[serde(into = "Type")]
0531ce1d
XL
332 Meta(NameValue(ref m)) if m.ident == "into" => {
333 if let Ok(into_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) {
334 type_into.set_opt(Some(into_ty));
3b2f2976
XL
335 }
336 }
337
338 // Parse `#[serde(remote = "...")]`
0531ce1d
XL
339 Meta(NameValue(ref m)) if m.ident == "remote" => {
340 if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
83c7162d
XL
341 if is_primitive_path(&path, "Self") {
342 remote.set(item.ident.into());
343 } else {
344 remote.set(path);
345 }
3b2f2976
XL
346 }
347 }
348
349 // Parse `#[serde(field_identifier)]`
0531ce1d 350 Meta(Word(word)) if word == "field_identifier" => {
3b2f2976
XL
351 field_identifier.set_true();
352 }
353
354 // Parse `#[serde(variant_identifier)]`
0531ce1d 355 Meta(Word(word)) if word == "variant_identifier" => {
3b2f2976
XL
356 variant_identifier.set_true();
357 }
358
0531ce1d 359 Meta(ref meta_item) => {
ff7c6d11
XL
360 cx.error(format!(
361 "unknown serde container attribute `{}`",
362 meta_item.name()
363 ));
3b2f2976
XL
364 }
365
366 Literal(_) => {
367 cx.error("unexpected literal in serde container attribute");
368 }
369 }
370 }
371 }
372
373 Container {
374 name: Name {
375 serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
376 deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
377 },
378 deny_unknown_fields: deny_unknown_fields.get(),
379 default: default.get().unwrap_or(Default::None),
380 rename_all: rename_all.get().unwrap_or(RenameRule::None),
381 ser_bound: ser_bound.get(),
382 de_bound: de_bound.get(),
0531ce1d
XL
383 tag: decide_tag(cx, item, &untagged, internal_tag, content),
384 type_from: type_from.get(),
385 type_into: type_into.get(),
3b2f2976 386 remote: remote.get(),
0531ce1d
XL
387 identifier: decide_identifier(cx, item, &field_identifier, &variant_identifier),
388 has_flatten: false,
3b2f2976
XL
389 }
390 }
391
392 pub fn name(&self) -> &Name {
393 &self.name
394 }
395
396 pub fn rename_all(&self) -> &RenameRule {
397 &self.rename_all
398 }
399
400 pub fn deny_unknown_fields(&self) -> bool {
401 self.deny_unknown_fields
402 }
403
404 pub fn default(&self) -> &Default {
405 &self.default
406 }
407
408 pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
409 self.ser_bound.as_ref().map(|vec| &vec[..])
410 }
411
412 pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
413 self.de_bound.as_ref().map(|vec| &vec[..])
414 }
415
416 pub fn tag(&self) -> &EnumTag {
417 &self.tag
418 }
419
0531ce1d
XL
420 pub fn type_from(&self) -> Option<&syn::Type> {
421 self.type_from.as_ref()
3b2f2976
XL
422 }
423
0531ce1d
XL
424 pub fn type_into(&self) -> Option<&syn::Type> {
425 self.type_into.as_ref()
3b2f2976
XL
426 }
427
428 pub fn remote(&self) -> Option<&syn::Path> {
429 self.remote.as_ref()
430 }
431
432 pub fn identifier(&self) -> Identifier {
433 self.identifier
434 }
0531ce1d
XL
435
436 pub fn has_flatten(&self) -> bool {
437 self.has_flatten
438 }
439
440 pub fn mark_has_flatten(&mut self) {
441 self.has_flatten = true;
442 }
3b2f2976
XL
443}
444
445fn decide_tag(
446 cx: &Ctxt,
447 item: &syn::DeriveInput,
0531ce1d 448 untagged: &BoolAttr,
3b2f2976
XL
449 internal_tag: Attr<String>,
450 content: Attr<String>,
451) -> EnumTag {
452 match (untagged.get(), internal_tag.get(), content.get()) {
453 (false, None, None) => EnumTag::External,
454 (true, None, None) => EnumTag::None,
455 (false, Some(tag), None) => {
456 // Check that there are no tuple variants.
0531ce1d
XL
457 if let syn::Data::Enum(ref data) = item.data {
458 for variant in &data.variants {
459 match variant.fields {
460 syn::Fields::Named(_) | syn::Fields::Unit => {}
461 syn::Fields::Unnamed(ref fields) => {
462 if fields.unnamed.len() != 1 {
3b2f2976
XL
463 cx.error(
464 "#[serde(tag = \"...\")] cannot be used with tuple \
ff7c6d11 465 variants",
3b2f2976
XL
466 );
467 break;
468 }
469 }
470 }
471 }
472 }
473 EnumTag::Internal { tag: tag }
474 }
475 (true, Some(_), None) => {
476 cx.error("enum cannot be both untagged and internally tagged");
477 EnumTag::External // doesn't matter, will error
478 }
479 (false, None, Some(_)) => {
ff7c6d11 480 cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
3b2f2976
XL
481 EnumTag::External
482 }
483 (true, None, Some(_)) => {
484 cx.error("untagged enum cannot have #[serde(content = \"...\")]");
485 EnumTag::External
486 }
ff7c6d11
XL
487 (false, Some(tag), Some(content)) => EnumTag::Adjacent {
488 tag: tag,
489 content: content,
490 },
3b2f2976 491 (true, Some(_), Some(_)) => {
ff7c6d11 492 cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
3b2f2976
XL
493 EnumTag::External
494 }
495 }
496}
497
498fn decide_identifier(
499 cx: &Ctxt,
500 item: &syn::DeriveInput,
0531ce1d
XL
501 field_identifier: &BoolAttr,
502 variant_identifier: &BoolAttr,
3b2f2976 503) -> Identifier {
0531ce1d 504 match (&item.data, field_identifier.get(), variant_identifier.get()) {
3b2f2976
XL
505 (_, false, false) => Identifier::No,
506 (_, true, true) => {
ff7c6d11 507 cx.error("`field_identifier` and `variant_identifier` cannot both be set");
3b2f2976
XL
508 Identifier::No
509 }
0531ce1d
XL
510 (&syn::Data::Enum(_), true, false) => Identifier::Field,
511 (&syn::Data::Enum(_), false, true) => Identifier::Variant,
83c7162d 512 (&syn::Data::Struct(_), true, false) | (&syn::Data::Union(_), true, false) => {
3b2f2976
XL
513 cx.error("`field_identifier` can only be used on an enum");
514 Identifier::No
515 }
83c7162d 516 (&syn::Data::Struct(_), false, true) | (&syn::Data::Union(_), false, true) => {
3b2f2976
XL
517 cx.error("`variant_identifier` can only be used on an enum");
518 Identifier::No
519 }
3b2f2976
XL
520 }
521}
522
523/// Represents variant attribute information
3b2f2976
XL
524pub struct Variant {
525 name: Name,
526 ser_renamed: bool,
527 de_renamed: bool,
528 rename_all: RenameRule,
529 skip_deserializing: bool,
530 skip_serializing: bool,
531 other: bool,
0531ce1d
XL
532 serialize_with: Option<syn::ExprPath>,
533 deserialize_with: Option<syn::ExprPath>,
534 borrow: Option<syn::Meta>,
3b2f2976
XL
535}
536
537impl Variant {
538 pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
539 let mut ser_name = Attr::none(cx, "rename");
540 let mut de_name = Attr::none(cx, "rename");
541 let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
542 let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
543 let mut rename_all = Attr::none(cx, "rename_all");
544 let mut other = BoolAttr::none(cx, "other");
ea8adc8c
XL
545 let mut serialize_with = Attr::none(cx, "serialize_with");
546 let mut deserialize_with = Attr::none(cx, "deserialize_with");
abe05a73 547 let mut borrow = Attr::none(cx, "borrow");
3b2f2976
XL
548
549 for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
550 for meta_item in meta_items {
551 match meta_item {
552 // Parse `#[serde(rename = "foo")]`
0531ce1d
XL
553 Meta(NameValue(ref m)) if m.ident == "rename" => {
554 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
555 ser_name.set(s.value());
556 de_name.set(s.value());
3b2f2976
XL
557 }
558 }
559
560 // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
0531ce1d
XL
561 Meta(List(ref m)) if m.ident == "rename" => {
562 if let Ok((ser, de)) = get_renames(cx, &m.nested) {
563 ser_name.set_opt(ser.map(syn::LitStr::value));
564 de_name.set_opt(de.map(syn::LitStr::value));
3b2f2976
XL
565 }
566 }
567
568 // Parse `#[serde(rename_all = "foo")]`
0531ce1d
XL
569 Meta(NameValue(ref m)) if m.ident == "rename_all" => {
570 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
571 match RenameRule::from_str(&s.value()) {
3b2f2976 572 Ok(rename_rule) => rename_all.set(rename_rule),
ff7c6d11
XL
573 Err(()) => cx.error(format!(
574 "unknown rename rule for #[serde(rename_all \
575 = {:?})]",
0531ce1d 576 s.value()
ff7c6d11 577 )),
3b2f2976
XL
578 }
579 }
580 }
581
582 // Parse `#[serde(skip_deserializing)]`
0531ce1d 583 Meta(Word(word)) if word == "skip_deserializing" => {
3b2f2976
XL
584 skip_deserializing.set_true();
585 }
586
587 // Parse `#[serde(skip_serializing)]`
0531ce1d 588 Meta(Word(word)) if word == "skip_serializing" => {
3b2f2976
XL
589 skip_serializing.set_true();
590 }
591
592 // Parse `#[serde(other)]`
0531ce1d 593 Meta(Word(word)) if word == "other" => {
3b2f2976
XL
594 other.set_true();
595 }
596
ea8adc8c 597 // Parse `#[serde(with = "...")]`
0531ce1d
XL
598 Meta(NameValue(ref m)) if m.ident == "with" => {
599 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
ea8adc8c 600 let mut ser_path = path.clone();
83c7162d
XL
601 ser_path
602 .path
603 .segments
604 .push(Ident::new("serialize", Span::call_site()).into());
ea8adc8c
XL
605 serialize_with.set(ser_path);
606 let mut de_path = path;
83c7162d
XL
607 de_path
608 .path
609 .segments
610 .push(Ident::new("deserialize", Span::call_site()).into());
ea8adc8c
XL
611 deserialize_with.set(de_path);
612 }
613 }
614
615 // Parse `#[serde(serialize_with = "...")]`
0531ce1d
XL
616 Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
617 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
ea8adc8c
XL
618 serialize_with.set(path);
619 }
620 }
621
622 // Parse `#[serde(deserialize_with = "...")]`
0531ce1d
XL
623 Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
624 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
ea8adc8c
XL
625 deserialize_with.set(path);
626 }
627 }
628
abe05a73 629 // Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
0531ce1d
XL
630 Meta(ref m) if m.name() == "borrow" => match variant.fields {
631 syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => {
632 borrow.set(m.clone());
abe05a73 633 }
ff7c6d11
XL
634 _ => {
635 cx.error("#[serde(borrow)] may only be used on newtype variants");
636 }
637 },
abe05a73 638
0531ce1d 639 Meta(ref meta_item) => {
ff7c6d11
XL
640 cx.error(format!(
641 "unknown serde variant attribute `{}`",
642 meta_item.name()
643 ));
3b2f2976
XL
644 }
645
646 Literal(_) => {
647 cx.error("unexpected literal in serde variant attribute");
648 }
649 }
650 }
651 }
652
653 let ser_name = ser_name.get();
654 let ser_renamed = ser_name.is_some();
655 let de_name = de_name.get();
656 let de_renamed = de_name.is_some();
657 Variant {
658 name: Name {
659 serialize: ser_name.unwrap_or_else(|| variant.ident.to_string()),
660 deserialize: de_name.unwrap_or_else(|| variant.ident.to_string()),
661 },
662 ser_renamed: ser_renamed,
663 de_renamed: de_renamed,
664 rename_all: rename_all.get().unwrap_or(RenameRule::None),
665 skip_deserializing: skip_deserializing.get(),
666 skip_serializing: skip_serializing.get(),
667 other: other.get(),
ea8adc8c
XL
668 serialize_with: serialize_with.get(),
669 deserialize_with: deserialize_with.get(),
abe05a73 670 borrow: borrow.get(),
3b2f2976
XL
671 }
672 }
673
674 pub fn name(&self) -> &Name {
675 &self.name
676 }
677
678 pub fn rename_by_rule(&mut self, rule: &RenameRule) {
679 if !self.ser_renamed {
680 self.name.serialize = rule.apply_to_variant(&self.name.serialize);
681 }
682 if !self.de_renamed {
683 self.name.deserialize = rule.apply_to_variant(&self.name.deserialize);
684 }
685 }
686
687 pub fn rename_all(&self) -> &RenameRule {
688 &self.rename_all
689 }
690
691 pub fn skip_deserializing(&self) -> bool {
692 self.skip_deserializing
693 }
694
695 pub fn skip_serializing(&self) -> bool {
696 self.skip_serializing
697 }
698
699 pub fn other(&self) -> bool {
700 self.other
701 }
ea8adc8c 702
0531ce1d 703 pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
ea8adc8c
XL
704 self.serialize_with.as_ref()
705 }
706
0531ce1d 707 pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
ea8adc8c
XL
708 self.deserialize_with.as_ref()
709 }
3b2f2976
XL
710}
711
712/// Represents field attribute information
3b2f2976
XL
713pub struct Field {
714 name: Name,
715 ser_renamed: bool,
716 de_renamed: bool,
717 skip_serializing: bool,
718 skip_deserializing: bool,
0531ce1d 719 skip_serializing_if: Option<syn::ExprPath>,
3b2f2976 720 default: Default,
0531ce1d
XL
721 serialize_with: Option<syn::ExprPath>,
722 deserialize_with: Option<syn::ExprPath>,
3b2f2976
XL
723 ser_bound: Option<Vec<syn::WherePredicate>>,
724 de_bound: Option<Vec<syn::WherePredicate>>,
725 borrowed_lifetimes: BTreeSet<syn::Lifetime>,
0531ce1d
XL
726 getter: Option<syn::ExprPath>,
727 flatten: bool,
3b2f2976
XL
728}
729
730/// Represents the default to use for a field when deserializing.
3b2f2976
XL
731pub enum Default {
732 /// Field must always be specified because it does not have a default.
733 None,
734 /// The default is given by `std::default::Default::default()`.
735 Default,
736 /// The default is given by this function.
0531ce1d 737 Path(syn::ExprPath),
3b2f2976
XL
738}
739
740impl Field {
741 /// Extract out the `#[serde(...)]` attributes from a struct field.
ff7c6d11
XL
742 pub fn from_ast(
743 cx: &Ctxt,
744 index: usize,
745 field: &syn::Field,
746 attrs: Option<&Variant>,
747 container_default: &Default,
748 ) -> Self {
3b2f2976
XL
749 let mut ser_name = Attr::none(cx, "rename");
750 let mut de_name = Attr::none(cx, "rename");
751 let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
752 let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
753 let mut skip_serializing_if = Attr::none(cx, "skip_serializing_if");
754 let mut default = Attr::none(cx, "default");
755 let mut serialize_with = Attr::none(cx, "serialize_with");
756 let mut deserialize_with = Attr::none(cx, "deserialize_with");
757 let mut ser_bound = Attr::none(cx, "bound");
758 let mut de_bound = Attr::none(cx, "bound");
759 let mut borrowed_lifetimes = Attr::none(cx, "borrow");
760 let mut getter = Attr::none(cx, "getter");
0531ce1d 761 let mut flatten = BoolAttr::none(cx, "flatten");
3b2f2976
XL
762
763 let ident = match field.ident {
764 Some(ref ident) => ident.to_string(),
765 None => index.to_string(),
766 };
767
abe05a73
XL
768 let variant_borrow = attrs
769 .map(|variant| &variant.borrow)
770 .unwrap_or(&None)
771 .as_ref()
0531ce1d 772 .map(|borrow| vec![Meta(borrow.clone())]);
abe05a73 773
ff7c6d11
XL
774 for meta_items in field
775 .attrs
776 .iter()
777 .filter_map(get_serde_meta_items)
778 .chain(variant_borrow)
779 {
3b2f2976
XL
780 for meta_item in meta_items {
781 match meta_item {
782 // Parse `#[serde(rename = "foo")]`
0531ce1d
XL
783 Meta(NameValue(ref m)) if m.ident == "rename" => {
784 if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
785 ser_name.set(s.value());
786 de_name.set(s.value());
3b2f2976
XL
787 }
788 }
789
790 // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
0531ce1d
XL
791 Meta(List(ref m)) if m.ident == "rename" => {
792 if let Ok((ser, de)) = get_renames(cx, &m.nested) {
793 ser_name.set_opt(ser.map(syn::LitStr::value));
794 de_name.set_opt(de.map(syn::LitStr::value));
3b2f2976
XL
795 }
796 }
797
798 // Parse `#[serde(default)]`
0531ce1d 799 Meta(Word(word)) if word == "default" => {
3b2f2976
XL
800 default.set(Default::Default);
801 }
802
803 // Parse `#[serde(default = "...")]`
0531ce1d
XL
804 Meta(NameValue(ref m)) if m.ident == "default" => {
805 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976
XL
806 default.set(Default::Path(path));
807 }
808 }
809
810 // Parse `#[serde(skip_serializing)]`
0531ce1d 811 Meta(Word(word)) if word == "skip_serializing" => {
3b2f2976
XL
812 skip_serializing.set_true();
813 }
814
815 // Parse `#[serde(skip_deserializing)]`
0531ce1d 816 Meta(Word(word)) if word == "skip_deserializing" => {
3b2f2976
XL
817 skip_deserializing.set_true();
818 }
819
820 // Parse `#[serde(skip)]`
0531ce1d 821 Meta(Word(word)) if word == "skip" => {
3b2f2976
XL
822 skip_serializing.set_true();
823 skip_deserializing.set_true();
ff7c6d11 824 }
3b2f2976
XL
825
826 // Parse `#[serde(skip_serializing_if = "...")]`
0531ce1d
XL
827 Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => {
828 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976
XL
829 skip_serializing_if.set(path);
830 }
831 }
832
833 // Parse `#[serde(serialize_with = "...")]`
0531ce1d
XL
834 Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
835 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976
XL
836 serialize_with.set(path);
837 }
838 }
839
840 // Parse `#[serde(deserialize_with = "...")]`
0531ce1d
XL
841 Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
842 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976
XL
843 deserialize_with.set(path);
844 }
845 }
846
847 // Parse `#[serde(with = "...")]`
0531ce1d
XL
848 Meta(NameValue(ref m)) if m.ident == "with" => {
849 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976 850 let mut ser_path = path.clone();
83c7162d
XL
851 ser_path
852 .path
853 .segments
854 .push(Ident::new("serialize", Span::call_site()).into());
3b2f2976
XL
855 serialize_with.set(ser_path);
856 let mut de_path = path;
83c7162d
XL
857 de_path
858 .path
859 .segments
860 .push(Ident::new("deserialize", Span::call_site()).into());
3b2f2976
XL
861 deserialize_with.set(de_path);
862 }
863 }
864
865 // Parse `#[serde(bound = "D: Serialize")]`
0531ce1d 866 Meta(NameValue(ref m)) if m.ident == "bound" => {
3b2f2976 867 if let Ok(where_predicates) =
0531ce1d 868 parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit)
ff7c6d11 869 {
3b2f2976
XL
870 ser_bound.set(where_predicates.clone());
871 de_bound.set(where_predicates);
872 }
873 }
874
875 // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
0531ce1d
XL
876 Meta(List(ref m)) if m.ident == "bound" => {
877 if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
3b2f2976
XL
878 ser_bound.set_opt(ser);
879 de_bound.set_opt(de);
880 }
881 }
882
883 // Parse `#[serde(borrow)]`
0531ce1d 884 Meta(Word(word)) if word == "borrow" => {
3b2f2976
XL
885 if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
886 borrowed_lifetimes.set(borrowable);
887 }
888 }
889
890 // Parse `#[serde(borrow = "'a + 'b")]`
0531ce1d 891 Meta(NameValue(ref m)) if m.ident == "borrow" => {
83c7162d
XL
892 if let Ok(lifetimes) =
893 parse_lit_into_lifetimes(cx, m.ident.as_ref(), &m.lit)
894 {
3b2f2976
XL
895 if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
896 for lifetime in &lifetimes {
897 if !borrowable.contains(lifetime) {
ff7c6d11
XL
898 cx.error(format!(
899 "field `{}` does not have lifetime {}",
0531ce1d 900 ident, lifetime
ff7c6d11 901 ));
3b2f2976
XL
902 }
903 }
904 borrowed_lifetimes.set(lifetimes);
905 }
906 }
907 }
908
909 // Parse `#[serde(getter = "...")]`
0531ce1d
XL
910 Meta(NameValue(ref m)) if m.ident == "getter" => {
911 if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
3b2f2976
XL
912 getter.set(path);
913 }
914 }
915
0531ce1d
XL
916 // Parse `#[serde(flatten)]`
917 Meta(Word(word)) if word == "flatten" => {
918 flatten.set_true();
919 }
920
921 Meta(ref meta_item) => {
ff7c6d11
XL
922 cx.error(format!(
923 "unknown serde field attribute `{}`",
924 meta_item.name()
925 ));
3b2f2976
XL
926 }
927
928 Literal(_) => {
929 cx.error("unexpected literal in serde field attribute");
930 }
931 }
932 }
933 }
934
ff7c6d11
XL
935 // Is skip_deserializing, initialize the field to Default::default() unless a different
936 // default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g.
937 // the struct we are in).
0531ce1d
XL
938 if let Default::None = *container_default {
939 if skip_deserializing.0.value.is_some() {
940 default.set_if_none(Default::Default);
941 }
3b2f2976
XL
942 }
943
944 let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default();
945 if !borrowed_lifetimes.is_empty() {
946 // Cow<str> and Cow<[u8]> never borrow by default:
947 //
948 // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
949 //
950 // A #[serde(borrow)] attribute enables borrowing that corresponds
951 // roughly to these impls:
952 //
953 // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str>
954 // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]>
0531ce1d
XL
955 if is_cow(&field.ty, is_str) {
956 let mut path = syn::Path {
957 leading_colon: None,
958 segments: Punctuated::new(),
959 };
83c7162d
XL
960 path.segments
961 .push(Ident::new("_serde", Span::call_site()).into());
962 path.segments
963 .push(Ident::new("private", Span::call_site()).into());
964 path.segments
965 .push(Ident::new("de", Span::call_site()).into());
966 path.segments
967 .push(Ident::new("borrow_cow_str", Span::call_site()).into());
0531ce1d
XL
968 let expr = syn::ExprPath {
969 attrs: Vec::new(),
970 qself: None,
971 path: path,
972 };
973 deserialize_with.set_if_none(expr);
974 } else if is_cow(&field.ty, is_slice_u8) {
975 let mut path = syn::Path {
976 leading_colon: None,
977 segments: Punctuated::new(),
978 };
83c7162d
XL
979 path.segments
980 .push(Ident::new("_serde", Span::call_site()).into());
981 path.segments
982 .push(Ident::new("private", Span::call_site()).into());
983 path.segments
984 .push(Ident::new("de", Span::call_site()).into());
985 path.segments
986 .push(Ident::new("borrow_cow_bytes", Span::call_site()).into());
0531ce1d
XL
987 let expr = syn::ExprPath {
988 attrs: Vec::new(),
989 qself: None,
990 path: path,
991 };
992 deserialize_with.set_if_none(expr);
3b2f2976 993 }
0531ce1d 994 } else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) {
3b2f2976
XL
995 // Types &str and &[u8] are always implicitly borrowed. No need for
996 // a #[serde(borrow)].
0531ce1d 997 collect_lifetimes(&field.ty, &mut borrowed_lifetimes);
3b2f2976
XL
998 }
999
1000 let ser_name = ser_name.get();
1001 let ser_renamed = ser_name.is_some();
1002 let de_name = de_name.get();
1003 let de_renamed = de_name.is_some();
1004 Field {
1005 name: Name {
1006 serialize: ser_name.unwrap_or_else(|| ident.clone()),
1007 deserialize: de_name.unwrap_or(ident),
1008 },
1009 ser_renamed: ser_renamed,
1010 de_renamed: de_renamed,
1011 skip_serializing: skip_serializing.get(),
1012 skip_deserializing: skip_deserializing.get(),
1013 skip_serializing_if: skip_serializing_if.get(),
1014 default: default.get().unwrap_or(Default::None),
1015 serialize_with: serialize_with.get(),
1016 deserialize_with: deserialize_with.get(),
1017 ser_bound: ser_bound.get(),
1018 de_bound: de_bound.get(),
1019 borrowed_lifetimes: borrowed_lifetimes,
1020 getter: getter.get(),
0531ce1d 1021 flatten: flatten.get(),
3b2f2976
XL
1022 }
1023 }
1024
1025 pub fn name(&self) -> &Name {
1026 &self.name
1027 }
1028
1029 pub fn rename_by_rule(&mut self, rule: &RenameRule) {
1030 if !self.ser_renamed {
1031 self.name.serialize = rule.apply_to_field(&self.name.serialize);
1032 }
1033 if !self.de_renamed {
1034 self.name.deserialize = rule.apply_to_field(&self.name.deserialize);
1035 }
1036 }
1037
1038 pub fn skip_serializing(&self) -> bool {
1039 self.skip_serializing
1040 }
1041
1042 pub fn skip_deserializing(&self) -> bool {
1043 self.skip_deserializing
1044 }
1045
0531ce1d 1046 pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> {
3b2f2976
XL
1047 self.skip_serializing_if.as_ref()
1048 }
1049
1050 pub fn default(&self) -> &Default {
1051 &self.default
1052 }
1053
0531ce1d 1054 pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
3b2f2976
XL
1055 self.serialize_with.as_ref()
1056 }
1057
0531ce1d 1058 pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
3b2f2976
XL
1059 self.deserialize_with.as_ref()
1060 }
1061
1062 pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
1063 self.ser_bound.as_ref().map(|vec| &vec[..])
1064 }
1065
1066 pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
1067 self.de_bound.as_ref().map(|vec| &vec[..])
1068 }
1069
1070 pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> {
1071 &self.borrowed_lifetimes
1072 }
1073
0531ce1d 1074 pub fn getter(&self) -> Option<&syn::ExprPath> {
3b2f2976
XL
1075 self.getter.as_ref()
1076 }
0531ce1d
XL
1077
1078 pub fn flatten(&self) -> bool {
1079 self.flatten
1080 }
3b2f2976
XL
1081}
1082
1083type SerAndDe<T> = (Option<T>, Option<T>);
1084
0531ce1d 1085fn get_ser_and_de<'a, T, F>(
3b2f2976
XL
1086 cx: &Ctxt,
1087 attr_name: &'static str,
0531ce1d 1088 metas: &'a Punctuated<syn::NestedMeta, Token![,]>,
3b2f2976
XL
1089 f: F,
1090) -> Result<SerAndDe<T>, ()>
1091where
0531ce1d
XL
1092 T: 'a,
1093 F: Fn(&Ctxt, &str, &str, &'a syn::Lit) -> Result<T, ()>,
3b2f2976 1094{
0531ce1d
XL
1095 let mut ser_meta = Attr::none(cx, attr_name);
1096 let mut de_meta = Attr::none(cx, attr_name);
1097
1098 for meta in metas {
1099 match *meta {
1100 Meta(NameValue(ref meta)) if meta.ident == "serialize" => {
1101 if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) {
1102 ser_meta.set(v);
3b2f2976
XL
1103 }
1104 }
1105
0531ce1d
XL
1106 Meta(NameValue(ref meta)) if meta.ident == "deserialize" => {
1107 if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) {
1108 de_meta.set(v);
3b2f2976
XL
1109 }
1110 }
1111
1112 _ => {
ff7c6d11
XL
1113 cx.error(format!(
1114 "malformed {0} attribute, expected `{0}(serialize = ..., \
1115 deserialize = ...)`",
1116 attr_name
1117 ));
3b2f2976
XL
1118 return Err(());
1119 }
1120 }
1121 }
1122
0531ce1d 1123 Ok((ser_meta.get(), de_meta.get()))
3b2f2976
XL
1124}
1125
83c7162d
XL
1126fn get_renames<'a>(
1127 cx: &Ctxt,
1128 items: &'a Punctuated<syn::NestedMeta, Token![,]>,
1129) -> Result<SerAndDe<&'a syn::LitStr>, ()> {
0531ce1d 1130 get_ser_and_de(cx, "rename", items, get_lit_str)
3b2f2976
XL
1131}
1132
1133fn get_where_predicates(
1134 cx: &Ctxt,
0531ce1d 1135 items: &Punctuated<syn::NestedMeta, Token![,]>,
3b2f2976
XL
1136) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
1137 get_ser_and_de(cx, "bound", items, parse_lit_into_where)
1138}
1139
0531ce1d
XL
1140pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMeta>> {
1141 if attr.path.segments.len() == 1 && attr.path.segments[0].ident == "serde" {
1142 match attr.interpret_meta() {
1143 Some(List(ref meta)) => Some(meta.nested.iter().cloned().collect()),
1144 _ => {
1145 // TODO: produce an error
1146 None
1147 }
1148 }
1149 } else {
1150 None
3b2f2976
XL
1151 }
1152}
1153
0531ce1d 1154fn get_lit_str<'a>(
3b2f2976
XL
1155 cx: &Ctxt,
1156 attr_name: &str,
1157 meta_item_name: &str,
0531ce1d
XL
1158 lit: &'a syn::Lit,
1159) -> Result<&'a syn::LitStr, ()> {
1160 if let syn::Lit::Str(ref lit) = *lit {
1161 Ok(lit)
3b2f2976 1162 } else {
ff7c6d11
XL
1163 cx.error(format!(
1164 "expected serde {} attribute to be a string: `{} = \"...\"`",
1165 attr_name, meta_item_name
1166 ));
3b2f2976
XL
1167 Err(())
1168 }
1169}
1170
1171fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
0531ce1d 1172 let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
83c7162d
XL
1173 parse_lit_str(string)
1174 .map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
0531ce1d
XL
1175}
1176
83c7162d
XL
1177fn parse_lit_into_expr_path(
1178 cx: &Ctxt,
1179 attr_name: &str,
1180 lit: &syn::Lit,
1181) -> Result<syn::ExprPath, ()> {
0531ce1d 1182 let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
83c7162d
XL
1183 parse_lit_str(string)
1184 .map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
3b2f2976
XL
1185}
1186
1187fn parse_lit_into_where(
1188 cx: &Ctxt,
1189 attr_name: &str,
1190 meta_item_name: &str,
1191 lit: &syn::Lit,
1192) -> Result<Vec<syn::WherePredicate>, ()> {
0531ce1d
XL
1193 let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit));
1194 if string.value().is_empty() {
3b2f2976
XL
1195 return Ok(Vec::new());
1196 }
1197
83c7162d 1198 let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span());
3b2f2976 1199
0531ce1d
XL
1200 parse_lit_str::<syn::WhereClause>(&where_string)
1201 .map(|wh| wh.predicates.into_iter().collect())
3b2f2976
XL
1202 .map_err(|err| cx.error(err))
1203}
1204
0531ce1d
XL
1205fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Type, ()> {
1206 let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
3b2f2976 1207
0531ce1d 1208 parse_lit_str(string).map_err(|_| {
ff7c6d11
XL
1209 cx.error(format!(
1210 "failed to parse type: {} = {:?}",
83c7162d
XL
1211 attr_name,
1212 string.value()
ff7c6d11
XL
1213 ))
1214 })
3b2f2976
XL
1215}
1216
1217// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of
1218// lifetimes separated by `+`.
1219fn parse_lit_into_lifetimes(
1220 cx: &Ctxt,
1221 attr_name: &str,
1222 lit: &syn::Lit,
1223) -> Result<BTreeSet<syn::Lifetime>, ()> {
0531ce1d
XL
1224 let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
1225 if string.value().is_empty() {
3b2f2976
XL
1226 cx.error("at least one lifetime must be borrowed");
1227 return Err(());
1228 }
1229
0531ce1d 1230 struct BorrowedLifetimes(Punctuated<syn::Lifetime, Token![+]>);
3b2f2976 1231
0531ce1d
XL
1232 impl Synom for BorrowedLifetimes {
1233 named!(parse -> Self, map!(
1234 call!(Punctuated::parse_separated_nonempty),
1235 BorrowedLifetimes
1236 ));
1237 }
1238
1239 if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
1240 let mut set = BTreeSet::new();
1241 for lifetime in lifetimes {
1242 if !set.insert(lifetime) {
1243 cx.error(format!("duplicate borrowed lifetime `{}`", lifetime));
3b2f2976 1244 }
3b2f2976 1245 }
0531ce1d 1246 return Ok(set);
3b2f2976 1247 }
0531ce1d 1248
83c7162d
XL
1249 cx.error(format!(
1250 "failed to parse borrowed lifetimes: {:?}",
1251 string.value()
1252 ));
0531ce1d 1253 Err(())
3b2f2976
XL
1254}
1255
1256// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T".
1257// This can have false negatives and false positives.
1258//
1259// False negative:
1260//
1261// use std::borrow::Cow as Pig;
1262//
1263// #[derive(Deserialize)]
1264// struct S<'a> {
1265// #[serde(borrow)]
1266// pig: Pig<'a, str>,
1267// }
1268//
1269// False positive:
1270//
1271// type str = [i16];
1272//
1273// #[derive(Deserialize)]
1274// struct S<'a> {
1275// #[serde(borrow)]
1276// cow: Cow<'a, str>,
1277// }
0531ce1d 1278fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
3b2f2976 1279 let path = match *ty {
0531ce1d 1280 syn::Type::Path(ref ty) => &ty.path,
3b2f2976
XL
1281 _ => {
1282 return false;
1283 }
1284 };
1285 let seg = match path.segments.last() {
0531ce1d 1286 Some(seg) => seg.into_value(),
3b2f2976
XL
1287 None => {
1288 return false;
1289 }
1290 };
0531ce1d
XL
1291 let args = match seg.arguments {
1292 syn::PathArguments::AngleBracketed(ref bracketed) => &bracketed.args,
3b2f2976
XL
1293 _ => {
1294 return false;
1295 }
1296 };
83c7162d
XL
1297 seg.ident == "Cow" && args.len() == 2 && match (&args[0], &args[1]) {
1298 (&syn::GenericArgument::Lifetime(_), &syn::GenericArgument::Type(ref arg)) => elem(arg),
1299 _ => false,
1300 }
3b2f2976
XL
1301}
1302
1303// Whether the type looks like it might be `&T` where elem="T". This can have
1304// false negatives and false positives.
1305//
1306// False negative:
1307//
1308// type Yarn = str;
1309//
1310// #[derive(Deserialize)]
1311// struct S<'a> {
1312// r: &'a Yarn,
1313// }
1314//
1315// False positive:
1316//
1317// type str = [i16];
1318//
1319// #[derive(Deserialize)]
1320// struct S<'a> {
1321// r: &'a str,
1322// }
0531ce1d 1323fn is_rptr(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
3b2f2976 1324 match *ty {
83c7162d 1325 syn::Type::Reference(ref ty) => ty.mutability.is_none() && elem(&ty.elem),
0531ce1d
XL
1326 _ => false,
1327 }
1328}
1329
1330fn is_str(ty: &syn::Type) -> bool {
83c7162d 1331 is_primitive_type(ty, "str")
0531ce1d
XL
1332}
1333
1334fn is_slice_u8(ty: &syn::Type) -> bool {
1335 match *ty {
83c7162d 1336 syn::Type::Slice(ref ty) => is_primitive_type(&ty.elem, "u8"),
0531ce1d
XL
1337 _ => false,
1338 }
1339}
1340
83c7162d 1341fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool {
0531ce1d 1342 match *ty {
83c7162d 1343 syn::Type::Path(ref ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive),
3b2f2976
XL
1344 _ => false,
1345 }
1346}
1347
83c7162d
XL
1348fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
1349 path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == primitive
1350 && path.segments[0].arguments.is_empty()
1351}
1352
3b2f2976
XL
1353// All lifetimes that this type could borrow from a Deserializer.
1354//
1355// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand
1356// a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer.
1357//
1358// This is used when there is an explicit or implicit `#[serde(borrow)]`
1359// attribute on the field so there must be at least one borrowable lifetime.
1360fn borrowable_lifetimes(
1361 cx: &Ctxt,
1362 name: &str,
0531ce1d 1363 ty: &syn::Type,
3b2f2976
XL
1364) -> Result<BTreeSet<syn::Lifetime>, ()> {
1365 let mut lifetimes = BTreeSet::new();
1366 collect_lifetimes(ty, &mut lifetimes);
1367 if lifetimes.is_empty() {
0531ce1d
XL
1368 cx.error(format!("field `{}` has no lifetimes to borrow", name));
1369 Err(())
3b2f2976
XL
1370 } else {
1371 Ok(lifetimes)
1372 }
1373}
1374
0531ce1d 1375fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
3b2f2976 1376 match *ty {
0531ce1d
XL
1377 syn::Type::Slice(ref ty) => {
1378 collect_lifetimes(&ty.elem, out);
3b2f2976 1379 }
0531ce1d
XL
1380 syn::Type::Array(ref ty) => {
1381 collect_lifetimes(&ty.elem, out);
3b2f2976 1382 }
0531ce1d
XL
1383 syn::Type::Ptr(ref ty) => {
1384 collect_lifetimes(&ty.elem, out);
3b2f2976 1385 }
0531ce1d
XL
1386 syn::Type::Reference(ref ty) => {
1387 out.extend(ty.lifetime.iter().cloned());
1388 collect_lifetimes(&ty.elem, out);
1389 }
1390 syn::Type::Tuple(ref ty) => for elem in &ty.elems {
ff7c6d11
XL
1391 collect_lifetimes(elem, out);
1392 },
0531ce1d
XL
1393 syn::Type::Path(ref ty) => {
1394 if let Some(ref qself) = ty.qself {
3b2f2976
XL
1395 collect_lifetimes(&qself.ty, out);
1396 }
0531ce1d
XL
1397 for seg in &ty.path.segments {
1398 if let syn::PathArguments::AngleBracketed(ref bracketed) = seg.arguments {
1399 for arg in &bracketed.args {
1400 match *arg {
1401 syn::GenericArgument::Lifetime(ref lifetime) => {
1402 out.insert(lifetime.clone());
1403 }
1404 syn::GenericArgument::Type(ref ty) => {
1405 collect_lifetimes(ty, out);
1406 }
1407 syn::GenericArgument::Binding(ref binding) => {
1408 collect_lifetimes(&binding.ty, out);
1409 }
1410 syn::GenericArgument::Const(_) => {}
1411 }
3b2f2976
XL
1412 }
1413 }
1414 }
1415 }
0531ce1d
XL
1416 syn::Type::Paren(ref ty) => {
1417 collect_lifetimes(&ty.elem, out);
1418 }
1419 syn::Type::Group(ref ty) => {
1420 collect_lifetimes(&ty.elem, out);
1421 }
1422 syn::Type::BareFn(_)
1423 | syn::Type::Never(_)
1424 | syn::Type::TraitObject(_)
1425 | syn::Type::ImplTrait(_)
1426 | syn::Type::Infer(_)
1427 | syn::Type::Macro(_)
1428 | syn::Type::Verbatim(_) => {}
1429 }
1430}
1431
1432fn parse_lit_str<T>(s: &syn::LitStr) -> Result<T, ParseError>
1433where
1434 T: Synom,
1435{
1436 let tokens = try!(spanned_tokens(s));
1437 syn::parse2(tokens)
1438}
1439
1440fn spanned_tokens(s: &syn::LitStr) -> Result<TokenStream, ParseError> {
1441 let stream = try!(syn::parse_str(&s.value()));
83c7162d 1442 Ok(respan_token_stream(stream, s.span()))
0531ce1d
XL
1443}
1444
1445fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
83c7162d
XL
1446 stream
1447 .into_iter()
1448 .map(|token| respan_token_tree(token, span))
1449 .collect()
0531ce1d
XL
1450}
1451
83c7162d
XL
1452fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
1453 if let TokenTree::Group(ref mut g) = token {
1454 *g = Group::new(g.delimiter(), respan_token_stream(g.stream().clone(), span));
3b2f2976 1455 }
83c7162d
XL
1456 token.set_span(span);
1457 token
3b2f2976 1458}