woot 0.1.2

WithOut Operational Transformaton. Rust implementation of the WOOT algorithm.
Documentation
extern crate woot;
extern crate rand;
use woot::{WString, Operation};

use rand::distributions::{IndependentSample, Range};
use std::collections::BinaryHeap;

type W = WString<u8>;

struct E (u64, usize, Operation<u8>);
impl std::cmp::Ord for E {
    fn cmp(&self, rhs: &E) -> std::cmp::Ordering {
        rhs.0.cmp(&self.0)
    }
}
impl std::cmp::PartialOrd for E {
    fn partial_cmp(&self, rhs: &E) -> Option<std::cmp::Ordering> {
        Some(self.cmp(rhs))
    }
}
impl std::cmp::PartialEq for E {
    fn eq(&self, rhs: &E) -> bool {
        self.0.eq(&rhs.0)
    }
}
impl std::cmp::Eq for E {}


fn test(sites_count: usize, timeout: u64) {
    let mut rng = rand::thread_rng();
    let sites_range = Range::new(0, sites_count);
    let latency_range = Range::new(0, 100u64);
    
    let mut sites: Vec<W> = Vec::with_capacity(sites_count);
    for id in 0 .. sites_count {
        sites.push(WString::with_id(id));
    }
    
    let mut heap: BinaryHeap<E> = BinaryHeap::new();
    
    // initial trigger
    let op = sites[0].ins(0, 42);
    for m in 1 .. sites_count {
        let latency = latency_range.ind_sample(&mut rng);
        heap.push(E(latency, m, op.clone()));
    }
    
    while let Some(E(time, site, op)) = heap.pop() {
        let s: &mut W = &mut sites[site];
        let len = s.len();
        println!("\nSite {} at time {:10}", site, time);
        
        s.apply(op);
        //println!("{:5} {:?}", site, s);
        
        if sites_range.ind_sample(&mut rng) < heap.len() {
            continue;
        }
        
        if time > timeout { 
            continue;
        }
        
        let op = if Range::new(0, len+1).ind_sample(&mut rng) < 100 {
            // insert
            // where do we want to insert
            let n = if len > 1 { Range::new(0, len).ind_sample(&mut rng) } else { 0 };
            let c = Range::new(0, 255u8).ind_sample(&mut rng);
            s.ins(n, c)
        } else {
            // where do we want to delete
            let n = Range::new(0, len-1).ind_sample(&mut rng);
            s.del(n)
        };
        //println!("op: {:?}", op);
        
        // broadcast (with some latency issues)
        for m in 0 .. sites_count {
            if m != site {
                let latency = latency_range.ind_sample(&mut rng);
                heap.push(E(time + latency, m, op.clone()));
            }
        }
    }

    let result = sites[0].contents();
    for i in 1 .. sites_count {
        println!("{:03}: {:?}", i, sites[i]);
        if result != sites[i].contents() {
            for i in 0 .. sites_count {
                println!("{:03}: {:?}", i, sites[i]);
            }
            panic!();
        }
    }
}

// 10^3
#[test]
fn brute_1_2() {
    test(10, 100);
}

// 10^4
#[test]
fn brute_1_3() {
    test(10, 1_000);
}
#[test]
fn brute_2_2() {
    test(100, 100);
}

// 10^5
#[test]
fn brute_1_4() {
    test(10, 10_000);
}
#[test]
fn brute_2_3() {
    test(100, 1_000);
}

// 10^6
#[test]
fn brute_3_3() {
    test(1_000, 1_000);
}
#[test]
fn brute_2_4() {
    test(100, 10_000);
}