1#[derive(Eq, PartialEq, Debug)]
11pub enum SMLMessageBuilder {
12 Empty,
13 IncompleteStartSignature(usize),
14 Recording(Vec<u8>),
15 Complete {
16 data: Vec<u8>,
18 rest: Vec<u8>,
20 },
21}
22
23static START_SEQUENCE: &[u8] = &[0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01];
24static END_SEQUENCE_WITHOUT_CRC: &[u8] = &[0x1b, 0x1b, 0x1b, 0x1b, 0x1a];
25
26impl SMLMessageBuilder {
27 pub fn record(&mut self, buf: &[u8]) {
28 match self {
29 SMLMessageBuilder::Empty | SMLMessageBuilder::IncompleteStartSignature(_) => {
30 let start = match self {
31 SMLMessageBuilder::Empty => 0,
32 SMLMessageBuilder::IncompleteStartSignature(start) => *start,
33 SMLMessageBuilder::Recording(_) => todo!(),
34 SMLMessageBuilder::Complete { data: _, rest: _ } => todo!(),
35 };
36 let remainder_of_start_sequence = &START_SEQUENCE[start..];
37 let remaining_start_sequence_bytes = remainder_of_start_sequence.len();
38
39 let buffer_length = buf.len();
40
41 struct MaximalOccurance {
42 index: usize,
43 length: usize,
44 }
45 let maximal_start_sequence_occurance = (0..buffer_length)
46 .map(|i| {
47 let window = &&buf[buffer_length - i - 1
48 ..usize::min(
49 buffer_length,
50 buffer_length - i - 1 + remainder_of_start_sequence.len(),
51 )];
52 let contained_length = contains(window, remainder_of_start_sequence);
53 if contained_length < remaining_start_sequence_bytes
54 && i + 1 > contained_length
55 {
56 MaximalOccurance {
57 index: buffer_length - i - 1,
58 length: 0,
59 }
60 } else {
61 MaximalOccurance {
62 index: buffer_length - i - 1,
63 length: contained_length,
64 }
65 }
66 })
67 .max_by_key(|item| item.length)
68 .unwrap_or(MaximalOccurance {
69 index: 0,
70 length: 0,
71 });
72
73 if maximal_start_sequence_occurance.length == remaining_start_sequence_bytes {
74 *self = SMLMessageBuilder::Recording([].to_vec());
75 self.record(
76 &buf[maximal_start_sequence_occurance.index
77 + maximal_start_sequence_occurance.length..]
78 .to_vec(),
79 );
80 } else if maximal_start_sequence_occurance.length > 0 {
81 *self = SMLMessageBuilder::IncompleteStartSignature(
82 maximal_start_sequence_occurance.length + start,
83 );
84 } else if maximal_start_sequence_occurance.length == 0 && buf.len() > 0 {
85 *self = SMLMessageBuilder::Empty;
86 };
87 }
88
89 SMLMessageBuilder::Recording(recorded) => {
90 recorded.append(&mut buf.to_vec());
91 let end = recorded
92 .windows(END_SEQUENCE_WITHOUT_CRC.len() + 3)
93 .enumerate()
94 .find(|(_, x)| x[..END_SEQUENCE_WITHOUT_CRC.len()] == *END_SEQUENCE_WITHOUT_CRC)
95 .map(|(index, _)| index);
96 if let Some(end) = end {
97 let (message, rest) = recorded.split_at_mut(end);
98 *self = SMLMessageBuilder::Complete {
99 data: message.to_vec(),
100 rest: rest[END_SEQUENCE_WITHOUT_CRC.len() + 3..].to_vec(),
101 }
102 }
103 }
104 _ => {}
105 }
106 }
107}
108fn contains(this: &[u8], that: &[u8]) -> usize {
109 let mut counter = 0;
110 for pair in this.iter().zip(that.iter()) {
111 if pair.0 == pair.1 {
112 counter += 1;
113 } else {
114 break;
115 }
116 }
117 counter
118}
119
120#[cfg(test)]
121mod test {
122
123 use super::*;
124
125 #[test]
126 pub fn extends_if_start_of_sequence_is_found() {
127 let buf = vec![0x1b];
128 let mut rec = SMLMessageBuilder::Empty;
129
130 rec.record(&buf);
131 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(1));
132 }
133
134 #[test]
135 pub fn extends_if_start_of_sequence_is_found_anywhere() {
136 let buf = vec![0xbb, 0x1b];
137 let mut rec = SMLMessageBuilder::Empty;
138
139 rec.record(&buf);
140 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(1));
141 }
142
143 #[test]
144 pub fn extends_more_if_bigger_portion_of_sequence_is_found() {
145 let buf = vec![0x1b, 0x1b];
146 let mut rec = SMLMessageBuilder::Empty;
147
148 rec.record(&buf);
149 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(2));
150 }
151
152 #[test]
153 pub fn extends_more_if_even_bigger_portion_of_sequence_is_found() {
154 let buf = vec![0x1b, 0x1b, 0x1b];
155 let mut rec = SMLMessageBuilder::Empty;
156
157 rec.record(&buf);
158 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(3));
159 }
160
161 #[test]
164 pub fn incomplete_occurences_must_be_at_the_end() {
165 let buf = vec![0x1b, 0x1b, 0x1b, 0x77];
166 let mut rec = SMLMessageBuilder::Empty;
167
168 rec.record(&buf);
169 assert_eq!(rec, SMLMessageBuilder::Empty);
170 }
171
172 #[test]
173 pub fn finds_complete_sequence() {
174 let buf = &[0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01];
175
176 let mut rec = SMLMessageBuilder::Empty;
177
178 rec.record(buf);
179 assert_eq!(rec, SMLMessageBuilder::Recording(vec![]));
180 }
181
182 #[test]
183 pub fn extends_existing_start_sequence() {
184 let buf = &[0x1b, 0x1b];
185
186 let mut rec = SMLMessageBuilder::Empty;
187
188 rec.record(buf);
189 rec.record(buf);
190 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(4));
191 }
192
193 #[test]
194 pub fn returns_into_empty_if_start_signature_is_not_continued() {
195 let buf = &[0x1b, 0x1b];
196
197 let mut rec = SMLMessageBuilder::Empty;
198
199 rec.record(buf);
200
201 let buf = &[0x1b, 0x1a];
202
203 rec.record(buf);
204 assert_eq!(rec, SMLMessageBuilder::Empty);
205 }
206
207 #[test]
208 pub fn leaves_unchanged_if_empty_buffer_is_recorded() {
209 let buf = &[0x1b, 0x1b];
210
211 let mut rec = SMLMessageBuilder::Empty;
212
213 rec.record(buf);
214
215 let buf = &[];
216
217 rec.record(buf);
218 assert_eq!(rec, SMLMessageBuilder::IncompleteStartSignature(2));
219 }
220
221 #[test]
222 pub fn finds_complete_sequence_in_two_parts() {
223 let buf = &[0x1b, 0x1b, 0x1b, 0x1b];
224 let buf2 = &[0x01, 0x01, 0x01, 0x01];
225
226 let mut rec = SMLMessageBuilder::Empty;
227
228 rec.record(buf);
229 rec.record(buf2);
230 assert_eq!(rec, SMLMessageBuilder::Recording(vec![]));
231 }
232
233 #[test]
234 pub fn puts_buffer_into_recorder() {
235 let buf = &[0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x42, 0x43];
236
237 let mut rec = SMLMessageBuilder::Empty;
238
239 rec.record(buf);
240 assert_eq!(rec, SMLMessageBuilder::Recording(vec![0x42, 0x43]));
241 }
242
243 #[test]
244 pub fn extends_buffer_when_recording() {
245 let buf = &[0x42, 0x43];
246
247 let mut rec = SMLMessageBuilder::Recording(vec![]);
248
249 rec.record(buf);
250 assert_eq!(rec, SMLMessageBuilder::Recording(vec![0x42, 0x43]));
251 }
252
253 #[test]
254 pub fn extends_recording_buffer() {
255 let buf = &[0x44, 0x45];
256
257 let mut rec = SMLMessageBuilder::Recording(vec![0x42, 0x43]);
258
259 rec.record(buf);
260 assert_eq!(
261 rec,
262 SMLMessageBuilder::Recording(vec![0x42, 0x43, 0x44, 0x45])
263 );
264 }
265
266 #[test]
267 pub fn puts_into_ended_state() {
268 let buf = &[0x1b, 0x1b, 0x1b, 0x1b, 0x1a, 0x00, 0x01, 0x02, 0x03];
269
270 let mut rec = SMLMessageBuilder::Recording(vec![0x42, 0x43]);
271
272 rec.record(buf);
273 assert_eq!(
274 rec,
275 SMLMessageBuilder::Complete {
276 data: vec![0x42, 0x43],
277 rest: vec![0x03]
278 }
279 );
280 }
281
282 #[test]
283 pub fn keeps_rest() {
284 let buf = &[0x1b, 0x1b, 0x1b, 0x1b, 0x1a, 0x00, 0x01, 0x02, 0x03];
285
286 let mut rec = SMLMessageBuilder::Recording(vec![0x42, 0x43]);
287
288 rec.record(buf);
289 assert_eq!(
290 rec,
291 SMLMessageBuilder::Complete {
292 data: vec![0x42, 0x43],
293 rest: vec![0x03]
294 }
295 );
296 }
297
298 #[test]
299 pub fn accepts_end_signature_in_two_parts() {
300 let buf = &[0x1b, 0x1b, 0x1b, 0x1b];
301
302 let mut rec = SMLMessageBuilder::Recording(vec![0x42, 0x43]);
303
304 rec.record(buf);
305 let buf = &[0x1a, 0x00, 0x01, 0x02, 0x03];
306 rec.record(buf);
307
308 assert_eq!(
309 rec,
310 SMLMessageBuilder::Complete {
311 data: vec![0x42, 0x43],
312 rest: vec![0x03]
313 }
314 );
315 }
316
317 #[test]
318 pub fn perform_recording_and_finishing_in_one_step() {
319 let buf = &[
320 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x42, 0x43, 0x1b, 0x1b, 0x1b, 0x1b,
321 0x1a, 0x00, 0x01, 0x02,
322 ];
323
324 let mut rec = SMLMessageBuilder::Empty;
325
326 rec.record(buf);
327
328 assert_eq!(
329 rec,
330 SMLMessageBuilder::Complete {
331 data: vec![0x42, 0x43],
332 rest: vec![]
333 }
334 );
335 }
336
337 #[test]
338 pub fn ignores_data_between_end_and_start() {
339 let buf = &[
340 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x42, 0x43, 0x1b, 0x1b, 0x1b,
341 0x1b, 0x1a, 0x00, 0x01, 0x02,
342 ];
343
344 let mut rec = SMLMessageBuilder::Empty;
345
346 rec.record(buf);
347
348 assert_eq!(
349 rec,
350 SMLMessageBuilder::Complete {
351 data: vec![0x42, 0x43],
352 rest: vec![]
353 }
354 );
355 }
356
357 #[test]
358 pub fn takes_first_of_two_messages() {
359 let buf = &[
360 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x42, 0x43, 0x1b, 0x1b, 0x1b, 0x1b,
361 0x1a, 0x00, 0x01, 0x02, 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x43, 0x1b,
362 0x1b, 0x1b, 0x1b, 0x1a, 0x00, 0x02, 0x01,
363 ];
364
365 let mut rec = SMLMessageBuilder::Empty;
366
367 rec.record(buf);
368
369 assert_eq!(
370 rec,
371 SMLMessageBuilder::Complete {
372 data: vec![0x42, 0x43],
373 rest: vec![
374 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01, 0x43, 0x1b, 0x1b, 0x1b, 0x1b,
375 0x1a, 0x00, 0x02, 0x01
376 ]
377 }
378 );
379 }
380}