dipa 0.1.1

dipa makes it easy to efficiently delta encode large Rust data structures.
Documentation
#[macro_export]
macro_rules! map_impl {
    ($map_ty:ty, $module:ident, $($additional_key_bounds:tt)*) => {
        mod $module {
            use super::{MapDelta, MapDeltaOwned};
            use crate::{CreatedDelta, Diffable, Patchable};
            use serde::{Serialize, de::DeserializeOwned};
            use std::hash::Hash;

            type MapAssociatedDeltaOwned<'s, 'e, K, V> =
                <$map_ty as Diffable<'s, 'e, $map_ty>>::DeltaOwned;

            impl<'s, 'e, K, V> Diffable<'s, 'e, $map_ty> for $map_ty
            where
                K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
                V: 'e + Diffable<'s, 'e, V>,
                <V as Diffable<'s,'e,V>>::Delta: Serialize,
                <V as Diffable<'s,'e,V>>::DeltaOwned: DeserializeOwned
            {
                type Delta = MapDelta<'s, 'e, K, V>;
                type DeltaOwned = MapDeltaOwned<'s, 'e, K, V>;

                fn create_delta_towards(
                    &'s self,
                    end_state: &'e $map_ty,
                ) -> CreatedDelta<Self::Delta> {
                    let mut did_change = false;

                    if end_state.len() == 0 && self.len() > 0 {
                        let delta = MapDelta::RemoveAll;
                        return CreatedDelta {
                            delta,
                            did_change: true
                        };
                    }

                    let mut delta = MapDelta::NoChange;

                    let mut fields_to_add = Vec::new();
                    let mut fields_to_remove = Vec::new();
                    let mut fields_changed = Vec::new();

                    for (key, start) in self.iter() {
                        match end_state.get(key) {
                            None => {
                                did_change = true;
                                fields_to_remove.push(key);
                            }
                            Some(end) => {
                                let CreatedDelta {delta, did_change: changed} = start.create_delta_towards(end);

                                if changed {
                                    did_change = true;
                                    fields_changed.push((key, delta));
                                }
                            }
                        }
                    }

                    for (key, val) in end_state.iter() {
                        if !self.contains_key(key) {
                            did_change = true;
                            fields_to_add.push((key, val));
                        }
                    }

                    let many_fields_to_add = fields_to_add.len() > 1;
                    let many_fields_to_remove = fields_to_remove.len() > 1;
                    let many_fields_changed = fields_changed.len() > 1;

                    let one_field_to_add = fields_to_add.len() == 1;
                    let one_field_to_remove = fields_to_remove.len() == 1;
                    let one_field_changed = fields_changed.len() == 1;

                    let encode_using_many_variant =
                        many_fields_to_add || many_fields_to_remove || many_fields_changed;

                    if encode_using_many_variant {
                        delta = MapDelta::ModifyMany {
                            added: fields_to_add,
                            removed: fields_to_remove,
                            changed: fields_changed,
                        }
                    } else if one_field_to_add {
                        delta = MapDelta::AddOneField(fields_to_add[0].0, fields_to_add[0].1);
                    } else if one_field_to_remove {
                        delta = MapDelta::RemoveOneField(fields_to_remove[0]);
                    } else if one_field_changed {
                        let change = fields_changed.remove(0);
                        delta = MapDelta::ChangeOneField(change.0, change.1);
                    }

                    CreatedDelta {
                        delta,
                        did_change
                    }
                }
            }

            impl<'s, 'e, K, V> Patchable<MapAssociatedDeltaOwned<'s, 'e, K, V>> for $map_ty
            where
                K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
                V: 'e + Diffable<'s, 'e, V>,
                V: Patchable<<V as Diffable<'s, 'e, V>>::DeltaOwned>,
                <V as Diffable<'s,'e,V>>::Delta: Serialize,
                <V as Diffable<'s,'e,V>>::DeltaOwned: DeserializeOwned
            {
                fn apply_patch(&mut self, patch: MapAssociatedDeltaOwned<'s, 'e, K, V>) {
                    match patch {
                        MapDeltaOwned::NoChange => {}
                        MapDeltaOwned::RemoveAll => self.clear(),
                        MapDeltaOwned::AddOneField(k, v) => {
                            self.insert(k, v);
                        }
                        MapDeltaOwned::RemoveOneField(k) => {
                            self.remove(&k);
                        }
                        MapDeltaOwned::ChangeOneField(k, delta) => {
                            self.get_mut(&k).unwrap().apply_patch(delta);
                        }
                        MapDeltaOwned::ModifyMany {
                            added,
                            removed,
                            changed,
                        } => {
                            for add in added {
                                self.insert(add.0, add.1);
                            }

                            for remove in removed {
                                self.remove(&remove);
                            }

                            for change in changed {
                                self.get_mut(&change.0).unwrap().apply_patch(change.1);
                            }
                        }
                    }
                }
            }
        }
    };
}