blockworx/doc_ng/
opcode.rs1use serde::{Deserialize, Serialize};
6
7use crate::doc_ng::{
8 block_model::{
9 BlockInit, BlockUpdate, CommentInit, CommentUpdate, ImageInit, ImageUpdate, PinInit,
10 PinUpdate, RouteInit, RouteLabelInit, RouteLabelUpdate, RouteUpdate, TextInit, TextUpdate,
11 },
12 document::TitleBlockUpdate,
13 id::{BlockId, CommentId, ImageId, PinId, RouteId, RouteLabelId, TextId},
14};
15
16#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
20pub enum Crud<I, U> {
21 Create(I),
22 Restore,
23 Update(U),
24 Delete,
25}
26
27impl<I, U> Crud<I, U> {
28 #[must_use]
36 pub fn invert_lifecycle(&self) -> Option<Crud<I, U>> {
37 match self {
38 Crud::Create(_) | Crud::Restore => Some(Crud::Delete),
39 Crud::Delete => Some(Crud::Restore),
40 Crud::Update(_) => None,
41 }
42 }
43}
44
45#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
46pub enum OpCodes {
47 Document(TitleBlockUpdate),
49 Block(BlockId, Crud<BlockInit, BlockUpdate>),
50 Pin(PinId, Crud<PinInit, PinUpdate>),
51 Route(RouteId, Crud<RouteInit, RouteUpdate>),
52 RouteLabel(RouteLabelId, Crud<RouteLabelInit, RouteLabelUpdate>),
53 Text(TextId, Crud<TextInit, TextUpdate>),
54 Comment(CommentId, Crud<CommentInit, CommentUpdate>),
55 Image(ImageId, Crud<ImageInit, ImageUpdate>),
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
66 fn lifecycle_inversion_is_asymmetric() {
67 assert!(matches!(
68 Crud::<u8, u8>::Create(1).invert_lifecycle(),
69 Some(Crud::Delete)
70 ));
71 assert!(matches!(
72 Crud::<u8, u8>::Restore.invert_lifecycle(),
73 Some(Crud::Delete)
74 ));
75 assert!(matches!(
76 Crud::<u8, u8>::Delete.invert_lifecycle(),
77 Some(Crud::Restore)
78 ));
79 }
80
81 #[test]
84 fn an_update_has_no_baseline_free_inverse() {
85 assert!(Crud::<u8, u8>::Update(7).invert_lifecycle().is_none());
86 }
87}