mergable 0.43.0

A library for user-friendly and efficient CRDTs.
Documentation
pub(crate) fn test_merge
	<T: crate::Mergable + Clone + PartialEq + std::fmt::Debug + 'static>
	(docs: &mut [&T])
	-> T
	where T::Diff: std::fmt::Debug
{
	if docs.len() == 1 {
		return (*docs.first().unwrap()).clone()
	}

	let mut reference = test_merge(&mut docs[1..]);
	reference.merge(docs[0].clone());

	for i in 1..docs.len() {
		docs.swap(0, i);

		let mut rest = test_merge(&mut docs[1..]);
		rest.merge(docs[0].clone());

		if rest != reference {
			eprintln!("Non-transient merge detected.");
			eprintln!(" left sequence:");
			for doc in docs.iter().rev() {
				eprintln!("  {:?}", doc);
			}
			eprintln!("right sequence:");
			docs.swap(i, 0);
			for doc in docs.iter().rev() {
				eprintln!("  {:?}", doc);
			}
		}
		assert_eq!(rest, reference);

		docs.swap(i, 0);
	}

	if docs.len() == 2 {
		eprintln!("L {:#?}", docs[0]);
		eprintln!("R {:#?}", docs[1]);

		let diff_left = || docs[0].diff(&docs[1]);
		eprintln!("L-R = {:#?}", diff_left());
		let diff_right = || docs[1].diff(&docs[0]);
		eprintln!("R-L = {:#?}", diff_right());

		let mut apply_left = docs[1].clone();
		apply_left.apply(diff_left()).unwrap();
		assert_eq!(apply_left, reference, "R+(L-R)");

		let mut apply_right = docs[0].clone();
		apply_right.apply(diff_right()).unwrap();
		assert_eq!(apply_right, reference, "L+(R-L)");

		let mut apply_both_left = docs[0].clone();
		apply_both_left.apply(diff_left()).unwrap();
		apply_both_left.apply(diff_right()).unwrap();
		assert_eq!(apply_both_left, apply_right);

		let mut apply_both_right = docs[1].clone();
		apply_both_right.apply(diff_left()).unwrap();
		apply_both_right.apply(diff_right()).unwrap();
		assert_eq!(apply_both_left, apply_right);
	}


	reference
}

pub(crate) fn test_apply
	<T: crate::Mergable + Clone + PartialEq + std::fmt::Debug + 'static>
	(initial: T, diffs: &mut [T::Diff])
	-> T
	where T::Diff: Clone + std::fmt::Debug
{
	if diffs.is_empty() {
		return initial
	}

	let mut with_first = initial.clone();
	dbg!(&with_first, &diffs[0]);
	with_first.apply(diffs[0].clone()).unwrap();
	let reference = test_apply(with_first, &mut diffs[1..]);

	for i in 1..diffs.len() {
		diffs.swap(0, i);

		let mut v = initial.clone();
		v.apply(diffs[0].clone()).unwrap();
		let r = test_apply(v, &mut diffs[1..]);

		if r != reference {
			eprintln!("Non-transient apply detected.");
			eprintln!(" left sequence:");
			for diff in &diffs[..] {
				eprintln!("  {:?}", diff);
			}
			eprintln!("right sequence:");
			diffs.swap(i, 0);
			for diff in &diffs[..] {
				eprintln!("  {:?}", diff);
			}
		}
		assert_eq!(r, reference);

		diffs.swap(i, 0);
	}

	reference
}