Skip to main content

mainstay_derive_serde/
lib.rs

1extern crate proc_macro;
2
3#[cfg(feature = "lazy-account")]
4mod lazy;
5
6use borsh_derive_internal::*;
7use proc_macro::TokenStream;
8use proc_macro2::{Span, TokenStream as TokenStream2};
9use syn::{Ident, Item};
10
11fn gen_borsh_serialize(input: TokenStream) -> TokenStream2 {
12    let cratename = Ident::new("borsh", Span::call_site());
13
14    let item: Item = syn::parse(input).unwrap();
15    let res = match item {
16        Item::Struct(item) => struct_ser(&item, cratename),
17        Item::Enum(item) => enum_ser(&item, cratename),
18        Item::Union(item) => union_ser(&item, cratename),
19        // Derive macros can only be defined on structs, enums, and unions.
20        _ => unreachable!(),
21    };
22
23    match res {
24        Ok(res) => res,
25        Err(err) => err.to_compile_error(),
26    }
27}
28
29#[proc_macro_derive(MainstaySerialize, attributes(borsh_skip))]
30pub fn mainstay_serialize(input: TokenStream) -> TokenStream {
31    #[cfg(not(feature = "idl-build"))]
32    let ret = gen_borsh_serialize(input);
33    #[cfg(feature = "idl-build")]
34    let ret = gen_borsh_serialize(input.clone());
35
36    #[cfg(feature = "idl-build")]
37    {
38        use mainstay_syn::idl::*;
39        use quote::quote;
40
41        let idl_build_impl = match syn::parse(input).unwrap() {
42            Item::Struct(item) => impl_idl_build_struct(&item),
43            Item::Enum(item) => impl_idl_build_enum(&item),
44            Item::Union(item) => impl_idl_build_union(&item),
45            // Derive macros can only be defined on structs, enums, and unions.
46            _ => unreachable!(),
47        };
48
49        return TokenStream::from(quote! {
50            #ret
51            #idl_build_impl
52        });
53    };
54
55    #[allow(unreachable_code)]
56    TokenStream::from(ret)
57}
58
59fn gen_borsh_deserialize(input: TokenStream) -> TokenStream2 {
60    let cratename = Ident::new("borsh", Span::call_site());
61
62    let item: Item = syn::parse(input).unwrap();
63    let res = match item {
64        Item::Struct(item) => struct_de(&item, cratename),
65        Item::Enum(item) => enum_de(&item, cratename),
66        Item::Union(item) => union_de(&item, cratename),
67        // Derive macros can only be defined on structs, enums, and unions.
68        _ => unreachable!(),
69    };
70
71    match res {
72        Ok(res) => res,
73        Err(err) => err.to_compile_error(),
74    }
75}
76
77#[proc_macro_derive(MainstayDeserialize, attributes(borsh_skip, borsh_init))]
78pub fn borsh_deserialize(input: TokenStream) -> TokenStream {
79    #[cfg(feature = "lazy-account")]
80    {
81        let deser = gen_borsh_deserialize(input.clone());
82        let lazy = lazy::gen_lazy(input).unwrap_or_else(|e| e.to_compile_error());
83        quote::quote! {
84            #deser
85            #lazy
86        }
87        .into()
88    }
89    #[cfg(not(feature = "lazy-account"))]
90    gen_borsh_deserialize(input).into()
91}
92
93#[cfg(feature = "lazy-account")]
94#[proc_macro_derive(Lazy)]
95pub fn lazy(input: TokenStream) -> TokenStream {
96    lazy::gen_lazy(input)
97        .unwrap_or_else(|e| e.to_compile_error())
98        .into()
99}