Tracker - track changes to structs efficiently
Tracker is a small crate that allows you to track changes to struct fields.
It implements the following methods for your struct fields:
-
get_#field_name()
Get an immutable reference tofield_name -
get_mut_#field_name()
Get a mutable reference tofield_name. Assumes the field will be modified and marks it as changed. -
set_#field_name(value)
Set a value offield_name. Marks the field as changed only if the new value isn't equal with the previous value. -
update_#field_name(fn)
Update yourfield_namewith a function or closure. Assumes the field will be modified and marks it as changed. -
changed_#field_name()
Check if value offield_namehas changed.
To check for changes explicitly you can call var_name.changed(StructName::field_name()) and it will return a bool.
Multiple fields can be checked with var_name.changed(StructName::field_name_1() | StructName::field_name_2()).
Finally, it is possible to check for any changes at all with var_name.changed(StructName::track_all()) or its shortcut
var_name.changed_any().
To reset all previous changes you can call var_name.reset().
How it works
Let's have a look at a small example.
What happens behind the scenes when you call set_x() is that a bitflag is set in the tracker field of your 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 |
As you can see this works pretty efficient. The macro expansion looks like this:
Further attributes
You can mark fields as
do_not_trackif you don't want tracker to implement anything for this fieldno_eqif the type of the field doesn't implement PartialEq or tracker should not check for equality when callingset_#field_name(value)so that even overwriting with the same value marks the field as changed.