1 | use crate::internals::name::{MultiName, Name}; |
2 | use crate::internals::symbol::*; |
3 | use crate::internals::{ungroup, Ctxt}; |
4 | use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; |
5 | use quote::ToTokens; |
6 | use std::borrow::Cow; |
7 | use std::collections::BTreeSet; |
8 | use std::iter::FromIterator; |
9 | use syn::meta::ParseNestedMeta; |
10 | use syn::parse::ParseStream; |
11 | use syn::punctuated::Punctuated; |
12 | use syn::spanned::Spanned; |
13 | use syn::{parse_quote, token, Ident, Lifetime, Token}; |
14 | |
15 | // This module handles parsing of `#[serde(...)]` attributes. The entrypoints |
16 | // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and |
17 | // `attr::Field::from_ast`. Each returns an instance of the corresponding |
18 | // struct. Note that none of them return a Result. Unrecognized, malformed, or |
19 | // duplicated attributes result in a span_err but otherwise are ignored. The |
20 | // user will see errors simultaneously for all bad attributes in the crate |
21 | // rather than just the first. |
22 | |
23 | pub use crate::internals::case::RenameRule; |
24 | |
25 | pub(crate) struct Attr<'c, T> { |
26 | cx: &'c Ctxt, |
27 | name: Symbol, |
28 | tokens: TokenStream, |
29 | value: Option<T>, |
30 | } |
31 | |
32 | impl<'c, T> Attr<'c, T> { |
33 | fn none(cx: &'c Ctxt, name: Symbol) -> Self { |
34 | Attr { |
35 | cx, |
36 | name, |
37 | tokens: TokenStream::new(), |
38 | value: None, |
39 | } |
40 | } |
41 | |
42 | fn set<A: ToTokens>(&mut self, obj: A, value: T) { |
43 | let tokens = obj.into_token_stream(); |
44 | |
45 | if self.value.is_some() { |
46 | let msg = format!("duplicate serde attribute ` {}`" , self.name); |
47 | self.cx.error_spanned_by(tokens, msg); |
48 | } else { |
49 | self.tokens = tokens; |
50 | self.value = Some(value); |
51 | } |
52 | } |
53 | |
54 | fn set_opt<A: ToTokens>(&mut self, obj: A, value: Option<T>) { |
55 | if let Some(value) = value { |
56 | self.set(obj, value); |
57 | } |
58 | } |
59 | |
60 | fn set_if_none(&mut self, value: T) { |
61 | if self.value.is_none() { |
62 | self.value = Some(value); |
63 | } |
64 | } |
65 | |
66 | pub(crate) fn get(self) -> Option<T> { |
67 | self.value |
68 | } |
69 | |
70 | fn get_with_tokens(self) -> Option<(TokenStream, T)> { |
71 | match self.value { |
72 | Some(v) => Some((self.tokens, v)), |
73 | None => None, |
74 | } |
75 | } |
76 | } |
77 | |
78 | struct BoolAttr<'c>(Attr<'c, ()>); |
79 | |
80 | impl<'c> BoolAttr<'c> { |
81 | fn none(cx: &'c Ctxt, name: Symbol) -> Self { |
82 | BoolAttr(Attr::none(cx, name)) |
83 | } |
84 | |
85 | fn set_true<A: ToTokens>(&mut self, obj: A) { |
86 | self.0.set(obj, ()); |
87 | } |
88 | |
89 | fn get(&self) -> bool { |
90 | self.0.value.is_some() |
91 | } |
92 | } |
93 | |
94 | pub(crate) struct VecAttr<'c, T> { |
95 | cx: &'c Ctxt, |
96 | name: Symbol, |
97 | first_dup_tokens: TokenStream, |
98 | values: Vec<T>, |
99 | } |
100 | |
101 | impl<'c, T> VecAttr<'c, T> { |
102 | fn none(cx: &'c Ctxt, name: Symbol) -> Self { |
103 | VecAttr { |
104 | cx, |
105 | name, |
106 | first_dup_tokens: TokenStream::new(), |
107 | values: Vec::new(), |
108 | } |
109 | } |
110 | |
111 | fn insert<A: ToTokens>(&mut self, obj: A, value: T) { |
112 | if self.values.len() == 1 { |
113 | self.first_dup_tokens = obj.into_token_stream(); |
114 | } |
115 | self.values.push(value); |
116 | } |
117 | |
118 | fn at_most_one(mut self) -> Option<T> { |
119 | if self.values.len() > 1 { |
120 | let dup_token = self.first_dup_tokens; |
121 | let msg = format!("duplicate serde attribute ` {}`" , self.name); |
122 | self.cx.error_spanned_by(dup_token, msg); |
123 | None |
124 | } else { |
125 | self.values.pop() |
126 | } |
127 | } |
128 | |
129 | pub(crate) fn get(self) -> Vec<T> { |
130 | self.values |
131 | } |
132 | } |
133 | |
134 | fn unraw(ident: &Ident) -> Ident { |
135 | Ident::new(string:ident.to_string().trim_start_matches("r#" ), ident.span()) |
136 | } |
137 | |
138 | #[derive (Copy, Clone)] |
139 | pub struct RenameAllRules { |
140 | pub serialize: RenameRule, |
141 | pub deserialize: RenameRule, |
142 | } |
143 | |
144 | impl RenameAllRules { |
145 | /// Returns a new `RenameAllRules` with the individual rules of `self` and |
146 | /// `other_rules` joined by `RenameRules::or`. |
147 | pub fn or(self, other_rules: Self) -> Self { |
148 | Self { |
149 | serialize: self.serialize.or(rule_b:other_rules.serialize), |
150 | deserialize: self.deserialize.or(rule_b:other_rules.deserialize), |
151 | } |
152 | } |
153 | } |
154 | |
155 | /// Represents struct or enum attribute information. |
156 | pub struct Container { |
157 | name: MultiName, |
158 | transparent: bool, |
159 | deny_unknown_fields: bool, |
160 | default: Default, |
161 | rename_all_rules: RenameAllRules, |
162 | rename_all_fields_rules: RenameAllRules, |
163 | ser_bound: Option<Vec<syn::WherePredicate>>, |
164 | de_bound: Option<Vec<syn::WherePredicate>>, |
165 | tag: TagType, |
166 | type_from: Option<syn::Type>, |
167 | type_try_from: Option<syn::Type>, |
168 | type_into: Option<syn::Type>, |
169 | remote: Option<syn::Path>, |
170 | identifier: Identifier, |
171 | serde_path: Option<syn::Path>, |
172 | is_packed: bool, |
173 | /// Error message generated when type can't be deserialized |
174 | expecting: Option<String>, |
175 | non_exhaustive: bool, |
176 | } |
177 | |
178 | /// Styles of representing an enum. |
179 | pub enum TagType { |
180 | /// The default. |
181 | /// |
182 | /// ```json |
183 | /// {"variant1": {"key1": "value1", "key2": "value2"}} |
184 | /// ``` |
185 | External, |
186 | |
187 | /// `#[serde(tag = "type")]` |
188 | /// |
189 | /// ```json |
190 | /// {"type": "variant1", "key1": "value1", "key2": "value2"} |
191 | /// ``` |
192 | Internal { tag: String }, |
193 | |
194 | /// `#[serde(tag = "t", content = "c")]` |
195 | /// |
196 | /// ```json |
197 | /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}} |
198 | /// ``` |
199 | Adjacent { tag: String, content: String }, |
200 | |
201 | /// `#[serde(untagged)]` |
202 | /// |
203 | /// ```json |
204 | /// {"key1": "value1", "key2": "value2"} |
205 | /// ``` |
206 | None, |
207 | } |
208 | |
209 | /// Whether this enum represents the fields of a struct or the variants of an |
210 | /// enum. |
211 | #[derive (Copy, Clone)] |
212 | pub enum Identifier { |
213 | /// It does not. |
214 | No, |
215 | |
216 | /// This enum represents the fields of a struct. All of the variants must be |
217 | /// unit variants, except possibly one which is annotated with |
218 | /// `#[serde(other)]` and is a newtype variant. |
219 | Field, |
220 | |
221 | /// This enum represents the variants of an enum. All of the variants must |
222 | /// be unit variants. |
223 | Variant, |
224 | } |
225 | |
226 | impl Identifier { |
227 | #[cfg (feature = "deserialize_in_place" )] |
228 | pub fn is_some(self) -> bool { |
229 | match self { |
230 | Identifier::No => false, |
231 | Identifier::Field | Identifier::Variant => true, |
232 | } |
233 | } |
234 | } |
235 | |
236 | impl Container { |
237 | /// Extract out the `#[serde(...)]` attributes from an item. |
238 | pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { |
239 | let mut ser_name = Attr::none(cx, RENAME); |
240 | let mut de_name = Attr::none(cx, RENAME); |
241 | let mut transparent = BoolAttr::none(cx, TRANSPARENT); |
242 | let mut deny_unknown_fields = BoolAttr::none(cx, DENY_UNKNOWN_FIELDS); |
243 | let mut default = Attr::none(cx, DEFAULT); |
244 | let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); |
245 | let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); |
246 | let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS); |
247 | let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS); |
248 | let mut ser_bound = Attr::none(cx, BOUND); |
249 | let mut de_bound = Attr::none(cx, BOUND); |
250 | let mut untagged = BoolAttr::none(cx, UNTAGGED); |
251 | let mut internal_tag = Attr::none(cx, TAG); |
252 | let mut content = Attr::none(cx, CONTENT); |
253 | let mut type_from = Attr::none(cx, FROM); |
254 | let mut type_try_from = Attr::none(cx, TRY_FROM); |
255 | let mut type_into = Attr::none(cx, INTO); |
256 | let mut remote = Attr::none(cx, REMOTE); |
257 | let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER); |
258 | let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER); |
259 | let mut serde_path = Attr::none(cx, CRATE); |
260 | let mut expecting = Attr::none(cx, EXPECTING); |
261 | let mut non_exhaustive = false; |
262 | |
263 | for attr in &item.attrs { |
264 | if attr.path() != SERDE { |
265 | non_exhaustive |= |
266 | matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE); |
267 | continue; |
268 | } |
269 | |
270 | if let syn::Meta::List(meta) = &attr.meta { |
271 | if meta.tokens.is_empty() { |
272 | continue; |
273 | } |
274 | } |
275 | |
276 | if let Err(err) = attr.parse_nested_meta(|meta| { |
277 | if meta.path == RENAME { |
278 | // #[serde(rename = "foo")] |
279 | // #[serde(rename(serialize = "foo", deserialize = "bar"))] |
280 | let (ser, de) = get_renames(cx, RENAME, &meta)?; |
281 | ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); |
282 | de_name.set_opt(&meta.path, de.as_ref().map(Name::from)); |
283 | } else if meta.path == RENAME_ALL { |
284 | // #[serde(rename_all = "foo")] |
285 | // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] |
286 | let one_name = meta.input.peek(Token![=]); |
287 | let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; |
288 | if let Some(ser) = ser { |
289 | match RenameRule::from_str(&ser.value()) { |
290 | Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), |
291 | Err(err) => cx.error_spanned_by(ser, err), |
292 | } |
293 | } |
294 | if let Some(de) = de { |
295 | match RenameRule::from_str(&de.value()) { |
296 | Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), |
297 | Err(err) => { |
298 | if !one_name { |
299 | cx.error_spanned_by(de, err); |
300 | } |
301 | } |
302 | } |
303 | } |
304 | } else if meta.path == RENAME_ALL_FIELDS { |
305 | // #[serde(rename_all_fields = "foo")] |
306 | // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))] |
307 | let one_name = meta.input.peek(Token![=]); |
308 | let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?; |
309 | |
310 | match item.data { |
311 | syn::Data::Enum(_) => { |
312 | if let Some(ser) = ser { |
313 | match RenameRule::from_str(&ser.value()) { |
314 | Ok(rename_rule) => { |
315 | rename_all_fields_ser_rule.set(&meta.path, rename_rule); |
316 | } |
317 | Err(err) => cx.error_spanned_by(ser, err), |
318 | } |
319 | } |
320 | if let Some(de) = de { |
321 | match RenameRule::from_str(&de.value()) { |
322 | Ok(rename_rule) => { |
323 | rename_all_fields_de_rule.set(&meta.path, rename_rule); |
324 | } |
325 | Err(err) => { |
326 | if !one_name { |
327 | cx.error_spanned_by(de, err); |
328 | } |
329 | } |
330 | } |
331 | } |
332 | } |
333 | syn::Data::Struct(_) => { |
334 | let msg = "#[serde(rename_all_fields)] can only be used on enums" ; |
335 | cx.syn_error(meta.error(msg)); |
336 | } |
337 | syn::Data::Union(_) => { |
338 | let msg = "#[serde(rename_all_fields)] can only be used on enums" ; |
339 | cx.syn_error(meta.error(msg)); |
340 | } |
341 | } |
342 | } else if meta.path == TRANSPARENT { |
343 | // #[serde(transparent)] |
344 | transparent.set_true(meta.path); |
345 | } else if meta.path == DENY_UNKNOWN_FIELDS { |
346 | // #[serde(deny_unknown_fields)] |
347 | deny_unknown_fields.set_true(meta.path); |
348 | } else if meta.path == DEFAULT { |
349 | if meta.input.peek(Token![=]) { |
350 | // #[serde(default = "...")] |
351 | if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { |
352 | match &item.data { |
353 | syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { |
354 | syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { |
355 | default.set(&meta.path, Default::Path(path)); |
356 | } |
357 | syn::Fields::Unit => { |
358 | let msg = "#[serde(default = \"... \")] can only be used on structs that have fields" ; |
359 | cx.syn_error(meta.error(msg)); |
360 | } |
361 | }, |
362 | syn::Data::Enum(_) => { |
363 | let msg = "#[serde(default = \"... \")] can only be used on structs" ; |
364 | cx.syn_error(meta.error(msg)); |
365 | } |
366 | syn::Data::Union(_) => { |
367 | let msg = "#[serde(default = \"... \")] can only be used on structs" ; |
368 | cx.syn_error(meta.error(msg)); |
369 | } |
370 | } |
371 | } |
372 | } else { |
373 | // #[serde(default)] |
374 | match &item.data { |
375 | syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { |
376 | syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { |
377 | default.set(meta.path, Default::Default); |
378 | } |
379 | syn::Fields::Unit => { |
380 | let msg = "#[serde(default)] can only be used on structs that have fields" ; |
381 | cx.error_spanned_by(fields, msg); |
382 | } |
383 | }, |
384 | syn::Data::Enum(_) => { |
385 | let msg = "#[serde(default)] can only be used on structs" ; |
386 | cx.syn_error(meta.error(msg)); |
387 | } |
388 | syn::Data::Union(_) => { |
389 | let msg = "#[serde(default)] can only be used on structs" ; |
390 | cx.syn_error(meta.error(msg)); |
391 | } |
392 | } |
393 | } |
394 | } else if meta.path == BOUND { |
395 | // #[serde(bound = "T: SomeBound")] |
396 | // #[serde(bound(serialize = "...", deserialize = "..."))] |
397 | let (ser, de) = get_where_predicates(cx, &meta)?; |
398 | ser_bound.set_opt(&meta.path, ser); |
399 | de_bound.set_opt(&meta.path, de); |
400 | } else if meta.path == UNTAGGED { |
401 | // #[serde(untagged)] |
402 | match item.data { |
403 | syn::Data::Enum(_) => { |
404 | untagged.set_true(&meta.path); |
405 | } |
406 | syn::Data::Struct(_) => { |
407 | let msg = "#[serde(untagged)] can only be used on enums" ; |
408 | cx.syn_error(meta.error(msg)); |
409 | } |
410 | syn::Data::Union(_) => { |
411 | let msg = "#[serde(untagged)] can only be used on enums" ; |
412 | cx.syn_error(meta.error(msg)); |
413 | } |
414 | } |
415 | } else if meta.path == TAG { |
416 | // #[serde(tag = "type")] |
417 | if let Some(s) = get_lit_str(cx, TAG, &meta)? { |
418 | match &item.data { |
419 | syn::Data::Enum(_) => { |
420 | internal_tag.set(&meta.path, s.value()); |
421 | } |
422 | syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { |
423 | syn::Fields::Named(_) => { |
424 | internal_tag.set(&meta.path, s.value()); |
425 | } |
426 | syn::Fields::Unnamed(_) | syn::Fields::Unit => { |
427 | let msg = "#[serde(tag = \"... \")] can only be used on enums and structs with named fields" ; |
428 | cx.syn_error(meta.error(msg)); |
429 | } |
430 | }, |
431 | syn::Data::Union(_) => { |
432 | let msg = "#[serde(tag = \"... \")] can only be used on enums and structs with named fields" ; |
433 | cx.syn_error(meta.error(msg)); |
434 | } |
435 | } |
436 | } |
437 | } else if meta.path == CONTENT { |
438 | // #[serde(content = "c")] |
439 | if let Some(s) = get_lit_str(cx, CONTENT, &meta)? { |
440 | match &item.data { |
441 | syn::Data::Enum(_) => { |
442 | content.set(&meta.path, s.value()); |
443 | } |
444 | syn::Data::Struct(_) => { |
445 | let msg = "#[serde(content = \"... \")] can only be used on enums" ; |
446 | cx.syn_error(meta.error(msg)); |
447 | } |
448 | syn::Data::Union(_) => { |
449 | let msg = "#[serde(content = \"... \")] can only be used on enums" ; |
450 | cx.syn_error(meta.error(msg)); |
451 | } |
452 | } |
453 | } |
454 | } else if meta.path == FROM { |
455 | // #[serde(from = "Type")] |
456 | if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? { |
457 | type_from.set_opt(&meta.path, Some(from_ty)); |
458 | } |
459 | } else if meta.path == TRY_FROM { |
460 | // #[serde(try_from = "Type")] |
461 | if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? { |
462 | type_try_from.set_opt(&meta.path, Some(try_from_ty)); |
463 | } |
464 | } else if meta.path == INTO { |
465 | // #[serde(into = "Type")] |
466 | if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? { |
467 | type_into.set_opt(&meta.path, Some(into_ty)); |
468 | } |
469 | } else if meta.path == REMOTE { |
470 | // #[serde(remote = "...")] |
471 | if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? { |
472 | if is_primitive_path(&path, "Self" ) { |
473 | remote.set(&meta.path, item.ident.clone().into()); |
474 | } else { |
475 | remote.set(&meta.path, path); |
476 | } |
477 | } |
478 | } else if meta.path == FIELD_IDENTIFIER { |
479 | // #[serde(field_identifier)] |
480 | field_identifier.set_true(&meta.path); |
481 | } else if meta.path == VARIANT_IDENTIFIER { |
482 | // #[serde(variant_identifier)] |
483 | variant_identifier.set_true(&meta.path); |
484 | } else if meta.path == CRATE { |
485 | // #[serde(crate = "foo")] |
486 | if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? { |
487 | serde_path.set(&meta.path, path); |
488 | } |
489 | } else if meta.path == EXPECTING { |
490 | // #[serde(expecting = "a message")] |
491 | if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? { |
492 | expecting.set(&meta.path, s.value()); |
493 | } |
494 | } else { |
495 | let path = meta.path.to_token_stream().to_string().replace(' ' , "" ); |
496 | return Err( |
497 | meta.error(format_args!("unknown serde container attribute ` {}`" , path)) |
498 | ); |
499 | } |
500 | Ok(()) |
501 | }) { |
502 | cx.syn_error(err); |
503 | } |
504 | } |
505 | |
506 | let mut is_packed = false; |
507 | for attr in &item.attrs { |
508 | if attr.path() == REPR { |
509 | let _ = attr.parse_args_with(|input: ParseStream| { |
510 | while let Some(token) = input.parse()? { |
511 | if let TokenTree::Ident(ident) = token { |
512 | is_packed |= ident == "packed" ; |
513 | } |
514 | } |
515 | Ok(()) |
516 | }); |
517 | } |
518 | } |
519 | |
520 | Container { |
521 | name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None), |
522 | transparent: transparent.get(), |
523 | deny_unknown_fields: deny_unknown_fields.get(), |
524 | default: default.get().unwrap_or(Default::None), |
525 | rename_all_rules: RenameAllRules { |
526 | serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), |
527 | deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), |
528 | }, |
529 | rename_all_fields_rules: RenameAllRules { |
530 | serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None), |
531 | deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None), |
532 | }, |
533 | ser_bound: ser_bound.get(), |
534 | de_bound: de_bound.get(), |
535 | tag: decide_tag(cx, item, untagged, internal_tag, content), |
536 | type_from: type_from.get(), |
537 | type_try_from: type_try_from.get(), |
538 | type_into: type_into.get(), |
539 | remote: remote.get(), |
540 | identifier: decide_identifier(cx, item, field_identifier, variant_identifier), |
541 | serde_path: serde_path.get(), |
542 | is_packed, |
543 | expecting: expecting.get(), |
544 | non_exhaustive, |
545 | } |
546 | } |
547 | |
548 | pub fn name(&self) -> &MultiName { |
549 | &self.name |
550 | } |
551 | |
552 | pub fn rename_all_rules(&self) -> RenameAllRules { |
553 | self.rename_all_rules |
554 | } |
555 | |
556 | pub fn rename_all_fields_rules(&self) -> RenameAllRules { |
557 | self.rename_all_fields_rules |
558 | } |
559 | |
560 | pub fn transparent(&self) -> bool { |
561 | self.transparent |
562 | } |
563 | |
564 | pub fn deny_unknown_fields(&self) -> bool { |
565 | self.deny_unknown_fields |
566 | } |
567 | |
568 | pub fn default(&self) -> &Default { |
569 | &self.default |
570 | } |
571 | |
572 | pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { |
573 | self.ser_bound.as_ref().map(|vec| &vec[..]) |
574 | } |
575 | |
576 | pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { |
577 | self.de_bound.as_ref().map(|vec| &vec[..]) |
578 | } |
579 | |
580 | pub fn tag(&self) -> &TagType { |
581 | &self.tag |
582 | } |
583 | |
584 | pub fn type_from(&self) -> Option<&syn::Type> { |
585 | self.type_from.as_ref() |
586 | } |
587 | |
588 | pub fn type_try_from(&self) -> Option<&syn::Type> { |
589 | self.type_try_from.as_ref() |
590 | } |
591 | |
592 | pub fn type_into(&self) -> Option<&syn::Type> { |
593 | self.type_into.as_ref() |
594 | } |
595 | |
596 | pub fn remote(&self) -> Option<&syn::Path> { |
597 | self.remote.as_ref() |
598 | } |
599 | |
600 | pub fn is_packed(&self) -> bool { |
601 | self.is_packed |
602 | } |
603 | |
604 | pub fn identifier(&self) -> Identifier { |
605 | self.identifier |
606 | } |
607 | |
608 | pub fn custom_serde_path(&self) -> Option<&syn::Path> { |
609 | self.serde_path.as_ref() |
610 | } |
611 | |
612 | pub fn serde_path(&self) -> Cow<syn::Path> { |
613 | self.custom_serde_path() |
614 | .map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed) |
615 | } |
616 | |
617 | /// Error message generated when type can't be deserialized. |
618 | /// If `None`, default message will be used |
619 | pub fn expecting(&self) -> Option<&str> { |
620 | self.expecting.as_ref().map(String::as_ref) |
621 | } |
622 | |
623 | pub fn non_exhaustive(&self) -> bool { |
624 | self.non_exhaustive |
625 | } |
626 | } |
627 | |
628 | fn decide_tag( |
629 | cx: &Ctxt, |
630 | item: &syn::DeriveInput, |
631 | untagged: BoolAttr, |
632 | internal_tag: Attr<String>, |
633 | content: Attr<String>, |
634 | ) -> TagType { |
635 | match ( |
636 | untagged.0.get_with_tokens(), |
637 | internal_tag.get_with_tokens(), |
638 | content.get_with_tokens(), |
639 | ) { |
640 | (None, None, None) => TagType::External, |
641 | (Some(_), None, None) => TagType::None, |
642 | (None, Some((_, tag)), None) => { |
643 | // Check that there are no tuple variants. |
644 | if let syn::Data::Enum(data) = &item.data { |
645 | for variant in &data.variants { |
646 | match &variant.fields { |
647 | syn::Fields::Named(_) | syn::Fields::Unit => {} |
648 | syn::Fields::Unnamed(fields) => { |
649 | if fields.unnamed.len() != 1 { |
650 | let msg = |
651 | "#[serde(tag = \"... \")] cannot be used with tuple variants" ; |
652 | cx.error_spanned_by(variant, msg); |
653 | break; |
654 | } |
655 | } |
656 | } |
657 | } |
658 | } |
659 | TagType::Internal { tag } |
660 | } |
661 | (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => { |
662 | let msg = "enum cannot be both untagged and internally tagged" ; |
663 | cx.error_spanned_by(untagged_tokens, msg); |
664 | cx.error_spanned_by(tag_tokens, msg); |
665 | TagType::External // doesn't matter, will error |
666 | } |
667 | (None, None, Some((content_tokens, _))) => { |
668 | let msg = "#[serde(tag = \"... \", content = \"... \")] must be used together" ; |
669 | cx.error_spanned_by(content_tokens, msg); |
670 | TagType::External |
671 | } |
672 | (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => { |
673 | let msg = "untagged enum cannot have #[serde(content = \"... \")]" ; |
674 | cx.error_spanned_by(untagged_tokens, msg); |
675 | cx.error_spanned_by(content_tokens, msg); |
676 | TagType::External |
677 | } |
678 | (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, |
679 | (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => { |
680 | let msg = "untagged enum cannot have #[serde(tag = \"... \", content = \"... \")]" ; |
681 | cx.error_spanned_by(untagged_tokens, msg); |
682 | cx.error_spanned_by(tag_tokens, msg); |
683 | cx.error_spanned_by(content_tokens, msg); |
684 | TagType::External |
685 | } |
686 | } |
687 | } |
688 | |
689 | fn decide_identifier( |
690 | cx: &Ctxt, |
691 | item: &syn::DeriveInput, |
692 | field_identifier: BoolAttr, |
693 | variant_identifier: BoolAttr, |
694 | ) -> Identifier { |
695 | match ( |
696 | &item.data, |
697 | field_identifier.0.get_with_tokens(), |
698 | variant_identifier.0.get_with_tokens(), |
699 | ) { |
700 | (_, None, None) => Identifier::No, |
701 | (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => { |
702 | let msg = |
703 | "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set" ; |
704 | cx.error_spanned_by(field_identifier_tokens, msg); |
705 | cx.error_spanned_by(variant_identifier_tokens, msg); |
706 | Identifier::No |
707 | } |
708 | (syn::Data::Enum(_), Some(_), None) => Identifier::Field, |
709 | (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant, |
710 | (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => { |
711 | let msg = "#[serde(field_identifier)] can only be used on an enum" ; |
712 | cx.error_spanned_by(struct_token, msg); |
713 | Identifier::No |
714 | } |
715 | (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { |
716 | let msg = "#[serde(field_identifier)] can only be used on an enum" ; |
717 | cx.error_spanned_by(union_token, msg); |
718 | Identifier::No |
719 | } |
720 | (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { |
721 | let msg = "#[serde(variant_identifier)] can only be used on an enum" ; |
722 | cx.error_spanned_by(struct_token, msg); |
723 | Identifier::No |
724 | } |
725 | (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { |
726 | let msg = "#[serde(variant_identifier)] can only be used on an enum" ; |
727 | cx.error_spanned_by(union_token, msg); |
728 | Identifier::No |
729 | } |
730 | } |
731 | } |
732 | |
733 | /// Represents variant attribute information |
734 | pub struct Variant { |
735 | name: MultiName, |
736 | rename_all_rules: RenameAllRules, |
737 | ser_bound: Option<Vec<syn::WherePredicate>>, |
738 | de_bound: Option<Vec<syn::WherePredicate>>, |
739 | skip_deserializing: bool, |
740 | skip_serializing: bool, |
741 | other: bool, |
742 | serialize_with: Option<syn::ExprPath>, |
743 | deserialize_with: Option<syn::ExprPath>, |
744 | borrow: Option<BorrowAttribute>, |
745 | untagged: bool, |
746 | } |
747 | |
748 | struct BorrowAttribute { |
749 | path: syn::Path, |
750 | lifetimes: Option<BTreeSet<syn::Lifetime>>, |
751 | } |
752 | |
753 | impl Variant { |
754 | pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { |
755 | let mut ser_name = Attr::none(cx, RENAME); |
756 | let mut de_name = Attr::none(cx, RENAME); |
757 | let mut de_aliases = VecAttr::none(cx, RENAME); |
758 | let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); |
759 | let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); |
760 | let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); |
761 | let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); |
762 | let mut ser_bound = Attr::none(cx, BOUND); |
763 | let mut de_bound = Attr::none(cx, BOUND); |
764 | let mut other = BoolAttr::none(cx, OTHER); |
765 | let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); |
766 | let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); |
767 | let mut borrow = Attr::none(cx, BORROW); |
768 | let mut untagged = BoolAttr::none(cx, UNTAGGED); |
769 | |
770 | for attr in &variant.attrs { |
771 | if attr.path() != SERDE { |
772 | continue; |
773 | } |
774 | |
775 | if let syn::Meta::List(meta) = &attr.meta { |
776 | if meta.tokens.is_empty() { |
777 | continue; |
778 | } |
779 | } |
780 | |
781 | if let Err(err) = attr.parse_nested_meta(|meta| { |
782 | if meta.path == RENAME { |
783 | // #[serde(rename = "foo")] |
784 | // #[serde(rename(serialize = "foo", deserialize = "bar"))] |
785 | let (ser, de) = get_multiple_renames(cx, &meta)?; |
786 | ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); |
787 | for de_value in de { |
788 | de_name.set_if_none(Name::from(&de_value)); |
789 | de_aliases.insert(&meta.path, Name::from(&de_value)); |
790 | } |
791 | } else if meta.path == ALIAS { |
792 | // #[serde(alias = "foo")] |
793 | if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { |
794 | de_aliases.insert(&meta.path, Name::from(&s)); |
795 | } |
796 | } else if meta.path == RENAME_ALL { |
797 | // #[serde(rename_all = "foo")] |
798 | // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] |
799 | let one_name = meta.input.peek(Token![=]); |
800 | let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; |
801 | if let Some(ser) = ser { |
802 | match RenameRule::from_str(&ser.value()) { |
803 | Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), |
804 | Err(err) => cx.error_spanned_by(ser, err), |
805 | } |
806 | } |
807 | if let Some(de) = de { |
808 | match RenameRule::from_str(&de.value()) { |
809 | Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), |
810 | Err(err) => { |
811 | if !one_name { |
812 | cx.error_spanned_by(de, err); |
813 | } |
814 | } |
815 | } |
816 | } |
817 | } else if meta.path == SKIP { |
818 | // #[serde(skip)] |
819 | skip_serializing.set_true(&meta.path); |
820 | skip_deserializing.set_true(&meta.path); |
821 | } else if meta.path == SKIP_DESERIALIZING { |
822 | // #[serde(skip_deserializing)] |
823 | skip_deserializing.set_true(&meta.path); |
824 | } else if meta.path == SKIP_SERIALIZING { |
825 | // #[serde(skip_serializing)] |
826 | skip_serializing.set_true(&meta.path); |
827 | } else if meta.path == OTHER { |
828 | // #[serde(other)] |
829 | other.set_true(&meta.path); |
830 | } else if meta.path == BOUND { |
831 | // #[serde(bound = "T: SomeBound")] |
832 | // #[serde(bound(serialize = "...", deserialize = "..."))] |
833 | let (ser, de) = get_where_predicates(cx, &meta)?; |
834 | ser_bound.set_opt(&meta.path, ser); |
835 | de_bound.set_opt(&meta.path, de); |
836 | } else if meta.path == WITH { |
837 | // #[serde(with = "...")] |
838 | if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { |
839 | let mut ser_path = path.clone(); |
840 | ser_path |
841 | .path |
842 | .segments |
843 | .push(Ident::new("serialize" , ser_path.span()).into()); |
844 | serialize_with.set(&meta.path, ser_path); |
845 | let mut de_path = path; |
846 | de_path |
847 | .path |
848 | .segments |
849 | .push(Ident::new("deserialize" , de_path.span()).into()); |
850 | deserialize_with.set(&meta.path, de_path); |
851 | } |
852 | } else if meta.path == SERIALIZE_WITH { |
853 | // #[serde(serialize_with = "...")] |
854 | if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { |
855 | serialize_with.set(&meta.path, path); |
856 | } |
857 | } else if meta.path == DESERIALIZE_WITH { |
858 | // #[serde(deserialize_with = "...")] |
859 | if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { |
860 | deserialize_with.set(&meta.path, path); |
861 | } |
862 | } else if meta.path == BORROW { |
863 | let borrow_attribute = if meta.input.peek(Token![=]) { |
864 | // #[serde(borrow = "'a + 'b")] |
865 | let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; |
866 | BorrowAttribute { |
867 | path: meta.path.clone(), |
868 | lifetimes: Some(lifetimes), |
869 | } |
870 | } else { |
871 | // #[serde(borrow)] |
872 | BorrowAttribute { |
873 | path: meta.path.clone(), |
874 | lifetimes: None, |
875 | } |
876 | }; |
877 | match &variant.fields { |
878 | syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { |
879 | borrow.set(&meta.path, borrow_attribute); |
880 | } |
881 | _ => { |
882 | let msg = "#[serde(borrow)] may only be used on newtype variants" ; |
883 | cx.error_spanned_by(variant, msg); |
884 | } |
885 | } |
886 | } else if meta.path == UNTAGGED { |
887 | untagged.set_true(&meta.path); |
888 | } else { |
889 | let path = meta.path.to_token_stream().to_string().replace(' ' , "" ); |
890 | return Err( |
891 | meta.error(format_args!("unknown serde variant attribute ` {}`" , path)) |
892 | ); |
893 | } |
894 | Ok(()) |
895 | }) { |
896 | cx.syn_error(err); |
897 | } |
898 | } |
899 | |
900 | Variant { |
901 | name: MultiName::from_attrs( |
902 | Name::from(&unraw(&variant.ident)), |
903 | ser_name, |
904 | de_name, |
905 | Some(de_aliases), |
906 | ), |
907 | rename_all_rules: RenameAllRules { |
908 | serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), |
909 | deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), |
910 | }, |
911 | ser_bound: ser_bound.get(), |
912 | de_bound: de_bound.get(), |
913 | skip_deserializing: skip_deserializing.get(), |
914 | skip_serializing: skip_serializing.get(), |
915 | other: other.get(), |
916 | serialize_with: serialize_with.get(), |
917 | deserialize_with: deserialize_with.get(), |
918 | borrow: borrow.get(), |
919 | untagged: untagged.get(), |
920 | } |
921 | } |
922 | |
923 | pub fn name(&self) -> &MultiName { |
924 | &self.name |
925 | } |
926 | |
927 | pub fn aliases(&self) -> &BTreeSet<Name> { |
928 | self.name.deserialize_aliases() |
929 | } |
930 | |
931 | pub fn rename_by_rules(&mut self, rules: RenameAllRules) { |
932 | if !self.name.serialize_renamed { |
933 | self.name.serialize.value = |
934 | rules.serialize.apply_to_variant(&self.name.serialize.value); |
935 | } |
936 | if !self.name.deserialize_renamed { |
937 | self.name.deserialize.value = rules |
938 | .deserialize |
939 | .apply_to_variant(&self.name.deserialize.value); |
940 | } |
941 | self.name |
942 | .deserialize_aliases |
943 | .insert(self.name.deserialize.clone()); |
944 | } |
945 | |
946 | pub fn rename_all_rules(&self) -> RenameAllRules { |
947 | self.rename_all_rules |
948 | } |
949 | |
950 | pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { |
951 | self.ser_bound.as_ref().map(|vec| &vec[..]) |
952 | } |
953 | |
954 | pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { |
955 | self.de_bound.as_ref().map(|vec| &vec[..]) |
956 | } |
957 | |
958 | pub fn skip_deserializing(&self) -> bool { |
959 | self.skip_deserializing |
960 | } |
961 | |
962 | pub fn skip_serializing(&self) -> bool { |
963 | self.skip_serializing |
964 | } |
965 | |
966 | pub fn other(&self) -> bool { |
967 | self.other |
968 | } |
969 | |
970 | pub fn serialize_with(&self) -> Option<&syn::ExprPath> { |
971 | self.serialize_with.as_ref() |
972 | } |
973 | |
974 | pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { |
975 | self.deserialize_with.as_ref() |
976 | } |
977 | |
978 | pub fn untagged(&self) -> bool { |
979 | self.untagged |
980 | } |
981 | } |
982 | |
983 | /// Represents field attribute information |
984 | pub struct Field { |
985 | name: MultiName, |
986 | skip_serializing: bool, |
987 | skip_deserializing: bool, |
988 | skip_serializing_if: Option<syn::ExprPath>, |
989 | default: Default, |
990 | serialize_with: Option<syn::ExprPath>, |
991 | deserialize_with: Option<syn::ExprPath>, |
992 | ser_bound: Option<Vec<syn::WherePredicate>>, |
993 | de_bound: Option<Vec<syn::WherePredicate>>, |
994 | borrowed_lifetimes: BTreeSet<syn::Lifetime>, |
995 | getter: Option<syn::ExprPath>, |
996 | flatten: bool, |
997 | transparent: bool, |
998 | } |
999 | |
1000 | /// Represents the default to use for a field when deserializing. |
1001 | pub enum Default { |
1002 | /// Field must always be specified because it does not have a default. |
1003 | None, |
1004 | /// The default is given by `std::default::Default::default()`. |
1005 | Default, |
1006 | /// The default is given by this function. |
1007 | Path(syn::ExprPath), |
1008 | } |
1009 | |
1010 | impl Default { |
1011 | pub fn is_none(&self) -> bool { |
1012 | match self { |
1013 | Default::None => true, |
1014 | Default::Default | Default::Path(_) => false, |
1015 | } |
1016 | } |
1017 | } |
1018 | |
1019 | impl Field { |
1020 | /// Extract out the `#[serde(...)]` attributes from a struct field. |
1021 | pub fn from_ast( |
1022 | cx: &Ctxt, |
1023 | index: usize, |
1024 | field: &syn::Field, |
1025 | attrs: Option<&Variant>, |
1026 | container_default: &Default, |
1027 | ) -> Self { |
1028 | let mut ser_name = Attr::none(cx, RENAME); |
1029 | let mut de_name = Attr::none(cx, RENAME); |
1030 | let mut de_aliases = VecAttr::none(cx, RENAME); |
1031 | let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); |
1032 | let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); |
1033 | let mut skip_serializing_if = Attr::none(cx, SKIP_SERIALIZING_IF); |
1034 | let mut default = Attr::none(cx, DEFAULT); |
1035 | let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); |
1036 | let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); |
1037 | let mut ser_bound = Attr::none(cx, BOUND); |
1038 | let mut de_bound = Attr::none(cx, BOUND); |
1039 | let mut borrowed_lifetimes = Attr::none(cx, BORROW); |
1040 | let mut getter = Attr::none(cx, GETTER); |
1041 | let mut flatten = BoolAttr::none(cx, FLATTEN); |
1042 | |
1043 | let ident = match &field.ident { |
1044 | Some(ident) => Name::from(&unraw(ident)), |
1045 | None => Name { |
1046 | value: index.to_string(), |
1047 | span: Span::call_site(), |
1048 | }, |
1049 | }; |
1050 | |
1051 | if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { |
1052 | if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { |
1053 | if let Some(lifetimes) = &borrow_attribute.lifetimes { |
1054 | for lifetime in lifetimes { |
1055 | if !borrowable.contains(lifetime) { |
1056 | let msg = |
1057 | format!("field ` {}` does not have lifetime {}" , ident, lifetime); |
1058 | cx.error_spanned_by(field, msg); |
1059 | } |
1060 | } |
1061 | borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone()); |
1062 | } else { |
1063 | borrowed_lifetimes.set(&borrow_attribute.path, borrowable); |
1064 | } |
1065 | } |
1066 | } |
1067 | |
1068 | for attr in &field.attrs { |
1069 | if attr.path() != SERDE { |
1070 | continue; |
1071 | } |
1072 | |
1073 | if let syn::Meta::List(meta) = &attr.meta { |
1074 | if meta.tokens.is_empty() { |
1075 | continue; |
1076 | } |
1077 | } |
1078 | |
1079 | if let Err(err) = attr.parse_nested_meta(|meta| { |
1080 | if meta.path == RENAME { |
1081 | // #[serde(rename = "foo")] |
1082 | // #[serde(rename(serialize = "foo", deserialize = "bar"))] |
1083 | let (ser, de) = get_multiple_renames(cx, &meta)?; |
1084 | ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); |
1085 | for de_value in de { |
1086 | de_name.set_if_none(Name::from(&de_value)); |
1087 | de_aliases.insert(&meta.path, Name::from(&de_value)); |
1088 | } |
1089 | } else if meta.path == ALIAS { |
1090 | // #[serde(alias = "foo")] |
1091 | if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { |
1092 | de_aliases.insert(&meta.path, Name::from(&s)); |
1093 | } |
1094 | } else if meta.path == DEFAULT { |
1095 | if meta.input.peek(Token![=]) { |
1096 | // #[serde(default = "...")] |
1097 | if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { |
1098 | default.set(&meta.path, Default::Path(path)); |
1099 | } |
1100 | } else { |
1101 | // #[serde(default)] |
1102 | default.set(&meta.path, Default::Default); |
1103 | } |
1104 | } else if meta.path == SKIP_SERIALIZING { |
1105 | // #[serde(skip_serializing)] |
1106 | skip_serializing.set_true(&meta.path); |
1107 | } else if meta.path == SKIP_DESERIALIZING { |
1108 | // #[serde(skip_deserializing)] |
1109 | skip_deserializing.set_true(&meta.path); |
1110 | } else if meta.path == SKIP { |
1111 | // #[serde(skip)] |
1112 | skip_serializing.set_true(&meta.path); |
1113 | skip_deserializing.set_true(&meta.path); |
1114 | } else if meta.path == SKIP_SERIALIZING_IF { |
1115 | // #[serde(skip_serializing_if = "...")] |
1116 | if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? { |
1117 | skip_serializing_if.set(&meta.path, path); |
1118 | } |
1119 | } else if meta.path == SERIALIZE_WITH { |
1120 | // #[serde(serialize_with = "...")] |
1121 | if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { |
1122 | serialize_with.set(&meta.path, path); |
1123 | } |
1124 | } else if meta.path == DESERIALIZE_WITH { |
1125 | // #[serde(deserialize_with = "...")] |
1126 | if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { |
1127 | deserialize_with.set(&meta.path, path); |
1128 | } |
1129 | } else if meta.path == WITH { |
1130 | // #[serde(with = "...")] |
1131 | if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { |
1132 | let mut ser_path = path.clone(); |
1133 | ser_path |
1134 | .path |
1135 | .segments |
1136 | .push(Ident::new("serialize" , ser_path.span()).into()); |
1137 | serialize_with.set(&meta.path, ser_path); |
1138 | let mut de_path = path; |
1139 | de_path |
1140 | .path |
1141 | .segments |
1142 | .push(Ident::new("deserialize" , de_path.span()).into()); |
1143 | deserialize_with.set(&meta.path, de_path); |
1144 | } |
1145 | } else if meta.path == BOUND { |
1146 | // #[serde(bound = "T: SomeBound")] |
1147 | // #[serde(bound(serialize = "...", deserialize = "..."))] |
1148 | let (ser, de) = get_where_predicates(cx, &meta)?; |
1149 | ser_bound.set_opt(&meta.path, ser); |
1150 | de_bound.set_opt(&meta.path, de); |
1151 | } else if meta.path == BORROW { |
1152 | if meta.input.peek(Token![=]) { |
1153 | // #[serde(borrow = "'a + 'b")] |
1154 | let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; |
1155 | if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { |
1156 | for lifetime in &lifetimes { |
1157 | if !borrowable.contains(lifetime) { |
1158 | let msg = format!( |
1159 | "field ` {}` does not have lifetime {}" , |
1160 | ident, lifetime, |
1161 | ); |
1162 | cx.error_spanned_by(field, msg); |
1163 | } |
1164 | } |
1165 | borrowed_lifetimes.set(&meta.path, lifetimes); |
1166 | } |
1167 | } else { |
1168 | // #[serde(borrow)] |
1169 | if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { |
1170 | borrowed_lifetimes.set(&meta.path, borrowable); |
1171 | } |
1172 | } |
1173 | } else if meta.path == GETTER { |
1174 | // #[serde(getter = "...")] |
1175 | if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? { |
1176 | getter.set(&meta.path, path); |
1177 | } |
1178 | } else if meta.path == FLATTEN { |
1179 | // #[serde(flatten)] |
1180 | flatten.set_true(&meta.path); |
1181 | } else { |
1182 | let path = meta.path.to_token_stream().to_string().replace(' ' , "" ); |
1183 | return Err( |
1184 | meta.error(format_args!("unknown serde field attribute ` {}`" , path)) |
1185 | ); |
1186 | } |
1187 | Ok(()) |
1188 | }) { |
1189 | cx.syn_error(err); |
1190 | } |
1191 | } |
1192 | |
1193 | // Is skip_deserializing, initialize the field to Default::default() unless a |
1194 | // different default is specified by `#[serde(default = "...")]` on |
1195 | // ourselves or our container (e.g. the struct we are in). |
1196 | if let Default::None = *container_default { |
1197 | if skip_deserializing.0.value.is_some() { |
1198 | default.set_if_none(Default::Default); |
1199 | } |
1200 | } |
1201 | |
1202 | let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default(); |
1203 | if !borrowed_lifetimes.is_empty() { |
1204 | // Cow<str> and Cow<[u8]> never borrow by default: |
1205 | // |
1206 | // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> |
1207 | // |
1208 | // A #[serde(borrow)] attribute enables borrowing that corresponds |
1209 | // roughly to these impls: |
1210 | // |
1211 | // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str> |
1212 | // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> |
1213 | if is_cow(&field.ty, is_str) { |
1214 | let mut path = syn::Path { |
1215 | leading_colon: None, |
1216 | segments: Punctuated::new(), |
1217 | }; |
1218 | let span = Span::call_site(); |
1219 | path.segments.push(Ident::new("_serde" , span).into()); |
1220 | path.segments.push(Ident::new("__private" , span).into()); |
1221 | path.segments.push(Ident::new("de" , span).into()); |
1222 | path.segments |
1223 | .push(Ident::new("borrow_cow_str" , span).into()); |
1224 | let expr = syn::ExprPath { |
1225 | attrs: Vec::new(), |
1226 | qself: None, |
1227 | path, |
1228 | }; |
1229 | deserialize_with.set_if_none(expr); |
1230 | } else if is_cow(&field.ty, is_slice_u8) { |
1231 | let mut path = syn::Path { |
1232 | leading_colon: None, |
1233 | segments: Punctuated::new(), |
1234 | }; |
1235 | let span = Span::call_site(); |
1236 | path.segments.push(Ident::new("_serde" , span).into()); |
1237 | path.segments.push(Ident::new("__private" , span).into()); |
1238 | path.segments.push(Ident::new("de" , span).into()); |
1239 | path.segments |
1240 | .push(Ident::new("borrow_cow_bytes" , span).into()); |
1241 | let expr = syn::ExprPath { |
1242 | attrs: Vec::new(), |
1243 | qself: None, |
1244 | path, |
1245 | }; |
1246 | deserialize_with.set_if_none(expr); |
1247 | } |
1248 | } else if is_implicitly_borrowed(&field.ty) { |
1249 | // Types &str and &[u8] are always implicitly borrowed. No need for |
1250 | // a #[serde(borrow)]. |
1251 | collect_lifetimes(&field.ty, &mut borrowed_lifetimes); |
1252 | } |
1253 | |
1254 | Field { |
1255 | name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)), |
1256 | skip_serializing: skip_serializing.get(), |
1257 | skip_deserializing: skip_deserializing.get(), |
1258 | skip_serializing_if: skip_serializing_if.get(), |
1259 | default: default.get().unwrap_or(Default::None), |
1260 | serialize_with: serialize_with.get(), |
1261 | deserialize_with: deserialize_with.get(), |
1262 | ser_bound: ser_bound.get(), |
1263 | de_bound: de_bound.get(), |
1264 | borrowed_lifetimes, |
1265 | getter: getter.get(), |
1266 | flatten: flatten.get(), |
1267 | transparent: false, |
1268 | } |
1269 | } |
1270 | |
1271 | pub fn name(&self) -> &MultiName { |
1272 | &self.name |
1273 | } |
1274 | |
1275 | pub fn aliases(&self) -> &BTreeSet<Name> { |
1276 | self.name.deserialize_aliases() |
1277 | } |
1278 | |
1279 | pub fn rename_by_rules(&mut self, rules: RenameAllRules) { |
1280 | if !self.name.serialize_renamed { |
1281 | self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value); |
1282 | } |
1283 | if !self.name.deserialize_renamed { |
1284 | self.name.deserialize.value = rules |
1285 | .deserialize |
1286 | .apply_to_field(&self.name.deserialize.value); |
1287 | } |
1288 | self.name |
1289 | .deserialize_aliases |
1290 | .insert(self.name.deserialize.clone()); |
1291 | } |
1292 | |
1293 | pub fn skip_serializing(&self) -> bool { |
1294 | self.skip_serializing |
1295 | } |
1296 | |
1297 | pub fn skip_deserializing(&self) -> bool { |
1298 | self.skip_deserializing |
1299 | } |
1300 | |
1301 | pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> { |
1302 | self.skip_serializing_if.as_ref() |
1303 | } |
1304 | |
1305 | pub fn default(&self) -> &Default { |
1306 | &self.default |
1307 | } |
1308 | |
1309 | pub fn serialize_with(&self) -> Option<&syn::ExprPath> { |
1310 | self.serialize_with.as_ref() |
1311 | } |
1312 | |
1313 | pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { |
1314 | self.deserialize_with.as_ref() |
1315 | } |
1316 | |
1317 | pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { |
1318 | self.ser_bound.as_ref().map(|vec| &vec[..]) |
1319 | } |
1320 | |
1321 | pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { |
1322 | self.de_bound.as_ref().map(|vec| &vec[..]) |
1323 | } |
1324 | |
1325 | pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> { |
1326 | &self.borrowed_lifetimes |
1327 | } |
1328 | |
1329 | pub fn getter(&self) -> Option<&syn::ExprPath> { |
1330 | self.getter.as_ref() |
1331 | } |
1332 | |
1333 | pub fn flatten(&self) -> bool { |
1334 | self.flatten |
1335 | } |
1336 | |
1337 | pub fn transparent(&self) -> bool { |
1338 | self.transparent |
1339 | } |
1340 | |
1341 | pub fn mark_transparent(&mut self) { |
1342 | self.transparent = true; |
1343 | } |
1344 | } |
1345 | |
1346 | type SerAndDe<T> = (Option<T>, Option<T>); |
1347 | |
1348 | fn get_ser_and_de<'c, T, F, R>( |
1349 | cx: &'c Ctxt, |
1350 | attr_name: Symbol, |
1351 | meta: &ParseNestedMeta, |
1352 | f: F, |
1353 | ) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)> |
1354 | where |
1355 | T: Clone, |
1356 | F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result<R>, |
1357 | R: Into<Option<T>>, |
1358 | { |
1359 | let mut ser_meta = VecAttr::none(cx, attr_name); |
1360 | let mut de_meta = VecAttr::none(cx, attr_name); |
1361 | |
1362 | let lookahead = meta.input.lookahead1(); |
1363 | if lookahead.peek(Token![=]) { |
1364 | if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() { |
1365 | ser_meta.insert(&meta.path, both.clone()); |
1366 | de_meta.insert(&meta.path, both); |
1367 | } |
1368 | } else if lookahead.peek(token::Paren) { |
1369 | meta.parse_nested_meta(|meta| { |
1370 | if meta.path == SERIALIZE { |
1371 | if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() { |
1372 | ser_meta.insert(&meta.path, v); |
1373 | } |
1374 | } else if meta.path == DESERIALIZE { |
1375 | if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() { |
1376 | de_meta.insert(&meta.path, v); |
1377 | } |
1378 | } else { |
1379 | return Err(meta.error(format_args!( |
1380 | "malformed {0} attribute, expected ` {0}(serialize = ..., deserialize = ...)`" , |
1381 | attr_name, |
1382 | ))); |
1383 | } |
1384 | Ok(()) |
1385 | })?; |
1386 | } else { |
1387 | return Err(lookahead.error()); |
1388 | } |
1389 | |
1390 | Ok((ser_meta, de_meta)) |
1391 | } |
1392 | |
1393 | fn get_renames( |
1394 | cx: &Ctxt, |
1395 | attr_name: Symbol, |
1396 | meta: &ParseNestedMeta, |
1397 | ) -> syn::Result<SerAndDe<syn::LitStr>> { |
1398 | let (ser: VecAttr<'_, LitStr>, de: VecAttr<'_, LitStr>) = get_ser_and_de(cx, attr_name, meta, f:get_lit_str2)?; |
1399 | Ok((ser.at_most_one(), de.at_most_one())) |
1400 | } |
1401 | |
1402 | fn get_multiple_renames( |
1403 | cx: &Ctxt, |
1404 | meta: &ParseNestedMeta, |
1405 | ) -> syn::Result<(Option<syn::LitStr>, Vec<syn::LitStr>)> { |
1406 | let (ser: VecAttr<'_, LitStr>, de: VecAttr<'_, LitStr>) = get_ser_and_de(cx, RENAME, meta, f:get_lit_str2)?; |
1407 | Ok((ser.at_most_one(), de.get())) |
1408 | } |
1409 | |
1410 | fn get_where_predicates( |
1411 | cx: &Ctxt, |
1412 | meta: &ParseNestedMeta, |
1413 | ) -> syn::Result<SerAndDe<Vec<syn::WherePredicate>>> { |
1414 | let (ser: VecAttr<'_, Vec>, de: VecAttr<'_, Vec>) = get_ser_and_de(cx, BOUND, meta, f:parse_lit_into_where)?; |
1415 | Ok((ser.at_most_one(), de.at_most_one())) |
1416 | } |
1417 | |
1418 | fn get_lit_str( |
1419 | cx: &Ctxt, |
1420 | attr_name: Symbol, |
1421 | meta: &ParseNestedMeta, |
1422 | ) -> syn::Result<Option<syn::LitStr>> { |
1423 | get_lit_str2(cx, attr_name, meta_item_name:attr_name, meta) |
1424 | } |
1425 | |
1426 | fn get_lit_str2( |
1427 | cx: &Ctxt, |
1428 | attr_name: Symbol, |
1429 | meta_item_name: Symbol, |
1430 | meta: &ParseNestedMeta, |
1431 | ) -> syn::Result<Option<syn::LitStr>> { |
1432 | let expr: syn::Expr = meta.value()?.parse()?; |
1433 | let mut value = &expr; |
1434 | while let syn::Expr::Group(e) = value { |
1435 | value = &e.expr; |
1436 | } |
1437 | if let syn::Expr::Lit(syn::ExprLit { |
1438 | lit: syn::Lit::Str(lit), |
1439 | .. |
1440 | }) = value |
1441 | { |
1442 | let suffix = lit.suffix(); |
1443 | if !suffix.is_empty() { |
1444 | cx.error_spanned_by( |
1445 | lit, |
1446 | format!("unexpected suffix ` {}` on string literal" , suffix), |
1447 | ); |
1448 | } |
1449 | Ok(Some(lit.clone())) |
1450 | } else { |
1451 | cx.error_spanned_by( |
1452 | expr, |
1453 | format!( |
1454 | "expected serde {} attribute to be a string: ` {} = \"... \"`" , |
1455 | attr_name, meta_item_name |
1456 | ), |
1457 | ); |
1458 | Ok(None) |
1459 | } |
1460 | } |
1461 | |
1462 | fn parse_lit_into_path( |
1463 | cx: &Ctxt, |
1464 | attr_name: Symbol, |
1465 | meta: &ParseNestedMeta, |
1466 | ) -> syn::Result<Option<syn::Path>> { |
1467 | let string: LitStr = match get_lit_str(cx, attr_name, meta)? { |
1468 | Some(string: LitStr) => string, |
1469 | None => return Ok(None), |
1470 | }; |
1471 | |
1472 | Ok(match string.parse() { |
1473 | Ok(path: Path) => Some(path), |
1474 | Err(_) => { |
1475 | cx.error_spanned_by( |
1476 | &string, |
1477 | msg:format!("failed to parse path: {:?}" , string.value()), |
1478 | ); |
1479 | None |
1480 | } |
1481 | }) |
1482 | } |
1483 | |
1484 | fn parse_lit_into_expr_path( |
1485 | cx: &Ctxt, |
1486 | attr_name: Symbol, |
1487 | meta: &ParseNestedMeta, |
1488 | ) -> syn::Result<Option<syn::ExprPath>> { |
1489 | let string: LitStr = match get_lit_str(cx, attr_name, meta)? { |
1490 | Some(string: LitStr) => string, |
1491 | None => return Ok(None), |
1492 | }; |
1493 | |
1494 | Ok(match string.parse() { |
1495 | Ok(expr: ExprPath) => Some(expr), |
1496 | Err(_) => { |
1497 | cx.error_spanned_by( |
1498 | &string, |
1499 | msg:format!("failed to parse path: {:?}" , string.value()), |
1500 | ); |
1501 | None |
1502 | } |
1503 | }) |
1504 | } |
1505 | |
1506 | fn parse_lit_into_where( |
1507 | cx: &Ctxt, |
1508 | attr_name: Symbol, |
1509 | meta_item_name: Symbol, |
1510 | meta: &ParseNestedMeta, |
1511 | ) -> syn::Result<Vec<syn::WherePredicate>> { |
1512 | let string: LitStr = match get_lit_str2(cx, attr_name, meta_item_name, meta)? { |
1513 | Some(string: LitStr) => string, |
1514 | None => return Ok(Vec::new()), |
1515 | }; |
1516 | |
1517 | Ok( |
1518 | match string.parse_with(parser:Punctuated::<syn::WherePredicate, Token![,]>::parse_terminated) { |
1519 | Ok(predicates: Punctuated) => Vec::from_iter(predicates), |
1520 | Err(err: Error) => { |
1521 | cx.error_spanned_by(obj:string, msg:err); |
1522 | Vec::new() |
1523 | } |
1524 | }, |
1525 | ) |
1526 | } |
1527 | |
1528 | fn parse_lit_into_ty( |
1529 | cx: &Ctxt, |
1530 | attr_name: Symbol, |
1531 | meta: &ParseNestedMeta, |
1532 | ) -> syn::Result<Option<syn::Type>> { |
1533 | let string: LitStr = match get_lit_str(cx, attr_name, meta)? { |
1534 | Some(string: LitStr) => string, |
1535 | None => return Ok(None), |
1536 | }; |
1537 | |
1538 | Ok(match string.parse() { |
1539 | Ok(ty: Type) => Some(ty), |
1540 | Err(_) => { |
1541 | cx.error_spanned_by( |
1542 | &string, |
1543 | msg:format!("failed to parse type: {} = {:?}" , attr_name, string.value()), |
1544 | ); |
1545 | None |
1546 | } |
1547 | }) |
1548 | } |
1549 | |
1550 | // Parses a string literal like "'a + 'b + 'c" containing a nonempty list of |
1551 | // lifetimes separated by `+`. |
1552 | fn parse_lit_into_lifetimes( |
1553 | cx: &Ctxt, |
1554 | meta: &ParseNestedMeta, |
1555 | ) -> syn::Result<BTreeSet<syn::Lifetime>> { |
1556 | let string = match get_lit_str(cx, BORROW, meta)? { |
1557 | Some(string) => string, |
1558 | None => return Ok(BTreeSet::new()), |
1559 | }; |
1560 | |
1561 | if let Ok(lifetimes) = string.parse_with(|input: ParseStream| { |
1562 | let mut set = BTreeSet::new(); |
1563 | while !input.is_empty() { |
1564 | let lifetime: Lifetime = input.parse()?; |
1565 | if !set.insert(lifetime.clone()) { |
1566 | cx.error_spanned_by( |
1567 | &string, |
1568 | format!("duplicate borrowed lifetime ` {}`" , lifetime), |
1569 | ); |
1570 | } |
1571 | if input.is_empty() { |
1572 | break; |
1573 | } |
1574 | input.parse::<Token![+]>()?; |
1575 | } |
1576 | Ok(set) |
1577 | }) { |
1578 | if lifetimes.is_empty() { |
1579 | cx.error_spanned_by(string, "at least one lifetime must be borrowed" ); |
1580 | } |
1581 | return Ok(lifetimes); |
1582 | } |
1583 | |
1584 | cx.error_spanned_by( |
1585 | &string, |
1586 | format!("failed to parse borrowed lifetimes: {:?}" , string.value()), |
1587 | ); |
1588 | Ok(BTreeSet::new()) |
1589 | } |
1590 | |
1591 | fn is_implicitly_borrowed(ty: &syn::Type) -> bool { |
1592 | is_implicitly_borrowed_reference(ty) || is_option(ty, elem:is_implicitly_borrowed_reference) |
1593 | } |
1594 | |
1595 | fn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool { |
1596 | is_reference(ty, elem:is_str) || is_reference(ty, elem:is_slice_u8) |
1597 | } |
1598 | |
1599 | // Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T". |
1600 | // This can have false negatives and false positives. |
1601 | // |
1602 | // False negative: |
1603 | // |
1604 | // use std::borrow::Cow as Pig; |
1605 | // |
1606 | // #[derive(Deserialize)] |
1607 | // struct S<'a> { |
1608 | // #[serde(borrow)] |
1609 | // pig: Pig<'a, str>, |
1610 | // } |
1611 | // |
1612 | // False positive: |
1613 | // |
1614 | // type str = [i16]; |
1615 | // |
1616 | // #[derive(Deserialize)] |
1617 | // struct S<'a> { |
1618 | // #[serde(borrow)] |
1619 | // cow: Cow<'a, str>, |
1620 | // } |
1621 | fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { |
1622 | let path = match ungroup(ty) { |
1623 | syn::Type::Path(ty) => &ty.path, |
1624 | _ => { |
1625 | return false; |
1626 | } |
1627 | }; |
1628 | let seg = match path.segments.last() { |
1629 | Some(seg) => seg, |
1630 | None => { |
1631 | return false; |
1632 | } |
1633 | }; |
1634 | let args = match &seg.arguments { |
1635 | syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, |
1636 | _ => { |
1637 | return false; |
1638 | } |
1639 | }; |
1640 | seg.ident == "Cow" |
1641 | && args.len() == 2 |
1642 | && match (&args[0], &args[1]) { |
1643 | (syn::GenericArgument::Lifetime(_), syn::GenericArgument::Type(arg)) => elem(arg), |
1644 | _ => false, |
1645 | } |
1646 | } |
1647 | |
1648 | fn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { |
1649 | let path = match ungroup(ty) { |
1650 | syn::Type::Path(ty) => &ty.path, |
1651 | _ => { |
1652 | return false; |
1653 | } |
1654 | }; |
1655 | let seg = match path.segments.last() { |
1656 | Some(seg) => seg, |
1657 | None => { |
1658 | return false; |
1659 | } |
1660 | }; |
1661 | let args = match &seg.arguments { |
1662 | syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, |
1663 | _ => { |
1664 | return false; |
1665 | } |
1666 | }; |
1667 | seg.ident == "Option" |
1668 | && args.len() == 1 |
1669 | && match &args[0] { |
1670 | syn::GenericArgument::Type(arg) => elem(arg), |
1671 | _ => false, |
1672 | } |
1673 | } |
1674 | |
1675 | // Whether the type looks like it might be `&T` where elem="T". This can have |
1676 | // false negatives and false positives. |
1677 | // |
1678 | // False negative: |
1679 | // |
1680 | // type Yarn = str; |
1681 | // |
1682 | // #[derive(Deserialize)] |
1683 | // struct S<'a> { |
1684 | // r: &'a Yarn, |
1685 | // } |
1686 | // |
1687 | // False positive: |
1688 | // |
1689 | // type str = [i16]; |
1690 | // |
1691 | // #[derive(Deserialize)] |
1692 | // struct S<'a> { |
1693 | // r: &'a str, |
1694 | // } |
1695 | fn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { |
1696 | match ungroup(ty) { |
1697 | syn::Type::Reference(ty: &TypeReference) => ty.mutability.is_none() && elem(&ty.elem), |
1698 | _ => false, |
1699 | } |
1700 | } |
1701 | |
1702 | fn is_str(ty: &syn::Type) -> bool { |
1703 | is_primitive_type(ty, primitive:"str" ) |
1704 | } |
1705 | |
1706 | fn is_slice_u8(ty: &syn::Type) -> bool { |
1707 | match ungroup(ty) { |
1708 | syn::Type::Slice(ty: &TypeSlice) => is_primitive_type(&ty.elem, primitive:"u8" ), |
1709 | _ => false, |
1710 | } |
1711 | } |
1712 | |
1713 | fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool { |
1714 | match ungroup(ty) { |
1715 | syn::Type::Path(ty: &TypePath) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive), |
1716 | _ => false, |
1717 | } |
1718 | } |
1719 | |
1720 | fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { |
1721 | path.leading_colon.is_none() |
1722 | && path.segments.len() == 1 |
1723 | && path.segments[0].ident == primitive |
1724 | && path.segments[0].arguments.is_empty() |
1725 | } |
1726 | |
1727 | // All lifetimes that this type could borrow from a Deserializer. |
1728 | // |
1729 | // For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand |
1730 | // a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer. |
1731 | // |
1732 | // This is used when there is an explicit or implicit `#[serde(borrow)]` |
1733 | // attribute on the field so there must be at least one borrowable lifetime. |
1734 | fn borrowable_lifetimes( |
1735 | cx: &Ctxt, |
1736 | name: &Name, |
1737 | field: &syn::Field, |
1738 | ) -> Result<BTreeSet<syn::Lifetime>, ()> { |
1739 | let mut lifetimes: BTreeSet = BTreeSet::new(); |
1740 | collect_lifetimes(&field.ty, &mut lifetimes); |
1741 | if lifetimes.is_empty() { |
1742 | let msg: String = format!("field ` {}` has no lifetimes to borrow" , name); |
1743 | cx.error_spanned_by(obj:field, msg); |
1744 | Err(()) |
1745 | } else { |
1746 | Ok(lifetimes) |
1747 | } |
1748 | } |
1749 | |
1750 | fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) { |
1751 | match ty { |
1752 | #![cfg_attr (all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] |
1753 | syn::Type::Slice(ty) => { |
1754 | collect_lifetimes(&ty.elem, out); |
1755 | } |
1756 | syn::Type::Array(ty) => { |
1757 | collect_lifetimes(&ty.elem, out); |
1758 | } |
1759 | syn::Type::Ptr(ty) => { |
1760 | collect_lifetimes(&ty.elem, out); |
1761 | } |
1762 | syn::Type::Reference(ty) => { |
1763 | out.extend(ty.lifetime.iter().cloned()); |
1764 | collect_lifetimes(&ty.elem, out); |
1765 | } |
1766 | syn::Type::Tuple(ty) => { |
1767 | for elem in &ty.elems { |
1768 | collect_lifetimes(elem, out); |
1769 | } |
1770 | } |
1771 | syn::Type::Path(ty) => { |
1772 | if let Some(qself) = &ty.qself { |
1773 | collect_lifetimes(&qself.ty, out); |
1774 | } |
1775 | for seg in &ty.path.segments { |
1776 | if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments { |
1777 | for arg in &bracketed.args { |
1778 | match arg { |
1779 | syn::GenericArgument::Lifetime(lifetime) => { |
1780 | out.insert(lifetime.clone()); |
1781 | } |
1782 | syn::GenericArgument::Type(ty) => { |
1783 | collect_lifetimes(ty, out); |
1784 | } |
1785 | syn::GenericArgument::AssocType(binding) => { |
1786 | collect_lifetimes(&binding.ty, out); |
1787 | } |
1788 | syn::GenericArgument::Const(_) |
1789 | | syn::GenericArgument::AssocConst(_) |
1790 | | syn::GenericArgument::Constraint(_) |
1791 | | _ => {} |
1792 | } |
1793 | } |
1794 | } |
1795 | } |
1796 | } |
1797 | syn::Type::Paren(ty) => { |
1798 | collect_lifetimes(&ty.elem, out); |
1799 | } |
1800 | syn::Type::Group(ty) => { |
1801 | collect_lifetimes(&ty.elem, out); |
1802 | } |
1803 | syn::Type::Macro(ty) => { |
1804 | collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out); |
1805 | } |
1806 | syn::Type::BareFn(_) |
1807 | | syn::Type::Never(_) |
1808 | | syn::Type::TraitObject(_) |
1809 | | syn::Type::ImplTrait(_) |
1810 | | syn::Type::Infer(_) |
1811 | | syn::Type::Verbatim(_) => {} |
1812 | |
1813 | _ => {} |
1814 | } |
1815 | } |
1816 | |
1817 | fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Lifetime>) { |
1818 | let mut iter: IntoIter = tokens.into_iter(); |
1819 | while let Some(tt: TokenTree) = iter.next() { |
1820 | match &tt { |
1821 | TokenTree::Punct(op: &Punct) if op.as_char() == ' \'' && op.spacing() == Spacing::Joint => { |
1822 | if let Some(TokenTree::Ident(ident: Ident)) = iter.next() { |
1823 | out.insert(syn::Lifetime { |
1824 | apostrophe: op.span(), |
1825 | ident, |
1826 | }); |
1827 | } |
1828 | } |
1829 | TokenTree::Group(group: &Group) => { |
1830 | let tokens: TokenStream = group.stream(); |
1831 | collect_lifetimes_from_tokens(tokens, out); |
1832 | } |
1833 | _ => {} |
1834 | } |
1835 | } |
1836 | } |
1837 | |