1use serde::{Deserialize, Serialize};
20
21use crate::{Address, B3Hash};
22
23#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
26pub struct DocumentWritten {
27 pub at: Address,
29 pub baseline: B3Hash,
31 pub version: B3Hash,
33 pub bytes: u64,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
41pub struct ProposalOffered {
42 pub doc: Address,
43 pub baseline: B3Hash,
44 pub start: u64,
47 pub end: u64,
48 pub before: String,
50 pub after: String,
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
58#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
59pub struct ProposalDecided {
60 pub proposal: B3Hash,
61 pub verdicts: Vec<SliceVerdict>,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
67#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
68pub struct SliceVerdict {
69 pub slice: u32,
70 pub verdict: Verdict,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case")]
77#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
78pub enum Verdict {
79 Accept,
80 Amend { text: String },
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
87pub struct ProposalWithdrawn {
88 pub proposal: B3Hash,
89}
90
91#[cfg(test)]
92#[allow(clippy::unwrap_used, clippy::expect_used, reason = "test code")]
93mod tests {
94 use super::*;
95 use crate::event::Payload;
96
97 #[test]
100 fn each_document_line_spells_its_keys_once() {
101 let doc = Address::parse("lab/notes.md").unwrap();
102 let zero = B3Hash::from_bytes([0; 32]);
103 let hex = "0".repeat(64);
104 let cases: [(Payload, String); 4] = [
105 (
106 Payload::of(&DocumentWritten {
107 at: doc.clone(),
108 baseline: zero,
109 version: zero,
110 bytes: 3,
111 })
112 .unwrap(),
113 format!(
114 "{{\"at\":\"lab/notes.md\",\"baseline\":\"{hex}\",\"bytes\":3,\"version\":\"{hex}\"}}"
115 ),
116 ),
117 (
118 Payload::of(&ProposalOffered {
119 doc,
120 baseline: zero,
121 start: 1,
122 end: 2,
123 before: "a".to_owned(),
124 after: "b".to_owned(),
125 })
126 .unwrap(),
127 format!(
128 "{{\"after\":\"b\",\"baseline\":\"{hex}\",\"before\":\"a\",\"doc\":\"lab/notes.md\",\"end\":2,\"start\":1}}"
129 ),
130 ),
131 (
132 Payload::of(&ProposalDecided {
133 proposal: zero,
134 verdicts: vec![
135 SliceVerdict {
136 slice: 1,
137 verdict: Verdict::Accept,
138 },
139 SliceVerdict {
140 slice: 2,
141 verdict: Verdict::Amend {
142 text: "c".to_owned(),
143 },
144 },
145 ],
146 })
147 .unwrap(),
148 format!(
149 "{{\"proposal\":\"{hex}\",\"verdicts\":[{{\"slice\":1,\"verdict\":\"accept\"}},{{\"slice\":2,\"verdict\":{{\"amend\":{{\"text\":\"c\"}}}}}}]}}"
150 ),
151 ),
152 (
153 Payload::of(&ProposalWithdrawn { proposal: zero }).unwrap(),
154 format!("{{\"proposal\":\"{hex}\"}}"),
155 ),
156 ];
157 for (payload, wire) in cases {
158 assert_eq!(serde_json::to_string(&payload).unwrap(), wire);
159 let back: Payload = serde_json::from_str(&wire).unwrap();
160 assert_eq!(back, payload);
161 }
162 }
163}