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
dipa
implementation fori128
does not use a reference for the delta sincei128
is 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.