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}