created_at2020-02-14 18:35:34.496477
updated_at2020-02-21 14:10:06.647108
descriptionTrack struct data modifications.
Timon (TimonPost)



Donate Latest Version docs Lines of Code MIT

Track Data Modifications

This library offers a boilerplate free approach to track struct data modifications. For optimization, only the adjusted fields are tracked. Changes will be serialized and sent on an channel.


  • Monitoring modifications in data

  • Serde based (excluding fields, ...)

  • Applying modifications to a type

  • Customizable Serialization

Feature Flags

Feature Description
bincode-serialization serialization using bincode (enabled by default) .
rmp-serialization serialization using rmp-serde .

Optionally implement your own serializer met SerializationStrategy](track/serialization/trait.SerializationStrategy.html).


First, add track attribute to mark your struct as trackable.

// imports all necessarily types for the `track` attribute.
use track::preclude::*;

pub struct Position {
    pub x: u32,
    pub y: u32,

You can specify a serialization method for the track macro. Give the name of the type that implements SerializationStrategy, and make sure it is in scope for the macro. Such as:

use track::serialization::bincode::Bincode;

#[track(serialization = "Bincode")]
struct Postition ...

Now let us make some modifications and apply those to other instances.

use track::{preclude::*, serialization::bincode::Bincode, Apply, ModificationChannel};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Identity {
    pub value: u8,

impl Identifier for Identity {}

fn main() {
    let channel = ModificationChannel::<Identity>::new();

    let updated_storage = vec![
        (Identity { value: 1 }, Position { x: 0, y: 0 }),
        (Identity { value: 2 }, Position { x: 0, y: 0 }),
    let mut outdated_storage = updated_storage.clone();

    // == Make changes to storage ==
    make_changes(&channel, updated_storage);

    // == Apply changes to outdated storage ==
    apply_changes(&channel, &mut outdated_storage);

fn make_changes(channel: &ModificationChannel<Identity>, entities: Vec<(Identity, Position)>) {
    for (id, mut position) in entities {
        let mut position = position.track(channel.sender(), id); /* returns `Tracker` which tracks changes */

        // `Tracker` implements `DerefMut`
        position.x += 1;
        position.y += 1;
    } // <- on the `Drop` of `wrapper` changes are serialized and sent on the channel.

fn apply_changes(
    channel: &ModificationChannel<Identity>,
    entities: &mut Vec<(Identity, Position)>,
) {
    for event in channel.receiver().try_iter() {
        let entity = entities
            .find(|e| e.0 == event.identifier)

        Apply::apply_to(&mut entity.1, &event.modified_fields, Bincode);

        println!("entity updated {:?}", entity);

For a more in-depth example checkout the examples on github.

Commit count: 14

cargo fmt