11个版本
0.2.2 | 2024年7月20日 |
---|---|
0.2.1 | 2023年3月20日 |
0.2.0 | 2022年11月30日 |
0.1.7 | 2022年9月27日 |
0.1.0 | 2021年7月27日 |
#1620 在 数据结构
3,616 每月下载量
在 18 个crate中使用(通过 tracker)
15KB
238 行
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()
时,幕后发生的事情是在您结构体的跟踪字段中设置一个位标志
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)
时不应检查相等性,这样即使用相同的值覆盖也标记字段为已更改。
依赖关系
~270–720KB
~17K SLoC