#[wrap]
Expand description
Procedural macro that will decorate the incoming function with the provided context.
The context is expected to be a type that implements the SyncWrapContext
trait.
Usage example:
struct PrintDuration;
impl<T> context_manager::SyncWrapContext<T> for PrintDuration {
fn new() -> Self { Self }
}
#[wrap(PrintDuration)]
fn sync_foo<'a, T>(int_value: usize, str_ref: &'a str, generic: T) -> usize {
let type_name = std::any::type_name::<T>();
println!("Sync call with int_value={int_value}, str_ref={str_ref}, type_of(T)={type_name}");
10
}
#[wrap(PrintDuration)]
async fn async_foo<'a, T>(int_value: usize, str_ref: &'a str, generic: T) -> usize {
let type_name = std::any::type_name::<T>();
println!("Async call with int_value={int_value}, str_ref={str_ref}, type_of(T)={type_name}");
10
}
The decorator does not induce limits on the shape of the incoming function, in terms of generics, sync/async, lifetime, etc.
The decorator will expand the incoming function by adding the context handling rendering something similar to
fn sync_foo<'a, T>(int_value: usize, str_ref: &'a str, generic: T) -> usize {
PrintDuration::run_sync(CallerContext { fn_name: "sync_foo" }, move || {
let type_name = std::any::type_name::<T>();
println!("Sync call with int_value={int_value}, str_ref={str_ref}, type_of(T)={type_name}");
10
})
}
async fn async_foo<'a, T>(int_value: usize, str_ref: &'a str, generic: T) -> usize {
PrintDuration::run_async(CallerContext { fn_name: "async_foo" }, async {
let type_name = std::any::type_name::<T>();
println!("Async call with int_value={int_value}, str_ref={str_ref}, type_of(T)={type_name}");
10
}).await
}
The structuring of the generated code is though to avoid any clone/copy of data, as well as reducing the number of jumps needed to execute the original code.
§Possible compile errors
§Passing a type that does not implement SyncWrapContext
trait will lead to compile errors.
struct AsyncPrintDuration;
impl<T> context_manager::AsyncWrapContext<T> for AsyncPrintDuration {
async fn new() -> Self { Self }
}
#[wrap(AsyncPrintDuration)]
fn foo() {}
would lead to the following compile error
---- src/lib.rs - decorate (line 98) stdout ----
error[E0277]: the trait bound `AsyncPrintDuration: SyncWrapContext<_>` is not satisfied
--> src/lib.rs:106:12
|
11 | #[wrap(AsyncPrintDuration)]
| ^^^^^^^^^^^^^^^^^^ the trait `SyncWrapContext<_>` is not implemented for `AsyncPrintDuration`
|
= help: the trait `SyncWrapContext<T>` is implemented for `TraceDuration`
§Decorating a constant function
Const functions are not supported for decoration. This is a side-effect of embedding code that is not const compatible (like async blocks and closures).
struct PrintDuration;
impl<T> context_manager::SyncWrapContext<T> for PrintDuration {
fn new() -> Self { Self }
}
#[wrap(PrintDuration)]
const fn foo() {}
would lead to the following error
error: #[wrap] cannot operate on const functions
--> context_manager_macro/src/lib.rs:131:1
|
11 | #[wrap(PrintDuration)]
| ^^^^^^^^^^^^^^^^^^^^^^
|
Procedural macro that will decorate the incoming function with the provided context.
The context is expected to be a type that implements the context_manager::SyncWrapContext
trait.
More documentation available here