borsh_derive/
lib.rs

1#![recursion_limit = "128"]
2#![cfg_attr(
3    feature = "force_exhaustive_checks",
4    feature(non_exhaustive_omitted_patterns_lint)
5)]
6#![allow(clippy::needless_lifetimes)]
7
8extern crate proc_macro;
9use proc_macro::TokenStream;
10#[cfg(feature = "schema")]
11use proc_macro2::Span;
12use syn::{DeriveInput, Error, ItemEnum, ItemStruct, ItemUnion, Path};
13
14///  by convention, local to borsh-derive crate, imports from proc_macro (1) are not allowed in `internals` module or in any of its submodules.
15mod internals;
16
17use crate::internals::attributes::item;
18
19#[cfg(feature = "schema")]
20use internals::schema;
21use internals::{cratename, deserialize, serialize};
22
23fn check_attrs_get_cratename(input: &TokenStream) -> Result<Path, Error> {
24    let input = input.clone();
25
26    let derive_input = syn::parse::<DeriveInput>(input)?;
27
28    item::check_attributes(&derive_input)?;
29
30    cratename::get(&derive_input.attrs)
31}
32
33/// ---
34///
35/// moved to docs of **Derive Macro** `BorshSerialize` in `borsh` crate
36#[proc_macro_derive(BorshSerialize, attributes(borsh))]
37pub fn borsh_serialize(input: TokenStream) -> TokenStream {
38    let cratename = match check_attrs_get_cratename(&input) {
39        Ok(cratename) => cratename,
40        Err(err) => {
41            return err.to_compile_error().into();
42        }
43    };
44
45    let res = if let Ok(input) = syn::parse::<ItemStruct>(input.clone()) {
46        serialize::structs::process(&input, cratename)
47    } else if let Ok(input) = syn::parse::<ItemEnum>(input.clone()) {
48        serialize::enums::process(&input, cratename)
49    } else if let Ok(input) = syn::parse::<ItemUnion>(input) {
50        serialize::unions::process(&input, cratename)
51    } else {
52        // Derive macros can only be defined on structs, enums, and unions.
53        unreachable!()
54    };
55    TokenStream::from(match res {
56        Ok(res) => res,
57        Err(err) => err.to_compile_error(),
58    })
59}
60
61/// ---
62///
63/// moved to docs of **Derive Macro** `BorshDeserialize` in `borsh` crate
64#[proc_macro_derive(BorshDeserialize, attributes(borsh))]
65pub fn borsh_deserialize(input: TokenStream) -> TokenStream {
66    let cratename = match check_attrs_get_cratename(&input) {
67        Ok(cratename) => cratename,
68        Err(err) => {
69            return err.to_compile_error().into();
70        }
71    };
72
73    let res = if let Ok(input) = syn::parse::<ItemStruct>(input.clone()) {
74        deserialize::structs::process(&input, cratename)
75    } else if let Ok(input) = syn::parse::<ItemEnum>(input.clone()) {
76        deserialize::enums::process(&input, cratename)
77    } else if let Ok(input) = syn::parse::<ItemUnion>(input) {
78        deserialize::unions::process(&input, cratename)
79    } else {
80        // Derive macros can only be defined on structs, enums, and unions.
81        unreachable!()
82    };
83    TokenStream::from(match res {
84        Ok(res) => res,
85        Err(err) => err.to_compile_error(),
86    })
87}
88
89/// ---
90///
91/// moved to docs of **Derive Macro** `BorshSchema` in `borsh` crate
92#[cfg(feature = "schema")]
93#[proc_macro_derive(BorshSchema, attributes(borsh))]
94pub fn borsh_schema(input: TokenStream) -> TokenStream {
95    let cratename = match check_attrs_get_cratename(&input) {
96        Ok(cratename) => cratename,
97        Err(err) => {
98            return err.to_compile_error().into();
99        }
100    };
101
102    let res = if let Ok(input) = syn::parse::<ItemStruct>(input.clone()) {
103        schema::structs::process(&input, cratename)
104    } else if let Ok(input) = syn::parse::<ItemEnum>(input.clone()) {
105        schema::enums::process(&input, cratename)
106    } else if syn::parse::<ItemUnion>(input).is_ok() {
107        Err(syn::Error::new(
108            Span::call_site(),
109            "Borsh schema does not support unions yet.",
110        ))
111    } else {
112        // Derive macros can only be defined on structs, enums, and unions.
113        unreachable!()
114    };
115    TokenStream::from(match res {
116        Ok(res) => res,
117        Err(err) => err.to_compile_error(),
118    })
119}