postcard_bindgen_derive/
lib.rs1use derive_enum::derive_enum;
2use derive_struct::derive_struct;
3use proc_macro2::TokenStream;
4use quote::quote;
5use serde_derive_internals::{ast, Ctxt, Derive};
6use syn::DeriveInput;
7
8mod derive_enum;
9mod derive_struct;
10
11#[proc_macro_derive(PostcardBindings)]
12pub fn postcard_bindings(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
13 derive_js_implementation(input).into()
14}
15
16fn derive_js_implementation(input: proc_macro::TokenStream) -> TokenStream {
17 let input: DeriveInput = syn::parse(input).unwrap();
18
19 let cx = Ctxt::new();
20 let container = ast::Container::from_ast(&cx, &input, Derive::Serialize).unwrap();
21
22 let body = match container.data {
23 ast::Data::Enum(variants) => derive_enum(container.ident.to_owned(), variants),
24 ast::Data::Struct(style, fields) => {
25 derive_struct(style, container.ident.to_owned(), fields)
26 }
27 };
28
29 let ident = container.ident;
30 let generics = container.generics;
31 let container_name = ident.to_string();
32
33 let expanded = if cfg!(feature = "expanding") {
34 quote!(
35 const _: () = {
36 #[allow(unused_extern_crates, clippy::useless_attribute)]
37 extern crate postcard_bindgen as _pb;
38 impl #generics _pb::__private::JsBindings for #ident #generics {
39 fn create_bindings(reg: &mut _pb::__private::BindingsRegistry) {
40 #body
41 }
42 }
43
44 impl #generics _pb::__private::GenBinding for #ident #generics {
45 fn get_type() -> _pb::__private::ValueType {
46 _pb::__private::ValueType::Object(_pb::__private::ObjectMeta {
47 name: #container_name.into(),
48 path: _pb::__private::Path::new(module_path!(), "::"),
49 })
50 }
51 }
52 };
53 )
54 } else {
55 TokenStream::new()
56 };
57
58 cx.check().unwrap();
59
60 expanded
61}