1#[derive(Clone, Debug, PartialEq, Eq)]
2pub struct Block {
3 pub clean: String,
4 pub raw: String,
6}
7
8#[derive(Default)]
16pub struct Settle {
17 settled: Vec<Block>,
18 committing: Option<Block>,
19 live: String,
20 committing_revised: bool,
21}
22
23impl Settle {
24 pub fn new() -> Self { Self::default() }
25
26 pub fn on_partial(&mut self, partial: &str) {
28 self.live = partial.to_string();
29 }
30
31 pub fn commit(&mut self, raw: &str, clean: &str) {
35 self.finalize();
36 self.committing = Some(Block { clean: clean.to_string(), raw: raw.to_string() });
37 self.committing_revised = false;
38 self.live.clear();
39 }
40
41 pub fn finalize(&mut self) {
43 if let Some(b) = self.committing.take() {
44 self.settled.push(b);
45 }
46 }
47
48 pub fn upgrade_committing(&mut self, clean: &str) -> bool {
52 match self.committing.as_mut() {
53 Some(b) => {
54 b.clean = clean.to_string();
55 self.committing_revised = true;
56 true
57 }
58 None => false,
59 }
60 }
61
62 pub fn revise_committing(&mut self, raw: &str, clean: &str) -> bool {
66 match self.committing.as_mut() {
67 Some(b) => {
68 b.raw = raw.to_string();
69 b.clean = clean.to_string();
70 self.committing_revised = true;
71 true
72 }
73 None => false,
74 }
75 }
76
77 pub fn try_late_revision_settled(&mut self, _index: usize, _new_text: &str) -> bool {
80 false
81 }
82
83 pub fn settled(&self) -> &[Block] { &self.settled }
84 pub fn committing(&self) -> Option<&Block> { self.committing.as_ref() }
85 pub fn live(&self) -> &str { &self.live }
86
87 pub fn committing_revised(&self) -> bool { self.committing_revised }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn partial_updates_only_the_live_edge() {
98 let mut s = Settle::new();
99 s.on_partial("um so the thing");
100 assert_eq!(s.live(), "um so the thing");
101 assert!(s.settled().is_empty() && s.committing().is_none());
102 }
103
104 #[test]
105 fn commit_moves_live_into_committing_not_settled() {
106 let mut s = Settle::new();
107 s.on_partial("um so the thing is");
108 s.commit("um so the thing is", "The thing is.");
109 assert_eq!(s.committing().unwrap().clean, "The thing is.");
110 assert_eq!(s.live(), "");
111 assert!(s.settled().is_empty());
112 }
113
114 #[test]
115 fn second_commit_finalizes_the_first() {
116 let mut s = Settle::new();
117 s.commit("a", "A.");
118 s.commit("b", "B.");
119 assert_eq!(s.settled().len(), 1);
120 assert_eq!(s.settled()[0].clean, "A.");
121 assert_eq!(s.committing().unwrap().clean, "B.");
122 }
123
124 #[test]
125 fn upgrade_changes_only_the_committing_block() {
126 let mut s = Settle::new();
127 s.commit("a", "A.");
128 s.commit("b raw", "B.");
129 let settled0 = s.settled()[0].clone();
130 assert!(s.upgrade_committing("B, refined."));
131 assert_eq!(s.settled()[0], settled0); assert_eq!(s.committing().unwrap().clean, "B, refined.");
133 }
134
135 #[test]
136 fn upgrade_is_noop_after_finalize() {
137 let mut s = Settle::new();
138 s.commit("a", "A.");
139 s.finalize();
140 assert!(!s.upgrade_committing("A!"));
141 assert_eq!(s.settled()[0].clean, "A.");
142 }
143
144 #[test]
145 fn revise_replaces_both_raw_and_clean_of_the_committing_block() {
146 let mut s = Settle::new();
147 s.commit("a", "A.");
148 s.commit("live hypothesis", "Live hypothesis.");
149 assert!(s.revise_committing("better raw", "Better raw."));
150 assert_eq!(s.settled()[0].clean, "A."); let c = s.committing().unwrap();
152 assert_eq!(c.raw, "better raw");
153 assert_eq!(c.clean, "Better raw.");
154 }
155
156 #[test]
157 fn revise_is_noop_after_finalize() {
158 let mut s = Settle::new();
159 s.commit("a", "A.");
160 s.finalize();
161 assert!(!s.revise_committing("x", "X."));
162 assert_eq!(s.settled()[0].raw, "a");
163 }
164
165 #[test]
166 fn committing_revised_flag_tracks_commit_then_revise_then_recommit() {
167 let mut s = Settle::new();
168 s.commit("a", "A.");
169 assert!(!s.committing_revised());
170 assert!(s.revise_committing("a2", "A2."));
171 assert!(s.committing_revised());
172 s.commit("b", "B.");
173 assert!(!s.committing_revised());
174 }
175
176 #[test]
177 fn upgrade_committing_sets_the_revised_flag() {
178 let mut s = Settle::new();
179 s.commit("a", "A.");
180 assert!(!s.committing_revised());
181 assert!(s.upgrade_committing("A, refined."));
182 assert!(s.committing_revised());
183 }
184
185 #[test]
186 fn late_revision_never_mutates_settled() {
187 let mut s = Settle::new();
188 s.commit("first", "First.");
189 s.finalize();
190 let before = s.settled().to_vec();
191 assert!(!s.try_late_revision_settled(0, "FIRST!!"));
192 assert_eq!(s.settled(), &before[..]);
193 }
194}