baml_macros/lib.rs
1//! Derive macros for BAML types.
2//!
3//! This crate provides `#[derive(BamlEncode)]` and `#[derive(BamlDecode)]`
4//! macros for automatically implementing serialization to/from BAML's protobuf
5//! format.
6//!
7//! # Usage
8//!
9//! ```ignore
10//! use baml::{BamlEncode, BamlDecode};
11//!
12//! #[derive(BamlEncode, BamlDecode)]
13//! #[baml(name = "Person")] // Optional: specify BAML type name if different from Rust name
14//! struct Person {
15//! name: String,
16//! #[baml(name = "years_old")] // Optional: rename field
17//! age: i64,
18//! #[baml(skip)] // Optional: skip field (only for encode)
19//! internal_id: String,
20//! }
21//!
22//! #[derive(BamlEncode, BamlDecode)]
23//! #[baml(name = "Color")]
24//! enum Color {
25//! Red,
26//! #[baml(name = "GREEN")] // Optional: rename variant
27//! Green,
28//! Blue,
29//! }
30//! ```
31
32use proc_macro::TokenStream;
33use syn::{parse_macro_input, DeriveInput};
34
35mod decode;
36mod encode;
37mod shared;
38
39/// Derive macro for `BamlEncode` trait.
40///
41/// Generates code to encode Rust structs/enums to BAML's `HostValue` format.
42///
43/// # Attributes
44///
45/// - `#[baml(name = "...")]` on the type: Specify the BAML type name
46/// - `#[baml(name = "...")]` on a field/variant: Specify the BAML field/variant
47/// name
48/// - `#[baml(skip)]` on a field: Skip this field during encoding
49///
50/// # Example
51///
52/// ```ignore
53/// #[derive(BamlEncode)]
54/// #[baml(name = "UserInfo")]
55/// struct User {
56/// name: String,
57/// #[baml(name = "email_address")]
58/// email: String,
59/// }
60/// ```
61#[proc_macro_derive(BamlEncode, attributes(baml))]
62pub fn derive_baml_encode(input: TokenStream) -> TokenStream {
63 let input = parse_macro_input!(input as DeriveInput);
64 encode::derive_encode(&input)
65 .unwrap_or_else(|e| e.to_compile_error())
66 .into()
67}
68
69/// Derive macro for `BamlDecode` trait.
70///
71/// Generates code to decode BAML's `CffiValueHolder` format to Rust
72/// structs/enums.
73///
74/// # Attributes
75///
76/// - `#[baml(name = "...")]` on the type: Specify the BAML type name
77/// - `#[baml(name = "...")]` on a field/variant: Specify the BAML field/variant
78/// name
79///
80/// # Example
81///
82/// ```ignore
83/// #[derive(BamlDecode)]
84/// #[baml(name = "UserInfo")]
85/// struct User {
86/// name: String,
87/// #[baml(name = "email_address")]
88/// email: Option<String>,
89/// }
90/// ```
91#[proc_macro_derive(BamlDecode, attributes(baml))]
92pub fn derive_baml_decode(input: TokenStream) -> TokenStream {
93 let input = parse_macro_input!(input as DeriveInput);
94 decode::derive_decode(&input)
95 .unwrap_or_else(|e| e.to_compile_error())
96 .into()
97}