rusmpp_macros/
lib.rs

1// Do not break MSRV 1.85.1
2#![allow(clippy::collapsible_if)]
3#![allow(clippy::collapsible_match)]
4
5use proc_macro::TokenStream;
6use syn::{DeriveInput, parse_macro_input};
7
8mod container_attributes;
9mod derive;
10mod enums;
11mod parts;
12mod repr;
13mod structs;
14
15/// Implements `Length`, `Encode`, `Decode` and `TestInstance` with one default value for structs and enums.
16/// And creates parts structs for structs with `new` and `raw` methods and adds `into_parts` and `from_parts` methods to the original struct.
17///
18/// # Enums
19///
20/// ## Container attributes
21///
22/// - `#[repr(u8)]`, `#[repr(u16)]`, or `#[repr(u32)]`: Use the `From<u8>`, `From<u16>`, or `From<u32>`/`Into<u8>`, `Into<u16>`, or `Into<u32>` representation for decoding.
23/// - `#[rusmpp(decode = skip|owned|borrowed|all)]`: Control which `Decode` implementations to generate. Default is `all`.
24/// - `#[rusmpp(test = skip)]`: Skip impl `TestInstance` for the enum.
25/// - `#[rusmpp(from_into = skip)]`: Skip implementing `From<repr>` and `From<Enum>` for the enum.
26///
27/// # Structs
28///
29/// ## Container attributes
30///
31/// - `#[rusmpp(repr = "u8")]`: Use the `From<u8>`/`Into<u8>` representation for decoding.
32/// - `#[rusmpp(decode = skip|owned|borrowed|all)]`: Control which `Decode` implementations to generate. Default is `all`.
33/// - `#[rusmpp(test = skip)]`: Skip impl `TestInstance` for the struct.
34///
35/// ## Field attributes
36///
37/// - `#[rusmpp(skip_decode)]`: Skip decoding the field (requires a corresponding `new` constructor that does not take the skipped field as an argument).
38/// - `#[rusmpp(length = "unchecked")]`: Decode without length checks.
39/// - `#[rusmpp(length = "checked")]`: Decode using `length_checked_decode`.
40/// - `#[rusmpp(length = ident)]`: Use the value of another field (`ident`) as the length for decoding.
41/// - `#[rusmpp(key = ident, length = "unchecked")]`: Decode using a key and unchecked length.
42/// - `#[rusmpp(key = ident, length = ident)]`: Decode using a key and the value of another field (`ident`) as the length.
43/// - `#[rusmpp(count = ident)]`: Decode a vector of values, where `ident` is the number of elements to decode.
44///
45/// # Examples
46///
47/// See `tests/expand`.
48#[proc_macro_derive(Rusmpp, attributes(rusmpp))]
49pub fn rusmpp(input: TokenStream) -> TokenStream {
50    let input = parse_macro_input!(input as DeriveInput);
51
52    derive::rusmpp(input)
53        .unwrap_or_else(syn::Error::into_compile_error)
54        .into()
55}
56
57/// Creates a `TlvValue`-like and implements `Into<TlvValue>` and `Into<Tlv>`.
58#[proc_macro_derive(TlvValue)]
59pub fn tlv_value(input: TokenStream) -> TokenStream {
60    let input = parse_macro_input!(input as DeriveInput);
61
62    derive::tlv_value(input)
63        .unwrap_or_else(syn::Error::into_compile_error)
64        .into()
65}