#decorator #macro #member #wrapper #static #function #decorating

fn-decorator

该包包含实现围绕成员或静态函数的包装函数的宏。

10个稳定版本

1.3.2 2024年5月27日
1.2.1 2024年5月26日
1.1.2 2023年7月9日
1.0.1 2023年7月5日

#163过程宏

Download history 586/week @ 2024-05-25 62/week @ 2024-06-01 11/week @ 2024-06-08 2/week @ 2024-06-15 63/week @ 2024-07-27

63 每月下载量

MIT 许可证

27KB
314

fn-decorator

该包包含实现围绕成员或静态函数的包装函数的宏。

使用 use_decorator

装饰器函数

fn decorator(f: fn() -> i64) -> i64 {
    f() + 1
}

装饰函数

#[use_decorator(decorator())]
fn get_1() -> i64 {
    1
}

当调用 get_1() 时,则会执行 decorator(get_1)。装饰器函数可以决定是否调用接收到的函数。

还有一个 use_impl_decorator 宏,它可以在 impl 块中使用。

这两个宏可以有相同的参数

  • 要执行的装饰器函数调用。这可以包含参数。请参阅示例以了解确切用法!
  • hide_parameters = [...]:如果装饰器函数签名与被装饰函数不匹配,则可以使用此列表来隐藏装饰器函数的一些参数。请注意,不能同时提供 hide_parametersexact_parameters
  • exact_parameters = [...]:如果装饰器函数签名与被装饰函数不匹配,则可以使用此列表来指定要传递给装饰器函数的精确参数。请注意,不能同时提供 hide_parametersexact_parameters
  • override_return_type = <type>:如果装饰器返回类型与被装饰函数不匹配,则可以使用此列表来更改被装饰函数的返回类型
  • debug:当给出此参数时,代码将生成编译错误和生成的源代码。这有助于调试。

完整工作示例

装饰无参数函数

use fn_decorator::use_decorator;

fn decorator(f: fn() -> i64) -> i64 {
    f() + 1
}

#[use_decorator(decorator())]
fn get_1() -> i64 {
    1
}

#[test]
fn fn_without_params_decorator() {
    let result = get_1();
    assert_eq!(result, 2);
}

装饰有参数的函数

use fn_decorator::use_decorator;

fn decorator(f: fn(x: i64) -> i64, x: i64) -> i64 {
    f(x) * 2
}

#[use_decorator(decorator())]
fn double(x: i64) -> i64 {
    x * 2
}

#[test]
fn decorator_without_params() {
    let result = double(2);
    assert_eq!(result, 8);
}

使用参数化装饰器函数

use fn_decorator::use_decorator;

fn decorator(
    middle: String,
    f: fn(String, String) -> String,
    left: String,
    right: String,
) -> String {
    let left = left + &middle;
    f(left, right)
}

#[use_decorator(decorator("_middle_".to_string()))]
fn concat(left: String, right: String) -> String {
    left + &right
}

#[test]
fn decorator_with_param() {
    let result = concat("left".into(), "right".into());
    assert_eq!(result, "left_middle_right");
}

调试fn装饰器

请注意,测试中不包含此代码,因为它会产生编译时错误。

use fn_decorator::use_decorator;

fn decorator(f: fn() -> i64) -> i64 {
    f() + 1
}

#[use_decorator(decorator(), debug)]
fn get_1() -> i64 {
    1
}

#[test]
fn debug_fn_decorator() {
    let result = get_1();
    assert_eq!(result, 2);
}

装饰成员函数

use fn_decorator::use_impl_decorator;

fn decorator(f: fn(&MyStruct, y: i64) -> i64, receiver: &MyStruct, y: i64) -> i64 {
    f(receiver, y) + 1
}

struct MyStruct {
    x: i64,
}

impl MyStruct {
    #[use_impl_decorator(decorator())]
    fn add(&self, y: i64) -> i64 {
        self.x + y
    }
}

#[test]
fn impl_member_decorator() {
    let obj = MyStruct { x: 1 };
    let result = obj.add(1);
    assert_eq!(result, 3);
}

装饰静态成员函数

use fn_decorator::use_impl_decorator;

fn decorator(f: fn(x: i64) -> i64, x: i64) -> i64 {
    f(x) + 1
}

struct MyStruct;

impl MyStruct {
    #[use_impl_decorator(decorator())]
    fn double(x: i64) -> i64 {
        x * 2
    }
}

#[test]
fn impl_static_member_decorator() {
    let result = MyStruct::double(2);
    assert_eq!(result, 5);
}

装饰异步函数

use std::future::Future;

use fn_decorator::use_decorator;

async fn decorator<FutureType: Future<Output = i64>>(f: fn(x: i64) -> FutureType, x: i64) -> i64 {
    f(x).await * 2
}

#[use_decorator(decorator())]
async fn double(x: i64) -> i64 {
    x * 2
}

#[tokio::test]
async fn async_decorator() {
    let result = double(2).await;
    assert_eq!(result, 8);
}

使用异步函数指定异步装饰器的确切参数列表

use std::future::Future;

use fn_decorator::use_decorator;

async fn decorator<FutureType: Future<Output = String>>(
    middle: String,
    f: impl FnOnce(String) -> FutureType,
    right: String,
) -> String {
    let right = middle + &right;
    f(right).await
}

#[use_decorator(decorator("_middle_".to_string()), exact_parameters = [right])]
async fn concat(left: String, right: String) -> String {
    left + &right
}

#[tokio::test]
async fn hiding_params_of_async_fn_decorator() {
    let result = concat("left".into(), "right".into()).await;
    assert_eq!(result, "left_middle_right");
}

使用异步成员函数指定异步装饰器的确切参数列表

use std::future::Future;

use fn_decorator::use_impl_decorator;

async fn decorator<'a, FutureType: Future<Output = &'a String>>(
    middle: String,
    f: impl FnOnce(&'a mut MyStruct) -> FutureType,
    receiver: &'a mut MyStruct,
) -> &'a String {
    receiver.left.push_str(&middle);
    f(receiver).await
}

struct MyStruct {
    left: String,
}

impl MyStruct {
    #[use_impl_decorator(decorator("_middle_".to_string()), exact_parameters = [self])]
    async fn concat(&mut self, right: String) -> &String {
        self.left.push_str(&right);
        &self.left
    }
}

#[tokio::test]
async fn hiding_params_of_async_impl_member_decorator() {
    let mut obj = MyStruct {
        left: "left".into(),
    };
    let result = obj.concat("right".into()).await;
    assert_eq!(result, "left_middle_right");
}

使用函数指定装饰器的确切参数列表

use fn_decorator::use_decorator;

fn decorator(middle: String, f: impl FnOnce(String) -> String, right: String) -> String {
    let right = middle + &right;
    f(right)
}

#[use_decorator(decorator("_middle_".to_string()), exact_parameters = [right])]
fn concat(left: String, right: String) -> String {
    left + &right
}

#[test]
fn hiding_params_of_fn_decorator() {
    let result = concat("left".into(), "right".into());
    assert_eq!(result, "left_middle_right");
}

使用成员函数指定装饰器的确切参数列表

use fn_decorator::use_impl_decorator;

fn decorator(middle: String, f: impl FnOnce(&MyStruct) -> String, receiver: &MyStruct) -> String {
    let new_struct = MyStruct {
        left: receiver.left.clone() + &middle,
    };
    f(&new_struct)
}

struct MyStruct {
    left: String,
}

impl MyStruct {
    #[use_impl_decorator(decorator("_middle_".to_string()), exact_parameters = [self])]
    fn concat(&self, right: String) -> String {
        self.left.clone() + &right
    }
}

#[test]
fn hiding_params_of_impl_member_decorator() {
    let obj = MyStruct {
        left: "left".into(),
    };
    let result = obj.concat("right".into());
    assert_eq!(result, "left_middle_right");
}

#[test] fn hiding_self_param_in_impl_member_decorator() { let obj = MyStruct { left: "left".into(), }; let result = obj.concat("right".into()); assert_eq!(result, "left_middle_right"); }


### Hiding parameters of an async function from a decorator
```rust
use std::future::Future;

use fn_decorator::use_decorator;

async fn decorator<FutureType: Future<Output = String>>(
    middle: String,
    f: impl FnOnce(String) -> FutureType,
    right: String,
) -> String {
    let right = middle + &right;
    f(right).await
}

#[use_decorator(decorator("_middle_".to_string()), hide_parameters = [left])]
async fn concat(left: String, right: String) -> String {
    left + &right
}

#[tokio::test]
async fn hiding_params_of_async_fn_decorator() {
    let result = concat("left".into(), "right".into()).await;
    assert_eq!(result, "left_middle_right");
}

从装饰器中隐藏异步成员函数的参数

use std::future::Future;

use fn_decorator::use_impl_decorator;

async fn decorator<'a, FutureType: Future<Output = &'a String>>(
    middle: String,
    f: impl FnOnce(&'a mut MyStruct) -> FutureType,
    receiver: &'a mut MyStruct,
) -> &'a String {
    receiver.left.push_str(&middle);
    f(receiver).await
}

struct MyStruct {
    left: String,
}

impl MyStruct {
    #[use_impl_decorator(decorator("_middle_".to_string()), hide_parameters = [right])]
    async fn concat(&mut self, right: String) -> &String {
        self.left.push_str(&right);
        &self.left
    }
}

#[tokio::test]
async fn hiding_params_of_async_impl_member_decorator() {
    let mut obj = MyStruct {
        left: "left".into(),
    };
    let result = obj.concat("right".into()).await;
    assert_eq!(result, "left_middle_right");
}

从装饰器中隐藏函数的参数

use fn_decorator::use_decorator;

fn decorator(middle: String, f: impl FnOnce(String) -> String, right: String) -> String {
    let right = middle + &right;
    f(right)
}

#[use_decorator(decorator("_middle_".to_string()), hide_parameters = [left])]
fn concat(left: String, right: String) -> String {
    left + &right
}

#[test]
fn hiding_params_of_fn_decorator() {
    let result = concat("left".into(), "right".into());
    assert_eq!(result, "left_middle_right");
}

从装饰器中隐藏成员函数的参数

use fn_decorator::use_impl_decorator;

fn decorator(middle: String, f: impl FnOnce(&MyStruct) -> String, receiver: &MyStruct) -> String {
    let new_struct = MyStruct {
        left: receiver.left.clone() + &middle,
    };
    f(&new_struct)
}

struct MyStruct {
    left: String,
}

impl MyStruct {
    #[use_impl_decorator(decorator("_middle_".to_string()), hide_parameters = [right])]
    fn concat(&self, right: String) -> String {
        self.left.clone() + &right
    }
}

#[test]
fn hiding_params_of_impl_member_decorator() {
    let obj = MyStruct {
        left: "left".into(),
    };
    let result = obj.concat("right".into());
    assert_eq!(result, "left_middle_right");
}

从装饰器中隐藏成员函数的self

use fn_decorator::use_impl_decorator;

fn decorator(middle: String, f: impl FnOnce(String) -> String, right: String) -> String {
    let right = middle + &right;
    f(right)
}

struct MyStruct {
    left: String,
}

impl MyStruct {
    #[use_impl_decorator(decorator("_middle_".to_string()), hide_parameters = [self])]
    fn concat(&self, right: String) -> String {
        self.left.clone() + &right
    }
}

#[test]
fn hiding_self_param_in_impl_member_decorator() {
    let obj = MyStruct {
        left: "left".into(),
    };
    let result = obj.concat("right".into());
    assert_eq!(result, "left_middle_right");
}

装饰异步成员函数

use std::future::Future;

use fn_decorator::use_impl_decorator;

async fn decorator<'a, FutureType: Future<Output = i64>>(
    f: fn(&'a MyStruct, y: i64) -> FutureType,
    receiver: &'a MyStruct,
    y: i64,
) -> i64 {
    f(receiver, y).await + 1
}

struct MyStruct {
    x: i64,
}

impl MyStruct {
    #[use_impl_decorator(decorator())]
    async fn add(&self, y: i64) -> i64 {
        self.x + y
    }
}

#[tokio::test]
async fn async_impl_member_decorator() {
    let obj = MyStruct { x: 1 };
    let result = obj.add(1).await;
    assert_eq!(result, 3);
}

装饰异步静态成员函数

use std::future::Future;

use fn_decorator::use_impl_decorator;

async fn decorator<FutureType: Future<Output = i64>>(f: fn(y: i64) -> FutureType, x: i64) -> i64 {
    f(x).await + 1
}

struct MyStruct;

impl MyStruct {
    #[use_impl_decorator(decorator())]
    async fn double(x: i64) -> i64 {
        x * 2
    }
}

#[tokio::test]
async fn async_impl_member_decorator() {
    let result = MyStruct::double(2).await;
    assert_eq!(result, 5);
}

重写返回类型

use fn_decorator::use_decorator;

fn decorator(f: fn() -> i64) -> Result<i64, ()> {
    Ok(f() + 1)
}

#[use_decorator(decorator(), override_return_type = Result<i64, ()>)]
fn get_1() -> i64 {
    1
}

#[use_decorator(decorator(), override_return_type = impl ::std::any::Any)]
fn get_2() -> i64 {
    2
}

#[test]
fn overriding_return_type() {
    let result = get_1();
    assert_eq!(result, Ok(2));

    let result = get_2();
    assert_eq!("core::result::Result<i64, ()>", ::std::any::type_name_of_val(&result));
}

依赖关系

~290–740KB
~18K SLoC