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, } } } #[derive(Default)] pub struct Doc { pub(crate) grids: Vec, } pub struct Grid { pub(crate) id: DerivedId, pub(crate) rows: Vec, } pub struct Row { pub(crate) id: DerivedId, pub(crate) cells: Vec, } 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!() }