#proc-macro #field #struct-fields #cache #proc #macro #properties

cached_field

Proc macro 用于在结构体字段上缓存关联函数的结果。类似于 Python 的 @cached_property 类装饰器。

1 个稳定版本

1.0.2 2024 年 2 月 7 日

203缓存

MIT 许可证

15KB
213 代码行

cached_field

Rust proc macro 用于在结构体字段上缓存关联函数的结果。类似于 Python 的 @cached_property 类装饰器。

安装

cargo install cached_field

用法

属性宏装饰在结构体的函数实现上;

函数必须将其第一个参数作为 &self 接收;结构体必须有一个相应的可选字段来存储计算结果;

参数

field:必须是字符串字面量,用于指示要缓存结果的结构体字段,默认为它装饰的函数的标识符;

borrow:布尔值,指示转换后的函数返回存储值的引用或副本;如果为 false,返回类型应实现 Copy 特性;默认为 true;

它接受按顺序排列的 (field, borrow) 位置参数或命名值参数;

示例

use cached_field::cached_field;
struct SomeStruct{
    some_value: Option<u8>
}

impl SomeStruct{
    #[cached_field]
    fn some_value(&self) -> u8 {
        100
    }
    #[cached_field("some_value")]
    fn same_value(&self) -> u8 {
        101
    }
}

// s has to be mut 
// since some_value requires a mutable reference to SomeStruct to mutate the some_value field inside;   
let mut s = SomeStruct{some_value:None};

assert_eq!(100, s.some_value());
assert_eq!(100, s.same_value());

trait 实现

  • trait 块中的函数定义应该是转换的最终形式。即接收参数为 &mut self,如果 borrow 为 true,则返回类型为 &T;
  • impl 函数签名应采用不可变形式;即 &self 和 T,如果没有 &(如果 trait 签名中 &T 作为返回类型),则不带 &;
  • 一般思路是 impl 函数仅用于计算目的,因此它不应修改结构体,并应返回原始结果;

use cached_field::cached_field;

struct AnotherStruct{ 
    another_value: Option<Vec<String>>
}

trait Another {
    fn another(&mut self)->&Vec<String>;
}

impl Another for AnotherStruct {
    #[cached_field(field = "another_value", borrow = true)]
    fn another(&self)->Vec<String>{
        vec![1.to_string(),3.to_string(),5.to_string()]
    }
}

assert_eq!(vec![1.to_string(),3.to_string(),5.to_string()], *AnotherStruct{another_value:None}.another());

特性

默认情况下,如果 borrow 为 true,宏将检查计算函数的返回类型,如果它找到一个 &,则将 panic;

使用以下特性修改 borrow 为 true 且现有 & 引用被发现时的行为

carry:在转换时保留返回类型不变;

prepend:将 & 预先附加到原始类型,例如将 &T 转换为 &&T;

这些特性是**互斥的**;

依赖项

~255–700KB
~17K SLoC