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