devpage_design/wire/
patch.rs1use super::{decode, encode, encode_own, file, files, font_file, font_files, node_id, unnode_id};
5use crate::proto::{self, op::Op as Kind};
6use crate::scene::{self, Applied, Edit, Edits, Scene, Uses};
7
8pub fn patch(edits: &Edits) -> proto::Patch {
10 proto::Patch {
11 ops: edits.list.iter().map(op).collect(),
12 images: edits.images.values().map(|f| file(f)).collect(),
13 fonts: edits.fonts.values().map(|f| font_file(f)).collect(),
14 themed: edits.themed,
15 }
16}
17
18fn op(edit: &Edit) -> proto::Op {
19 let op = match edit {
20 Edit::Change(n) => Kind::Change(encode_own(n)),
21 Edit::Insert {
22 parent,
23 after,
24 node,
25 } => Kind::Insert(proto::Insert {
26 parent: parent.as_ref().map(node_id),
27 after: after.as_ref().map(node_id),
28 node: Some(encode(node)),
29 }),
30 Edit::Remove(id) => Kind::Remove(node_id(id)),
31 Edit::Move { id, parent, after } => Kind::Move(proto::Move {
32 id: Some(node_id(id)),
33 parent: Some(node_id(parent)),
34 after: after.as_ref().map(node_id),
35 }),
36 };
37 proto::Op { op: Some(op) }
38}
39
40pub(crate) fn edits(patch: &proto::Patch, scene: &Scene) -> Result<Edits, String> {
44 let list = patch
45 .ops
46 .iter()
47 .map(|o| {
48 Ok(match o.op.as_ref().ok_or("an empty operation")? {
49 Kind::Change(n) => Edit::Change(decode(n)?),
50 Kind::Insert(i) => Edit::Insert {
51 parent: i.parent.as_ref().map(|p| unnode_id(Some(p))).transpose()?,
52 after: i.after.as_ref().map(|a| unnode_id(Some(a))).transpose()?,
53 node: decode(i.node.as_ref().ok_or("an insert with no node")?)?,
54 },
55 Kind::Remove(id) => Edit::Remove(unnode_id(Some(id))?),
56 Kind::Move(m) => Edit::Move {
57 id: unnode_id(m.id.as_ref())?,
58 parent: unnode_id(m.parent.as_ref())?,
59 after: m.after.as_ref().map(|a| unnode_id(Some(a))).transpose()?,
60 },
61 })
62 })
63 .collect::<Result<_, String>>()?;
64 Ok(Edits {
65 list,
66 images: files(&patch.images, &scene.images)?,
67 fonts: font_files(&patch.fonts, &scene.fonts)?,
68 themed: patch.themed,
69 })
70}
71
72pub fn apply(scene: &mut Scene, uses: &mut Uses, patch: &proto::Patch) -> Result<Applied, String> {
76 let edits = edits(patch, scene)?;
77 scene::apply(scene, uses, &edits)
78}
79
80#[cfg(test)]
81mod tests;