Skip to content

Instantly share code, notes, and snippets.

Created January 5, 2016 21:50
Show Gist options
  • Save anonymous/6f6061a728aca0fefd5f to your computer and use it in GitHub Desktop.
Save anonymous/6f6061a728aca0fefd5f to your computer and use it in GitHub Desktop.
Shared via Rust Playground
use std::collections::HashMap;
use std::marker::PhantomData;
use std::collections::hash_map;
pub trait DiffableIters<'a, T: Diffable> where T::Key: 'a, T::ListChild: 'a {
type KeyIter: Iterator<Item=&'a T::Key>;
type ListChildIter: Iterator<Item=&'a T::ListChild>;
}
pub type KeyIter<'a, T> = <T as DiffableIters<'a, T>>::KeyIter;
pub type ListChildIter<'a, T> = <T as DiffableIters<'a, T>>::ListChildIter;
pub trait Diffable: Clone + for<'b> DiffableIters<'b, Self> {
type MapChild: Diffable;
type Content;
type Key;
type ListChild: Diffable;
fn content_same_as(&self, other: &Self) -> bool;
fn content(&self) -> Self::Content;
fn list_children(&self) -> Option<ListChildIter<Self>> { None }
fn map_keys(&self) -> Option<KeyIter<Self>> { None }
fn lookup(&self, key: &Self::Key) -> Option<&Self::MapChild> { None }
}
pub struct UnitIter<'a>(PhantomData<&'a()>);
impl<'a> Iterator for UnitIter<'a> {
type Item = &'a ();
fn next(&mut self) -> Option<&'a ()> { None }
}
impl<'a> DiffableIters<'a, ()> for () {
type KeyIter = UnitIter<'a>;
type ListChildIter = UnitIter<'a>;
}
impl Diffable for () {
type MapChild = ();
type Content = ();
type Key = ();
type ListChild = ();
fn content(&self) {}
fn content_same_as(&self, other: &Self) -> bool { true }
}
pub enum ListEdit<T: Diffable> {
Insert(T::ListChild),
Remove,
Replace(T::ListChild)
}
pub enum MapEdit<T: Diffable> {
Set(T::MapChild),
Remove,
Move(T::Key)
}
impl<'a, K, V> DiffableIters<'a, HashMap<K, V>> for HashMap<K, V>
where
K: Eq + std::hash::Hash + Clone + 'static,
V: Diffable + 'static
{
type ListChildIter = UnitIter<'a>;
type KeyIter = hash_map::Keys<'a, K, V>;
}
impl<K: Eq + std::hash::Hash + Clone + 'static, V: Diffable + 'static> Diffable
for HashMap<K, V>
{
type MapChild = V;
type Content = ();
type Key = K;
type ListChild = ();
fn content_same_as(&self, _: &HashMap<K, V>) -> bool { true }
fn content(&self) {}
fn map_keys(&self) -> Option<hash_map::Keys<K, V>> { Some(self.keys()) }
}
pub struct Diff<T: Diffable> {
new_content: Option<T::Content>,
list_diffs: Box<[(usize, ListEdit<T>)]>,
map_diffs: HashMap<T::Key, MapEdit<T>>
}
pub fn diff<T: Diffable>(from: &T, to: &T) -> Diff<T> {
Diff {
new_content: if from.content_same_as(to) {
None
} else {
Some(from.content())
},
list_diffs: panic!(),
map_diffs: panic!()
}
}
fn main() {
let mut map = HashMap::new();
map.insert(1, ());
map.map_keys().unwrap().next();
//diff(&(), &());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment