Implementing Diffable
Here's a look at the Diffable trait.
#![allow(unused_variables)] fn main() { pub trait Diffable<'s, 'e Other> { type Delta; type DeltaOwned; fn create_delta_towards(&self, end_state: &'p Other) -> CreatedDelta<Self::Delta>; } }
The create_delta_towards method takes some end value and generates a delta encoding that can later
be used to turn your start value (&self) into this end value.
Let's walk through a simple implementation of Diffable for an unsigned 128 bit integer.
#![allow(unused_variables)] fn main() { impl Diffable<'s, 'e i128> for i128 { // Note, the real implementation does not use a reference here since i128 // is Copy. This is simply for illustration. type Delta = Option<&'a i128>; type DeltaOwned = Option<i128>; fn create_delta_towards(&self, end_state: &'p i128) -> CreatedDelta<Self::Delta> { let mut did_change = false; let delta = if self == end_state { None } else { did_change = true; Some(end_state) }; CreatedDelta { delta, did_change, } } } }
The i128 in impl Diffable<'s, 'e i128> is the type that we are diffing our &self type against.
A Diffable implementation can diff a type against any other type. The main use case for this is being able
to diff T and &T.
The Diffable::Delta associated type is the type of your delta encoding. For simple types like integers
the implementations that dipa provides use Option<T> as the Delta.
For more complex types such as Vec<T>, custom data structures are used for the Delta.
As we see in type Delta = Option<&'a i28> a Delta can borrow values from the Other type in order to avoid
clones.
NOTE: The real
dipaimplementation fori128does not use a reference for the delta sincei128is a small copy type. It simply usesOption<i128>.
type DeltaOwned is just the Delta type with all of the reference types replaced with owned types.
You'll typically serialize to Diffable::Delta, send the bytes across the wire (potentially after further compressing
them using either a general purpose or custom compression algorithm), and then deserialize them to the
Diffable::DeserializeOwned type.
The did_change is used by the #[derive(DiffPatch)] in the code that it automatically generates for you.
The Delta that the macro generates for is an enum with different variants that get used based on which
of those fields within the Diffable type have changed.