1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! # Postcard Bindgen
//!
//! This crate allows automatically generating javascript bindings to
//! serialize javascript objects to postcard format and vice versa.
//!
//! # Example
//!
//! This example shows how to generate a `npm` package out of the rust
//! structures. A new folder with the package name will be created. A
//! javascript file and typescript typings as well as a package.json
//! will be placed in it.
//!
//! ```rust
//! # use postcard_bindgen::{PostcardBindings, generate_bindings, build_npm_package, PackageInfo};
//! # use serde::Serialize;
//! # extern crate alloc;
//! #[derive(Serialize, PostcardBindings)]
//! struct A(u8);
//!
//! #[derive(Serialize, PostcardBindings)]
//! struct B {
//!     a: u8
//! }
//!
//! #[derive(Serialize, PostcardBindings)]
//! enum C {
//!     A,
//!     B(u8),
//!     C(A, B),
//!     D { a: &'static str, b: B },
//! }
//!
//! fn main() {
//!     build_npm_package(
//!         std::env::current_dir().unwrap().as_path(),
//!         PackageInfo {
//!             name: "test-bindings".into(),
//!             version: "0.1.0".try_into().unwrap(),
//!         },
//!         generate_bindings!(A, B, C),
//!     )
//!     .unwrap();
//! }
//! ```
//!
//! ```text
//! // JavaScript
//! import { serialize } form "test-bindings"
//!
//! const c = {
//!     tag: "C",
//!     value: [
//!         123,
//!         {
//!             a: 234
//!         }
//!     ]
//! }
//!
//! const bytes = serialize("C", c)
//! ```

#![cfg_attr(not(feature = "generating"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
mod export;
#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
mod npm_package;

#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
pub use export::export_bindings;
#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
pub use npm_package::{build_npm_package, PackageInfo, Version, VersionFromStrError};
#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
pub use postcard_bindgen_core::ExportStrings;

/// Macro to annotate structs or enums for which bindings should be generated.
///
/// For this macro to work, the [`serde::Serialize`] macro must be derived as well.
///
/// # Example
/// ```rust
/// # use serde::Serialize;
/// # use postcard_bindgen_derive::PostcardBindings;
/// #[derive(Serialize, PostcardBindings)]
/// struct Test {
///    a: u32
/// }
/// ```
pub use postcard_bindgen_derive::PostcardBindings;

#[cfg(feature = "generating")]
#[doc(hidden)]
pub mod __private {
    pub use postcard_bindgen_core::{
        gen_ts_typings, generate_js,
        registry::*,
        type_info::{GenJsBinding, JsType, ObjectMeta},
    };
}

/// Macro to generate javascript and typescript binding strings which
/// can be exported into files.
///
/// The supplied structures needs to implement the `trait` [`crate::__private::JsBindings`].
/// This `trait` is automatically implemented when deriving the
/// [`postcard_bindgen_derive::PostcardBindings`] on the types.
///
/// # Example
/// ```rust
/// # use serde::Serialize;
/// # use postcard_bindgen::{PostcardBindings, generate_bindings};
/// #[derive(Serialize, PostcardBindings)]
/// struct Test {
///     field: u8
/// }
///
/// let bindings = generate_bindings!(Test);
/// ```
#[cfg(feature = "generating")]
#[cfg_attr(docsrs, doc(cfg(feature = "generating")))]
#[macro_export]
macro_rules! generate_bindings {
    ($( $x:ty ),*) => {
        {
            let mut reg = postcard_bindgen::__private::BindingsRegistry::default();
            $(
                <$x as postcard_bindgen::__private::JsBindings>::create_bindings(&mut reg);
            )*
            let bindings = reg.into_entries();
            postcard_bindgen::ExportStrings {
                js_file: postcard_bindgen::__private::generate_js(&bindings).to_file_string().unwrap(),
                ts_file: postcard_bindgen::__private::gen_ts_typings(bindings).to_file_string().unwrap()
            }
        }
    };
}