1 unstable release
| 0.1.0 | Jul 23, 2025 |
|---|
#6 in #aop
Used in axaddrspace
25KB
245 lines
Axin
A Rust procedural macro library for function instrumentation. Axin provides the attribute procedural macro axin that enable clean separation of cross-cutting concerns such as logging, timing, validation, and resource management.
Features
- Entry & Exit Hooks: Execute functions before and after target function execution
- Decorators: Wrap functions with additional behavior using the decorator pattern
- Prologue: Insert statements directly at function entry
- Composable: Combine multiple features seamlessly
- Zero Runtime Cost: All transformations occur at compile time
Installation
Add this to your Cargo.toml:
[dependencies]
axin = "0.1.0"
Usage
Basic Example
use axin::axin;
fn setup() {
println!("Function starting");
}
fn cleanup() {
println!("Function completed");
}
#[axin(on_enter(setup), on_exit(cleanup))]
fn my_function() {
println!("Executing main logic");
}
fn main() {
my_function();
// Output:
// Function starting
// Executing main logic
// Function completed
}
Decorators
use axin::axin;
fn timing_decorator<F, R>(func: F) -> R
where
F: FnOnce() -> R,
{
let start = std::time::Instant::now();
let result = func();
println!("Execution time: {:?}", start.elapsed());
result
}
#[axin(decorator(timing_decorator))]
fn measured_function() -> i32 {
std::thread::sleep(std::time::Duration::from_millis(100));
42
}
Prologue Statements
use axin::axin;
#[axin(prologue(
println!("Initializing context");
let start_time = std::time::Instant::now();
))]
fn function_with_setup() {
println!("Main logic executed");
// start_time variable is available in this scope
}
Combined Usage
use axin::axin;
fn init() { println!("Initializing"); }
fn cleanup() { println!("Cleaning up"); }
fn monitor<F, R>(f: F) -> R where F: FnOnce() -> R {
println!("Monitoring started");
let result = f();
println!("Monitoring completed");
result
}
#[axin(
prologue(println!("Setting up context");),
on_enter(init),
decorator(monitor),
on_exit(cleanup)
)]
fn complex_function() -> String {
println!("Core logic");
"result".to_string()
}
Execution Order
When combining features, execution follows this order:
- Entry hook
- Decorator
- Prologue statements
- Original function body
- Exit hook
API Reference
Parameters Syntax
#[axin(
prologue(statement1; statement2; ...),
on_enter(function_name), // or on_enter(function_with_args("arg1", "arg2")),
decorator(decorator_function), // or decorator(parameterized_decorator(param1, param2)),
on_exit(cleanup_function) // or on_exit(cleanup_function_with_args("arg1", "arg2")),
)]
prologue(statements...)- Insert statements at function starton_enter(function)- Execute function before main functionon_enter(function_with_args("arg1", "arg2"))- Pass arguments to the entry function
on_exit(function)- Execute function after main functionon_exit(function_with_args("arg1", "arg2"))- Pass arguments to the exit function
decorator(function)- Wrap function with decoratordecorator(function_with_args("arg1", "arg2"))- Pass arguments to the decorator
All parameters are optional and can be combined in any order.
Examples
See the examples/ directory for comprehensive usage examples:
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Dependencies
~3MB
~69K SLoC