summaryrefslogtreecommitdiff
path: root/crdt/src/doc.rs
blob: fcca1d8b9711d9962e4ee5373c460a7c764096cb (plain)
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
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;

use crate::op::{ChangeSubdivisions, CreateGrid, Op, OpKind};

/// An deterministically derived ID, e.g. a grid ID derived from the
/// op ID which creates it.
pub struct DerivedId {
    base: String,
    tag: &'static str,
    index: usize,
}

impl ToString for DerivedId {
    fn to_string(&self) -> String {
        format!("{}:{}={}", self.base, self.tag, self.index)
    }
}

trait DerivableId {
    fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId;
}

impl DerivableId for Uuid {
    fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId {
        DerivedId {
            base: self.to_string(),
            tag,
            index,
        }
    }
}

impl DerivableId for DerivedId {
    fn derive_id(&self, tag: &'static str, index: usize) -> DerivedId {
        DerivedId {
            base: self.to_string(),
            tag,
            index,
        }
    }
}

impl Serialize for DerivedId {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

#[derive(Default, Serialize)]
pub struct Doc {
    pub(crate) grids: Vec<Grid>,
}

#[derive(Serialize)]
pub struct Grid {
    pub(crate) id: DerivedId,
    pub(crate) rows: Vec<Row>,
}

#[derive(Serialize)]
pub struct Row {
    pub(crate) id: DerivedId,
    pub(crate) cells: Vec<Cell>,
}

#[derive(Serialize)]
pub struct Cell {
    pub(crate) id: DerivedId,
}

#[derive(Error, Debug)]
pub enum ApplyOpError {}

pub type ApplyOpResult = Result<(), ApplyOpError>;

impl Doc {
    pub fn apply_op(&mut self, op: &Op) -> ApplyOpResult {
        match &op.kind {
            OpKind::CreateGrid(data) => apply_create_grid(self, &op.id, data),
            OpKind::ChangeSubdivisions(data) => apply_change_subdivisions(self, data),
        }
    }
}

fn apply_create_grid(doc: &mut Doc, op_id: &Uuid, data: &CreateGrid) -> ApplyOpResult {
    let grid_id = op_id.derive_id("grid", 0);

    let rows = (0..data.rows)
        .map(|row_idx| {
            let row_id = grid_id.derive_id("row", row_idx);

            let cells = (0..data.base_cells_per_row)
                .map(|cell_idx| Cell {
                    id: row_id.derive_id("cell", cell_idx),
                })
                .collect();

            Row { id: row_id, cells }
        })
        .collect();

    doc.grids.push(Grid { id: grid_id, rows });

    Ok(())
}

fn apply_change_subdivisions(doc: &mut Doc, data: &ChangeSubdivisions) -> ApplyOpResult {
    todo!()
}