2 unstable releases

0.1.0 Feb 21, 2020
0.0.0 Feb 14, 2020

#5 in #track


Used in net-sync

MIT license

23KB
288 lines

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.

Features

  • 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).

Examples

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

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

#[track]
#[derive(Debug)]
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
            .iter_mut()
            .find(|e| e.0 == event.identifier)
            .unwrap();

        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.

Dependencies

~1.3–2MB
~44K SLoC