pbf_derive/
lib.rs

1use darling::{self, FromField, FromVariant};
2use proc_macro::TokenStream;
3use proc_macro2::Span;
4use proc_macro_crate::{crate_name, FoundCrate};
5use syn::{parse_macro_input, Data, DeriveInput, Ident};
6
7mod bitcast;
8mod read;
9mod write;
10
11use bitcast::expand_bitcast;
12use read::{derive_proto_read_enum, derive_proto_read_struct};
13use write::{derive_proto_write_enum, derive_proto_write_struct};
14
15#[derive(Debug, FromField, FromVariant)]
16#[darling(attributes(pbf))]
17struct FieldAttributes {
18    tag: Option<u64>,
19    #[darling(default)]
20    signed: bool,
21    #[darling(default)]
22    fixed: bool,
23    #[darling(default)]
24    nested: bool,
25    #[darling(default)]
26    ignore: bool,
27}
28
29/// Derive the `BitCast` trait for an enum.
30#[proc_macro_derive(BitCast)]
31pub fn derive_bit_cast(input: TokenStream) -> TokenStream {
32    expand_bitcast(input)
33}
34
35#[proc_macro_derive(ProtoWrite, attributes(pbf))]
36pub fn derive_proto_write(input: TokenStream) -> TokenStream {
37    let input = parse_macro_input!(input as DeriveInput);
38    let name = &input.ident;
39
40    let crate_name = match crate_name("pbf") {
41        Ok(FoundCrate::Itself) => "pbf".to_string(),
42        Ok(FoundCrate::Name(name)) => name,
43        Err(_) => "pbf_core".to_string(), // Fallback if resolution fails (happens for testing)
44    };
45    let pbf_core = Ident::new(&crate_name, Span::call_site());
46
47    match &input.data {
48        Data::Struct(data_struct) => derive_proto_write_struct(data_struct, name, &pbf_core),
49        Data::Enum(data_enum) => derive_proto_write_enum(data_enum, name, &pbf_core),
50        _ => panic!("ProtoWrite can only be derived for structs and enums"),
51    }
52}
53
54#[proc_macro_derive(ProtoRead, attributes(pbf))]
55pub fn derive_proto_read(input: TokenStream) -> TokenStream {
56    let input = parse_macro_input!(input as DeriveInput);
57    let name = &input.ident;
58
59    let crate_name = match crate_name("pbf") {
60        Ok(FoundCrate::Itself) => "pbf".to_string(),
61        Ok(FoundCrate::Name(name)) => name,
62        Err(_) => "pbf_core".to_string(), // Fallback if resolution fails (happens for testing)
63    };
64    let pbf_core = Ident::new(&crate_name, Span::call_site());
65
66    match &input.data {
67        Data::Struct(data_struct) => derive_proto_read_struct(data_struct, name, &pbf_core),
68        Data::Enum(data_enum) => derive_proto_read_enum(data_enum, name, &pbf_core),
69        _ => panic!("ProtoRead can only be derived for structs and enums"),
70    }
71}