cel_cxx_macros/lib.rs
1extern crate proc_macro;
2use proc_macro::TokenStream;
3
4mod opaque;
5mod symbol;
6
7#[cfg(feature = "prost")]
8mod prost_value;
9
10#[cfg(feature = "protobuf-legacy")]
11mod protobuf_legacy_value;
12
13#[cfg(feature = "protobuf")]
14mod protobuf_value;
15
16/// Derive macro for creating opaque types for cxx-cel.
17///
18/// # Attributes
19/// - `type = "..."`: The type name of the opaque type.
20/// - `display`: Generates `impl std::fmt::Display` with `Debug` trait.
21/// - `display = EXPR`: Generates `impl std::fmt::Display` with the given expression.
22/// - `crate = ...`: The crate name of the cel_cxx crate, if you are using a different crate name in Cargo.toml.
23///
24/// # Example
25///
26/// ```ignore
27/// #[derive(Opaque, Debug, Clone, PartialEq)]
28/// #[cel_cxx(type = "my_app.my_module.User")]
29/// // Generates `std::fmt::Display` impl with `Debug` trait.
30/// #[cel_cxx(display)]
31/// // or you can specify a custom format.
32/// // Generates `std::fmt::Display` impl with custom format.
33/// #[cel_cxx(display = write!(fmt, "User(id={id}, name={name})", id = self.id, name = self.name))]
34/// struct User {
35/// id: i32,
36/// name: String,
37/// email: String,
38/// }
39/// ```
40///
41///
42#[proc_macro_derive(Opaque, attributes(cel_cxx))]
43pub fn derive_opaque(input: TokenStream) -> TokenStream {
44 let input = syn::parse_macro_input!(input as syn::DeriveInput);
45 opaque::expand_derive_opaque(input)
46 .unwrap_or_else(syn::Error::into_compile_error)
47 .into()
48}
49
50/// Derive macro for prost-generated protobuf types.
51///
52/// Generates `TypedValue`, `IntoValue`, `FromValue`, `From<T>` for `Value`,
53/// and `TryFrom<Value>` implementations using prost serialization.
54///
55/// # Requirements
56///
57/// The type must implement `prost::Message` and `prost::Name`.
58/// Enable `prost::Name` generation via `.enable_type_names()` in prost-build.
59///
60/// # Attributes
61/// - `type_name = "..."`: Override the protobuf type name (default: `prost::Name::full_name()`).
62/// - `crate = ...`: Custom path to the cel_cxx crate.
63///
64/// # Setup
65///
66/// In your `build.rs`, inject the derive via `type_attribute()`:
67///
68/// ```rust,ignore
69/// // build.rs
70/// prost_build::Config::new()
71/// .enable_type_names()
72/// .type_attribute("my.package.MyMessage", "#[derive(::cel_cxx::ProstValue)]")
73/// .compile_protos(&["proto/my.proto"], &["proto/"])
74/// .unwrap();
75/// ```
76#[cfg(feature = "prost")]
77#[proc_macro_derive(ProstValue, attributes(cel_cxx))]
78pub fn derive_prost_value(input: TokenStream) -> TokenStream {
79 let input = syn::parse_macro_input!(input as syn::DeriveInput);
80 prost_value::expand_derive_prost_value(input)
81 .unwrap_or_else(syn::Error::into_compile_error)
82 .into()
83}
84
85/// Derive macro for protobuf v3 (stepancheg) generated types.
86///
87/// Generates `TypedValue`, `IntoValue`, `FromValue`, `From<T>` for `Value`,
88/// and `TryFrom<Value>` implementations using protobuf v3 serialization.
89///
90/// # Requirements
91///
92/// The type must implement `protobuf::MessageFull`.
93///
94/// # Attributes
95/// - `type_name = "..."`: Override the protobuf type name (default: from descriptor).
96/// - `crate = ...`: Custom path to the cel_cxx crate.
97///
98/// # Setup
99///
100/// In your `build.rs`, inject the derive via `customize_callback()`:
101///
102/// ```rust,ignore
103/// // build.rs
104/// use protobuf::reflect::MessageDescriptor;
105/// use protobuf_codegen::{Codegen, Customize, CustomizeCallback};
106///
107/// struct DeriveProtobufLegacyValue;
108///
109/// impl CustomizeCallback for DeriveProtobufLegacyValue {
110/// fn message(&self, _message: &MessageDescriptor) -> Customize {
111/// Customize::default().before("#[derive(::cel_cxx::ProtobufLegacyValue)]")
112/// }
113/// }
114///
115/// fn main() {
116/// Codegen::new()
117/// .cargo_out_dir("protos")
118/// .input("proto/my.proto")
119/// .include("proto/")
120/// .customize_callback(DeriveProtobufLegacyValue)
121/// .run_from_script();
122/// }
123/// ```
124#[cfg(feature = "protobuf-legacy")]
125#[proc_macro_derive(ProtobufLegacyValue, attributes(cel_cxx))]
126pub fn derive_protobuf_legacy_value(input: TokenStream) -> TokenStream {
127 let input = syn::parse_macro_input!(input as syn::DeriveInput);
128 protobuf_legacy_value::expand_derive_protobuf_legacy_value(input)
129 .unwrap_or_else(syn::Error::into_compile_error)
130 .into()
131}
132
133/// Derive macro for protobuf v4 (cpp kernel) types — **stub, not yet implemented**.
134///
135/// All generated methods will panic with `unimplemented!()`.
136///
137/// # Attributes
138/// - `type_name = "..."`: **Required.** The fully-qualified protobuf type name.
139/// - `crate = ...`: Custom path to the cel_cxx crate.
140#[cfg(feature = "protobuf")]
141#[proc_macro_derive(ProtobufValue, attributes(cel_cxx))]
142pub fn derive_protobuf_value(input: TokenStream) -> TokenStream {
143 let input = syn::parse_macro_input!(input as syn::DeriveInput);
144 protobuf_value::expand_derive_protobuf_value(input)
145 .unwrap_or_else(syn::Error::into_compile_error)
146 .into()
147}