edit-text icon indicating copy to clipboard operation
edit-text copied to clipboard

Better method definitions for OT and Schema

Open tcr opened this issue 7 years ago • 1 comments

At a recent talk I presented a simpler API (for purposes of explanation) and noticed that RtfSchema and TrackType could be unified. With some normalizing, this makes the trait API oatie into the following:

/// impl on the Operation
pub trait OT where Self: Sized {
    type Doc;

    fn apply(&Self::Doc, &Self) -> Self::Doc; // should reverse args?
    fn compose(&Self, &Self) -> Self;
    fn transform<S: Schema>(&Self, &Self) -> (Self, Self);
    fn transform_advance<S: Schema>(a: &Self, b: &Self) -> Self;

    fn empty() -> Self;
    fn compose_iter<'a, I>(iter: I) -> Self where I: Iterator<Item=&'a Self>, Self: 'a;
}

/// impl on an enum of types
pub trait Schema: Copy {
    type Attrs = HashMap<String, String>; // overloadable?

    fn allowed_in_root(&self) -> bool;
    fn contains_text(&self) -> bool;
    fn contains_children(&self) -> Vec<Self>;

    fn validate(&Doc) -> Result<(), Error>;
    fn identify(&Self::Attrs) -> Option<Schema>;
}

enum RtfSchema {
    ListItems,      // bullet
    BlockQuotes,    // blockquote
    Blocks,         // h1, h2, h3, h4, h5, h6, p, pre
    BlockObjects,   // hr
    Inlines,        // span
    InlineObjects,  // caret
}

tcr avatar Mar 31 '18 16:03 tcr

Follow-up: what if Schema ditched the concept of Attrs entirely?

In this design, RtfSchema would actually encode all information needed by Attrs:

enum BlockType {
    P, H1, H2, H3, H4, H5, H6, Code
}

enum InlineObjectType {
    Caret { client_id: String },
    Image(Url),
    // ...
}

enum BlockObjectType {
    Hr,
    Image(Url),
}

// Each of these elements have common transform characteristics
enum RtfSchema {
    ListItem,
    BlockQuote,
    Block(BlockType),
    BlockObject(BlockObjectType),
    InlineObject(InlineObjectType),
}

enum DocElement<S: Schema + Sized> {
    DocChars(DocString),
    DocGroup(S, Vec<DocElement>),
}

This would require no string manipulation (inspecting tag), would introduce more type safety, but also be more verbose to type and less "generic". The biggest question would be how to express these elements in Ron in a way that's extensible:

DocGroup(Block(H1), [...]) // This works I think?
DocGroup(BlockObject(Caret("client-a")), [...]) // verbose...

tcr avatar Apr 23 '18 02:04 tcr