borsh_derive/internals/deserialize/
mod.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use syn::{ExprPath, Generics, Ident, Path};
4
5use super::{
6    attributes::{field, BoundType},
7    generics,
8};
9
10pub mod enums;
11pub mod structs;
12pub mod unions;
13
14struct GenericsOutput {
15    overrides: Vec<syn::WherePredicate>,
16    default_visitor: generics::FindTyParams,
17    deserialize_visitor: generics::FindTyParams,
18}
19
20impl GenericsOutput {
21    fn new(generics: &Generics) -> Self {
22        Self {
23            overrides: vec![],
24            deserialize_visitor: generics::FindTyParams::new(generics),
25            default_visitor: generics::FindTyParams::new(generics),
26        }
27    }
28    fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) {
29        let de_trait: Path = syn::parse2(quote! { #cratename::de::BorshDeserialize }).unwrap();
30        let default_trait: Path = syn::parse2(quote! { core::default::Default }).unwrap();
31        let de_predicates =
32            generics::compute_predicates(self.deserialize_visitor.process_for_bounds(), &de_trait);
33        let default_predicates =
34            generics::compute_predicates(self.default_visitor.process_for_bounds(), &default_trait);
35        where_clause.predicates.extend(de_predicates);
36        where_clause.predicates.extend(default_predicates);
37        where_clause.predicates.extend(self.overrides);
38    }
39}
40
41fn process_field(
42    field: &syn::Field,
43    cratename: &Path,
44    body: &mut TokenStream2,
45    generics: &mut GenericsOutput,
46) -> syn::Result<()> {
47    let parsed = field::Attributes::parse(&field.attrs)?;
48
49    generics
50        .overrides
51        .extend(parsed.collect_bounds(BoundType::Deserialize));
52    let needs_bounds_derive = parsed.needs_bounds_derive(BoundType::Deserialize);
53
54    let field_name = field.ident.as_ref();
55    let delta = if parsed.skip {
56        if needs_bounds_derive {
57            generics.default_visitor.visit_field(field);
58        }
59        field_default_output(field_name)
60    } else {
61        if needs_bounds_derive {
62            generics.deserialize_visitor.visit_field(field);
63        }
64        field_output(field_name, cratename, parsed.deserialize_with)
65    };
66    body.extend(delta);
67    Ok(())
68}
69
70/// function which computes derive output [proc_macro2::TokenStream]
71/// of code, which deserializes single field
72fn field_output(
73    field_name: Option<&Ident>,
74    cratename: &Path,
75    deserialize_with: Option<ExprPath>,
76) -> TokenStream2 {
77    let default_path: ExprPath =
78        syn::parse2(quote! { #cratename::BorshDeserialize::deserialize_reader }).unwrap();
79    let path: ExprPath = deserialize_with.unwrap_or(default_path);
80    if let Some(field_name) = field_name {
81        quote! {
82            #field_name: #path(reader)?,
83        }
84    } else {
85        quote! {
86            #path(reader)?,
87        }
88    }
89}
90
91/// function which computes derive output [proc_macro2::TokenStream]
92/// of code, which deserializes single skipped field
93fn field_default_output(field_name: Option<&Ident>) -> TokenStream2 {
94    if let Some(field_name) = field_name {
95        quote! {
96            #field_name: core::default::Default::default(),
97        }
98    } else {
99        quote! { core::default::Default::default(), }
100    }
101}