Skip to main content

rust_dix_macros/
lib.rs

1//! Procedural macros for [`rust-dix`](https://docs.rs/rust-dix)
2//! (`rust-dix-macros`).
3//!
4//! This crate is an implementation detail of `rust-dix`; depend on
5//! `rust-dix`, which re-exports these macros (do not depend on this crate
6//! directly unless you have a specific reason).
7//!
8//! # Macros
9//!
10//! - [`macro@Inject`] — `#[derive(Inject)]` generates constructor injection
11//!   code from struct fields (fields marked `#[inject]`,
12//!   `#[inject(owned)]`, `#[inject(provider)]`, `#[inject(key = "...")]` or
13//!   `#[inject(owned, key = "...")]`).
14//! - [`macro@inject`] — attribute macro placed on structs or trait impls to
15//!   auto-register services with the container.
16//! - [`macro@module`] — compile-time module scan that collects
17//!   `register!()` declarations.
18//! - [`macro@register`] — function-like placeholder used inside
19//!   `#[rust_dix::module]`.
20//!
21//! # Example
22//!
23//! Illustrative only (the macros generate code that references `rust_dix`, so
24//! this proc-macro crate's doctests cannot link the core crate; the same
25//! patterns are compiled in `rust-dix`' test suite):
26//!
27//! ```rust,ignore
28//! use rust_dix::{inject, Inject};
29//! use std::sync::Arc;
30//!
31//! struct Config;
32//! trait IWorker: Send + Sync {}
33//!
34//! #[derive(Inject)]
35//! struct Worker {
36//!     #[inject]
37//!     config: Arc<Config>,
38//! }
39//!
40//! #[inject(singleton)]
41//! impl IWorker for Worker {}
42//! ```
43//!
44//! # Engineering baseline
45//!
46//! MSRV **Rust 1.95**; `#![forbid(unsafe_code)]`; errors are emitted as
47//! compile errors instead of panics where possible. See the
48//! [repository security policy](https://github.com/Rust-Framework/rust-dix/blob/main/SECURITY.md).
49
50#![forbid(unsafe_code)]
51
52use proc_macro::TokenStream;
53use quote::quote;
54use syn::parse_macro_input;
55
56mod field_init;
57mod inject_attr;
58mod inject_derive;
59mod module;
60
61// ───────────────────────────────────────────────────────────────────────────
62// #[derive(Inject)] — auto-generate constructor from struct fields
63// ───────────────────────────────────────────────────────────────────────────
64
65#[proc_macro_derive(Inject, attributes(inject))]
66pub fn inject_derive(input: TokenStream) -> TokenStream {
67    inject_derive::expand_inject_derive(parse_macro_input!(input as syn::DeriveInput))
68        .unwrap_or_else(|e| e.to_compile_error())
69        .into()
70}
71
72// ───────────────────────────────────────────────────────────────────────────
73// register!() — function-like placeholder macro for use inside #[module]
74// ───────────────────────────────────────────────────────────────────────────
75
76#[proc_macro]
77pub fn register(_: TokenStream) -> TokenStream {
78    quote! {}.into()
79}
80
81// ───────────────────────────────────────────────────────────────────────────
82// #[module] — compile-time module scanning for register!() declarations
83// ───────────────────────────────────────────────────────────────────────────
84
85#[proc_macro_attribute]
86pub fn module(_: TokenStream, item: TokenStream) -> TokenStream {
87    module::expand_md(parse_macro_input!(item as syn::ItemMod))
88        .unwrap_or_else(|e| e.to_compile_error())
89        .into()
90}
91
92// ───────────────────────────────────────────────────────────────────────────
93// #[inject] — attribute macro for auto-registration
94// ───────────────────────────────────────────────────────────────────────────
95
96#[proc_macro_attribute]
97pub fn inject(attr: TokenStream, item: TokenStream) -> TokenStream {
98    inject_attr::expand_inject(
99        parse_macro_input!(attr as inject_attr::InjectArgs),
100        parse_macro_input!(item as syn::Item),
101    )
102    .unwrap_or_else(|e| e.to_compile_error())
103    .into()
104}