light_instruction_decoder_derive/
lib.rs

1//! Derive macros for InstructionDecoder implementations
2//!
3//! This crate provides two macros:
4//! 1. `#[derive(InstructionDecoder)]` - For instruction enums (native programs)
5//! 2. `#[instruction_decoder]` - Attribute macro for Anchor program modules
6//!
7//! The attribute macro extracts function names from the program module and generates
8//! an instruction enum with `#[derive(InstructionDecoder)]` applied.
9//!
10//! ## Enhanced InstructionDecoder for Anchor Programs
11//!
12//! The derive macro supports an enhanced mode that references Anchor-generated types
13//! for account names and parameter decoding:
14//!
15//! ```rust,ignore
16//! use light_instruction_decoder_derive::InstructionDecoder;
17//!
18//! #[derive(InstructionDecoder)]
19//! #[instruction_decoder(
20//!     program_id = "MyProgram111111111111111111111111111111111",
21//!     program_name = "My Program"
22//! )]
23//! pub enum MyInstruction {
24//!     #[instruction_decoder(accounts = CreateRecord, params = CreateRecordParams)]
25//!     CreateRecord,
26//!
27//!     #[instruction_decoder(accounts = UpdateRecord)]
28//!     UpdateRecord,
29//! }
30//! ```
31//!
32//! This generates a decoder that:
33//! - Gets account names from `<AccountsType<'_>>::ACCOUNT_NAMES`
34//! - Decodes instruction data using `ParamsType::try_from_slice()` with Debug output
35
36extern crate proc_macro;
37
38mod attribute_impl;
39mod builder;
40mod crate_context;
41mod derive_impl;
42mod parsing;
43mod utils;
44
45use proc_macro::TokenStream;
46use syn::{parse_macro_input, DeriveInput};
47
48use crate::utils::into_token_stream;
49
50/// Derives an InstructionDecoder implementation for an Anchor instruction enum.
51///
52/// This macro generates a decoder struct and InstructionDecoder trait implementation
53/// that can decode Anchor program instructions for logging purposes.
54///
55/// ## Usage
56///
57/// ```rust,ignore
58/// use light_instruction_decoder_derive::InstructionDecoder;
59///
60/// #[derive(InstructionDecoder)]
61/// #[instruction_decoder(
62///     program_id = "MyProgramId111111111111111111111111111111111",
63///     program_name = "My Program"
64/// )]
65/// pub enum MyInstruction {
66///     CreateRecord,
67///     UpdateRecord { score: u64 },
68///     DeleteRecord,
69/// }
70/// ```
71///
72/// This generates a `MyInstructionDecoder` struct that implements `InstructionDecoder`.
73#[proc_macro_derive(InstructionDecoder, attributes(instruction_decoder, discriminator))]
74pub fn derive_instruction_decoder(input: TokenStream) -> TokenStream {
75    let input = parse_macro_input!(input as DeriveInput);
76    into_token_stream(derive_impl::derive_instruction_decoder_impl(input))
77}
78
79/// Attribute macro for generating InstructionDecoder from Anchor program modules.
80///
81/// This macro extracts function names from the program module and generates
82/// an InstructionDecoder implementation automatically.
83///
84/// ## Usage
85///
86/// ```rust,ignore
87/// use light_instruction_decoder_derive::instruction_decoder;
88///
89/// #[instruction_decoder]
90/// #[program]
91/// pub mod my_program {
92///     pub fn create_record(ctx: Context<CreateRecord>) -> Result<()> { ... }
93///     pub fn update_record(ctx: Context<UpdateRecord>) -> Result<()> { ... }
94/// }
95/// ```
96///
97/// This generates a `MyProgramInstructionDecoder` struct that implements `InstructionDecoder`.
98/// The program_id can also be omitted if `declare_id!` is used inside the module.
99#[proc_macro_attribute]
100pub fn instruction_decoder(attr: TokenStream, item: TokenStream) -> TokenStream {
101    into_token_stream(attribute_impl::instruction_decoder_attr(
102        attr.into(),
103        item.into(),
104    ))
105}