1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! Defines types for using operational tranform to modify HTML-like documents.
//! 
//! See the book for more details: http://tcr.github.io/edit-text/

#![feature(nll)]

#![allow(unknown_lints)]
#![allow(single_char_pattern)]
#![allow(ptr_arg)]
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(unused_imports)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate maplit;
// extern crate rand;
#[macro_use]
extern crate serde_derive;
extern crate yansi;
extern crate serde_json;
extern crate term_painter;
#[macro_use]
extern crate failure;
extern crate regex;
extern crate either;
extern crate ron;
extern crate serde;

/* logging */

// Macros can only be used after they are defined

macro_rules! log_transform {
    ( $( $x:expr ),* $(,)* ) => {
        // println!( $( $x ),* );
    };
}

macro_rules! log_compose {
    ( $( $x:expr ),* $(,)* ) => {
        // println!( $( $x ),* );
    };
}

/* /logging */


pub mod compose;
pub mod doc;
//pub mod random;
pub mod schema;
pub mod stepper;
pub mod transform;
pub mod writer;
pub mod transform_test;
pub mod macros;
pub mod apply;
mod parse;
pub mod validate;

use apply::*;
use doc::*;
use compose::*;
use std::collections::HashMap;
use std::fmt::Debug;
pub use transform::{Schema, Track};
use transform::transform;

/// A type that can have operational transform applied to it.
/// The `OT` trait is implemented on an operation object, and its 
/// associated type `Doc` is what the operation should operate on.
pub trait OT where Self: Sized {
    type Doc;
    
    /// Applies an operation to a `Self::Doc`, returning the modified `Self::Doc`.
    fn apply(&Self::Doc, &Self) -> Self::Doc;

    /// Returns an empty operation.
    fn empty() -> Self;

    /// Composes two operations, returning a single operation encapsulating them
    /// both.
    fn compose(&Self, &Self) -> Self;

    /// Composes an iterator of operations into a single operation.
    /// If no operations are returned from the iterator, the OT::empty() should be
    /// returned.
    fn compose_iter<'a, I>(iter: I) -> Self where I: Iterator<Item=&'a Self>, Self: 'a;

    /// Transform a document given the corresponding Schema trait.
    fn transform<S: Schema>(&Self, &Self) -> (Self, Self);

    /// Utility function to transform an operation against a competing one,
    /// returning the results of composing them both.
    fn transform_advance<S: Schema>(a: &Self, b: &Self) -> Self;
}

impl OT for Op {
    type Doc = Doc;

    fn apply(doc: &Self::Doc, op: &Self) -> Self::Doc {
        Doc(apply_operation(&doc.0, op))
    }

    fn empty() -> Self {
        (vec![], vec![])
    }

    fn compose(a: &Self, b: &Self) -> Self {
        compose(a, b)
    }

    fn compose_iter<'a, I>(iter: I) -> Self where I: Iterator<Item=&'a Self> {
        let mut base = Self::empty();
        for item in iter {
            base = Self::compose(&base, item);
        }
        base
    }

    fn transform<S: Schema>(a: &Self, b: &Self) -> (Self, Self) {
        transform::<S>(&a, &b)
    }

    fn transform_advance<S: Schema>(a: &Self, b: &Self) -> Self {
        let (a_transform, b_transform) = Self::transform::<S>(a, b);
        let a_res = Self::compose(a, &a_transform);
        let b_res = Self::compose(a, &a_transform);
        // assert_eq!(a_res, b_res); 
        a_res
    }
}