6 个版本
0.2.2 | 2024年7月20日 |
---|---|
0.2.1 | 2023年3月20日 |
0.2.0 | 2022年11月30日 |
0.1.2 | 2022年9月27日 |
0.1.0 | 2021年7月27日 |
#180 in 数据结构
3,341 每月下载量
在 17 个 仓中使用(直接使用 7 个)
14KB
140 行
Tracker - 高效跟踪结构体变化
Tracker 是一个小的 crate,允许您跟踪结构体字段的更改。
它为您结构体字段实现了以下方法
-
get_#field_name()
获取对field_name
的不可变引用 -
get_mut_#field_name()
获取对field_name
的可变引用。假设该字段将被修改,并将其标记为已更改。 -
set_#field_name(value)
设置field_name
的值。只有当新值与旧值不相等时,才将字段标记为已更改。 -
update_#field_name(fn)
使用函数或闭包更新您的field_name
。假设该字段将被修改,并将其标记为已更改。 -
changed_#field_name()
检查field_name
的值是否已更改。
要显式检查更改,您可以调用 var_name.changed(StructName::field_name())
,它将返回一个布尔值。可以通过 var_name.changed(StructName::field_name_1() | StructName::field_name_2())
检查多个字段。最后,您可以使用 var_name.changed(StructName::track_all())
或其快捷方式 var_name.changed_any()
检查任何更改。
要重置所有之前的更改,您可以调用 var_name.reset()
。
工作原理
让我们看看一个小例子。
#[tracker::track]
struct Test {
x: u8,
y: u64,
}
fn main() {
let mut t = Test {
x: 0,
y: 0,
// the macro generates a new variable called
// "tracker" that stores the changes
tracker: 0,
};
t.set_x(42);
// let's check whether the change was detected
assert!(t.changed(Test::x()));
// reset t so we don't track old changes
t.reset();
t.set_x(42);
// same value so no change
assert!(!t.changed(Test::x()));
}
当您调用 set_x()
时,在您的 struct 的跟踪器字段中会设置一个位标志
y x
tracker: u8 = | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
set_x(42) -> | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
reset() -> | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
如您所见,这非常高效。宏展开如下
impl Test {
pub fn get_x(&self) -> &u8 {
&self.x
}
pub fn get_mut_x(&mut self) -> &mut u8 {
self.tracker |= Self::x();
&mut self.x
}
pub fn update_x<F: Fn(&mut u8)>(&mut self, f: F) {
self.tracker |= Self::x();
f(&mut self.x);
}
pub const fn x() -> u8 {
1 << 0usize
}
pub fn set_x(&mut self, value: u8) {
if self.x != value {
self.tracker |= Self::x();
}
self.x = value;
}
}
进一步属性
#[tracker::track]
struct Test {
#[tracker::do_not_track]
a: u8,
#[do_not_track]
b: u8,
#[tracker::no_eq]
c: u8,
#[no_eq]
d: u8,
}
您可以将字段标记为
do_not_track
如果您不希望跟踪器为此字段实现任何功能no_eq
如果字段的类型没有实现 PartialEq 或在调用set_#field_name(value)
时跟踪器不应检查相等性,这样即使用相同的值覆盖也会将该字段标记为已更改。
依赖项
~235–670KB
~16K SLoC