1use core::fmt;
2
3use crate::config::ASSEMBLER_MAX_SEGMENT_COUNT;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct TooManyHolesError;
7
8impl fmt::Display for TooManyHolesError {
9 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10 write!(f, "too many holes")
11 }
12}
13
14impl core::error::Error for TooManyHolesError {}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18struct Contig {
19 hole_size: usize,
20 data_size: usize,
21}
22
23impl fmt::Display for Contig {
24 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25 if self.has_hole() {
26 write!(f, "({})", self.hole_size)?;
27 }
28 if self.has_hole() && self.has_data() {
29 write!(f, " ")?;
30 }
31 if self.has_data() {
32 write!(f, "{}", self.data_size)?;
33 }
34 Ok(())
35 }
36}
37
38#[cfg(feature = "defmt")]
39impl defmt::Format for Contig {
40 fn format(&self, fmt: defmt::Formatter) {
41 if self.has_hole() {
42 defmt::write!(fmt, "({})", self.hole_size);
43 }
44 if self.has_hole() && self.has_data() {
45 defmt::write!(fmt, " ");
46 }
47 if self.has_data() {
48 defmt::write!(fmt, "{}", self.data_size);
49 }
50 }
51}
52
53impl Contig {
54 const fn empty() -> Contig {
55 Contig {
56 hole_size: 0,
57 data_size: 0,
58 }
59 }
60
61 fn hole_and_data(hole_size: usize, data_size: usize) -> Contig {
62 Contig {
63 hole_size,
64 data_size,
65 }
66 }
67
68 fn has_hole(&self) -> bool {
69 self.hole_size != 0
70 }
71
72 fn has_data(&self) -> bool {
73 self.data_size != 0
74 }
75
76 fn total_size(&self) -> usize {
77 self.hole_size + self.data_size
78 }
79
80 fn shrink_hole_by(&mut self, size: usize) {
81 self.hole_size -= size;
82 }
83
84 fn shrink_hole_to(&mut self, size: usize) {
85 debug_assert!(self.hole_size >= size);
86
87 let total_size = self.total_size();
88 self.hole_size = size;
89 self.data_size = total_size - size;
90 }
91}
92
93#[derive(Debug, PartialEq, Eq, Clone)]
97pub struct Assembler {
98 contigs: [Contig; ASSEMBLER_MAX_SEGMENT_COUNT],
99}
100
101impl fmt::Display for Assembler {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 write!(f, "[ ")?;
104 for contig in self.contigs.iter() {
105 if !contig.has_data() {
106 break;
107 }
108 write!(f, "{contig} ")?;
109 }
110 write!(f, "]")?;
111 Ok(())
112 }
113}
114
115#[cfg(feature = "defmt")]
116impl defmt::Format for Assembler {
117 fn format(&self, fmt: defmt::Formatter) {
118 defmt::write!(fmt, "[ ");
119 for contig in self.contigs.iter() {
120 if !contig.has_data() {
121 break;
122 }
123 defmt::write!(fmt, "{} ", contig);
124 }
125 defmt::write!(fmt, "]");
126 }
127}
128
129impl Assembler {
134 pub const fn new() -> Assembler {
136 const EMPTY: Contig = Contig::empty();
137 Assembler {
138 contigs: [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT],
139 }
140 }
141
142 pub fn clear(&mut self) {
143 self.contigs.fill(Contig::empty());
144 }
145
146 fn front(&self) -> Contig {
147 self.contigs[0]
148 }
149
150 pub fn peek_front(&self) -> usize {
152 let front = self.front();
153 if front.has_hole() { 0 } else { front.data_size }
154 }
155
156 fn back(&self) -> Contig {
157 self.contigs[self.contigs.len() - 1]
158 }
159
160 pub fn is_empty(&self) -> bool {
162 !self.front().has_data()
163 }
164
165 fn remove_contig_at(&mut self, at: usize) {
167 debug_assert!(self.contigs[at].has_data());
168
169 for i in at..self.contigs.len() - 1 {
170 if !self.contigs[i].has_data() {
171 return;
172 }
173 self.contigs[i] = self.contigs[i + 1];
174 }
175
176 self.contigs[self.contigs.len() - 1] = Contig::empty();
178 }
179
180 fn add_contig_at(&mut self, at: usize) -> Result<&mut Contig, TooManyHolesError> {
182 if self.back().has_data() {
183 return Err(TooManyHolesError);
184 }
185
186 for i in (at + 1..self.contigs.len()).rev() {
187 self.contigs[i] = self.contigs[i - 1];
188 }
189
190 self.contigs[at] = Contig::empty();
191 Ok(&mut self.contigs[at])
192 }
193
194 pub fn add(&mut self, mut offset: usize, size: usize) -> Result<(), TooManyHolesError> {
197 if size == 0 {
198 return Ok(());
199 }
200
201 let mut i = 0;
202
203 loop {
205 if i == self.contigs.len() {
206 return Err(TooManyHolesError);
208 }
209 let contig = &mut self.contigs[i];
210 if !contig.has_data() {
211 *contig = Contig::hole_and_data(offset, size);
213 return Ok(());
214 }
215 if offset <= contig.total_size() {
216 break;
217 }
218 offset -= contig.total_size();
219 i += 1;
220 }
221
222 let contig = &mut self.contigs[i];
223 if offset < contig.hole_size {
224 if offset + size < contig.hole_size {
227 let new_contig = self.add_contig_at(i)?;
229 new_contig.hole_size = offset;
230 new_contig.data_size = size;
231
232 self.contigs[i + 1].shrink_hole_by(offset + size);
234 return Ok(());
235 }
236
237 contig.shrink_hole_to(offset);
240 }
241
242 let mut j = i + 1;
244 while j < self.contigs.len()
245 && self.contigs[j].has_data()
246 && offset + size >= self.contigs[i].total_size() + self.contigs[j].hole_size
247 {
248 self.contigs[i].data_size += self.contigs[j].total_size();
249 j += 1;
250 }
251 let shift = j - i - 1;
252 if shift != 0 {
253 for x in i + 1..self.contigs.len() {
254 if !self.contigs[x].has_data() {
255 break;
256 }
257
258 self.contigs[x] = self
259 .contigs
260 .get(x + shift)
261 .copied()
262 .unwrap_or_else(Contig::empty);
263 }
264 }
265
266 if offset + size > self.contigs[i].total_size() {
267 let left = offset + size - self.contigs[i].total_size();
269 self.contigs[i].data_size += left;
270
271 if i + 1 < self.contigs.len() && self.contigs[i + 1].has_data() {
273 self.contigs[i + 1].hole_size -= left;
274 }
275 }
276
277 Ok(())
278 }
279
280 pub fn remove_front(&mut self) -> usize {
283 let front = self.front();
284 if front.has_hole() || !front.has_data() {
285 0
286 } else {
287 self.remove_contig_at(0);
288 debug_assert!(front.data_size > 0);
289 front.data_size
290 }
291 }
292
293 pub fn add_then_remove_front(
300 &mut self,
301 offset: usize,
302 size: usize,
303 ) -> Result<usize, TooManyHolesError> {
304 if offset == 0 && size < self.contigs[0].hole_size {
308 self.contigs[0].hole_size -= size;
309 return Ok(size);
310 }
311
312 self.add(offset, size)?;
313 Ok(self.remove_front())
314 }
315
316 pub fn iter_data(&self) -> impl Iterator<Item = (usize, usize)> + '_ {
326 let mut offset = 0;
327 self.contigs.iter().filter_map(move |contig| {
328 offset += contig.hole_size;
329 let left = offset;
330 offset += contig.data_size;
331 let right = offset;
332 if left < right {
333 Some((left, right))
334 } else {
335 None
336 }
337 })
338 }
339}
340
341#[cfg(test)]
342mod test {
343 use super::*;
344 use std::vec::Vec;
345
346 impl From<Vec<(usize, usize)>> for Assembler {
347 fn from(vec: Vec<(usize, usize)>) -> Assembler {
348 const EMPTY: Contig = Contig::empty();
349
350 let mut contigs = [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT];
351 for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
352 contigs[i] = Contig {
353 hole_size,
354 data_size,
355 };
356 }
357 Assembler { contigs }
358 }
359 }
360
361 macro_rules! contigs {
362 [$( $x:expr ),*] => ({
363 Assembler::from(vec![$( $x ),*])
364 })
365 }
366
367 #[test]
368 fn test_new() {
369 let assr = Assembler::new();
370 assert_eq!(assr, contigs![]);
371 }
372
373 #[test]
374 fn test_empty_add_full() {
375 let mut assr = Assembler::new();
376 assert_eq!(assr.add(0, 16), Ok(()));
377 assert_eq!(assr, contigs![(0, 16)]);
378 }
379
380 #[test]
381 fn test_empty_add_front() {
382 let mut assr = Assembler::new();
383 assert_eq!(assr.add(0, 4), Ok(()));
384 assert_eq!(assr, contigs![(0, 4)]);
385 }
386
387 #[test]
388 fn test_empty_add_back() {
389 let mut assr = Assembler::new();
390 assert_eq!(assr.add(12, 4), Ok(()));
391 assert_eq!(assr, contigs![(12, 4)]);
392 }
393
394 #[test]
395 fn test_empty_add_mid() {
396 let mut assr = Assembler::new();
397 assert_eq!(assr.add(4, 8), Ok(()));
398 assert_eq!(assr, contigs![(4, 8)]);
399 }
400
401 #[test]
402 fn test_partial_add_front() {
403 let mut assr = contigs![(4, 8)];
404 assert_eq!(assr.add(0, 4), Ok(()));
405 assert_eq!(assr, contigs![(0, 12)]);
406 }
407
408 #[test]
409 fn test_partial_add_back() {
410 let mut assr = contigs![(4, 8)];
411 assert_eq!(assr.add(12, 4), Ok(()));
412 assert_eq!(assr, contigs![(4, 12)]);
413 }
414
415 #[test]
416 fn test_partial_add_front_overlap() {
417 let mut assr = contigs![(4, 8)];
418 assert_eq!(assr.add(0, 8), Ok(()));
419 assert_eq!(assr, contigs![(0, 12)]);
420 }
421
422 #[test]
423 fn test_partial_add_front_overlap_split() {
424 let mut assr = contigs![(4, 8)];
425 assert_eq!(assr.add(2, 6), Ok(()));
426 assert_eq!(assr, contigs![(2, 10)]);
427 }
428
429 #[test]
430 fn test_partial_add_back_overlap() {
431 let mut assr = contigs![(4, 8)];
432 assert_eq!(assr.add(8, 8), Ok(()));
433 assert_eq!(assr, contigs![(4, 12)]);
434 }
435
436 #[test]
437 fn test_partial_add_back_overlap_split() {
438 let mut assr = contigs![(4, 8)];
439 assert_eq!(assr.add(10, 4), Ok(()));
440 assert_eq!(assr, contigs![(4, 10)]);
441 }
442
443 #[test]
444 fn test_partial_add_both_overlap() {
445 let mut assr = contigs![(4, 8)];
446 assert_eq!(assr.add(0, 16), Ok(()));
447 assert_eq!(assr, contigs![(0, 16)]);
448 }
449
450 #[test]
451 fn test_partial_add_both_overlap_split() {
452 let mut assr = contigs![(4, 8)];
453 assert_eq!(assr.add(2, 12), Ok(()));
454 assert_eq!(assr, contigs![(2, 12)]);
455 }
456
457 #[test]
458 fn test_rejected_add_keeps_state() {
459 let mut assr = Assembler::new();
460 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
461 assert_eq!(assr.add(c * 10, 3), Ok(()));
462 }
463 let assr_before = assr.clone();
465 assert_eq!(assr.add(1, 3), Err(TooManyHolesError));
466 assert_eq!(assr_before, assr);
467 }
468
469 #[test]
470 fn test_empty_remove_front() {
471 let mut assr = contigs![];
472 assert_eq!(assr.remove_front(), 0);
473 }
474
475 #[test]
476 fn test_trailing_hole_remove_front() {
477 let mut assr = contigs![(0, 4)];
478 assert_eq!(assr.remove_front(), 4);
479 assert_eq!(assr, contigs![]);
480 }
481
482 #[test]
483 fn test_trailing_data_remove_front() {
484 let mut assr = contigs![(0, 4), (4, 4)];
485 assert_eq!(assr.remove_front(), 4);
486 assert_eq!(assr, contigs![(4, 4)]);
487 }
488
489 #[test]
490 fn test_boundary_case_remove_front() {
491 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
492 vec[0] = (0, 2);
493 let mut assr = Assembler::from(vec);
494 assert_eq!(assr.remove_front(), 2);
495 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
496 vec[ASSEMBLER_MAX_SEGMENT_COUNT - 1] = (0, 0);
497 let exp_assr = Assembler::from(vec);
498 assert_eq!(assr, exp_assr);
499 }
500
501 #[test]
502 fn test_shrink_next_hole() {
503 let mut assr = Assembler::new();
504 assert_eq!(assr.add(100, 10), Ok(()));
505 assert_eq!(assr.add(50, 10), Ok(()));
506 assert_eq!(assr.add(40, 30), Ok(()));
507 assert_eq!(assr, contigs![(40, 30), (30, 10)]);
508 }
509
510 #[test]
511 fn test_join_two() {
512 let mut assr = Assembler::new();
513 assert_eq!(assr.add(10, 10), Ok(()));
514 assert_eq!(assr.add(50, 10), Ok(()));
515 assert_eq!(assr.add(15, 40), Ok(()));
516 assert_eq!(assr, contigs![(10, 50)]);
517 }
518
519 #[test]
520 fn test_join_two_reversed() {
521 let mut assr = Assembler::new();
522 assert_eq!(assr.add(50, 10), Ok(()));
523 assert_eq!(assr.add(10, 10), Ok(()));
524 assert_eq!(assr.add(15, 40), Ok(()));
525 assert_eq!(assr, contigs![(10, 50)]);
526 }
527
528 #[test]
529 fn test_join_two_overlong() {
530 let mut assr = Assembler::new();
531 assert_eq!(assr.add(50, 10), Ok(()));
532 assert_eq!(assr.add(10, 10), Ok(()));
533 assert_eq!(assr.add(15, 60), Ok(()));
534 assert_eq!(assr, contigs![(10, 65)]);
535 }
536
537 #[test]
538 fn test_iter_empty() {
539 let assr = Assembler::new();
540 let segments: Vec<_> = assr.iter_data().collect();
541 assert_eq!(segments, vec![]);
542 }
543
544 #[test]
545 fn test_iter_full() {
546 let mut assr = Assembler::new();
547 assert_eq!(assr.add(0, 16), Ok(()));
548 let segments: Vec<_> = assr.iter_data().collect();
549 assert_eq!(segments, vec![(0, 16)]);
550 }
551
552 #[test]
553 fn test_iter_one_front() {
554 let mut assr = Assembler::new();
555 assert_eq!(assr.add(0, 4), Ok(()));
556 let segments: Vec<_> = assr.iter_data().collect();
557 assert_eq!(segments, vec![(0, 4)]);
558 }
559
560 #[test]
561 fn test_iter_one_back() {
562 let mut assr = Assembler::new();
563 assert_eq!(assr.add(12, 4), Ok(()));
564 let segments: Vec<_> = assr.iter_data().collect();
565 assert_eq!(segments, vec![(12, 16)]);
566 }
567
568 #[test]
569 fn test_iter_one_mid() {
570 let mut assr = Assembler::new();
571 assert_eq!(assr.add(4, 8), Ok(()));
572 let segments: Vec<_> = assr.iter_data().collect();
573 assert_eq!(segments, vec![(4, 12)]);
574 }
575
576 #[test]
577 fn test_iter_one_trailing_gap() {
578 let assr = contigs![(4, 8)];
579 let segments: Vec<_> = assr.iter_data().collect();
580 assert_eq!(segments, vec![(4, 12)]);
581 }
582
583 #[test]
584 fn test_iter_two_split() {
585 let assr = contigs![(2, 6), (4, 1)];
586 let segments: Vec<_> = assr.iter_data().collect();
587 assert_eq!(segments, vec![(2, 8), (12, 13)]);
588 }
589
590 #[test]
591 fn test_iter_three_split() {
592 let assr = contigs![(2, 6), (2, 1), (2, 2)];
593 let segments: Vec<_> = assr.iter_data().collect();
594 assert_eq!(segments, vec![(2, 8), (10, 11), (13, 15)]);
595 }
596
597 #[test]
598 fn test_issue_694() {
599 let mut assr = Assembler::new();
600 assert_eq!(assr.add(0, 1), Ok(()));
601 assert_eq!(assr.add(2, 1), Ok(()));
602 assert_eq!(assr.add(1, 1), Ok(()));
603 }
604
605 #[test]
606 fn test_add_then_remove_front() {
607 let mut assr = Assembler::new();
608 assert_eq!(assr.add(50, 10), Ok(()));
609 assert_eq!(assr.add_then_remove_front(10, 10), Ok(0));
610 assert_eq!(assr, contigs![(10, 10), (30, 10)]);
611 }
612
613 #[test]
614 fn test_add_then_remove_front_at_front() {
615 let mut assr = Assembler::new();
616 assert_eq!(assr.add(50, 10), Ok(()));
617 assert_eq!(assr.add_then_remove_front(0, 10), Ok(10));
618 assert_eq!(assr, contigs![(40, 10)]);
619 }
620
621 #[test]
622 fn test_add_then_remove_front_at_front_touch() {
623 let mut assr = Assembler::new();
624 assert_eq!(assr.add(50, 10), Ok(()));
625 assert_eq!(assr.add_then_remove_front(0, 50), Ok(60));
626 assert_eq!(assr, contigs![]);
627 }
628
629 #[test]
630 fn test_add_then_remove_front_at_front_full() {
631 let mut assr = Assembler::new();
632 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
633 assert_eq!(assr.add(c * 10, 3), Ok(()));
634 }
635 let assr_before = assr.clone();
637 assert_eq!(assr.add_then_remove_front(1, 3), Err(TooManyHolesError));
638 assert_eq!(assr_before, assr);
639 }
640
641 #[test]
642 fn test_add_then_remove_front_at_front_full_offset_0() {
643 let mut assr = Assembler::new();
644 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
645 assert_eq!(assr.add(c * 10, 3), Ok(()));
646 }
647 assert_eq!(assr.add_then_remove_front(0, 3), Ok(3));
648 }
649
650 #[test]
652 fn test_random() {
653 use rand::Rng;
654
655 const MAX_INDEX: usize = 256;
656
657 for max_size in [2, 5, 10, 100] {
658 for _ in 0..300 {
659 let mut assr = Assembler::new();
661 let mut map = [false; MAX_INDEX];
662
663 for _ in 0..60 {
664 let offset = rand::thread_rng().gen_range(0..MAX_INDEX - max_size - 1);
665 let size = rand::thread_rng().gen_range(1..=max_size);
666
667 let res = assr.add(offset, size);
670
671 let mut map2 = map;
673 map2[offset..][..size].fill(true);
674
675 let mut contigs = vec![];
676 let mut hole: usize = 0;
677 let mut data: usize = 0;
678 for b in map2 {
679 if b {
680 data += 1;
681 } else {
682 if data != 0 {
683 contigs.push((hole, data));
684 hole = 0;
685 data = 0;
686 }
687 hole += 1;
688 }
689 }
690
691 let wanted_res = if contigs.len() > ASSEMBLER_MAX_SEGMENT_COUNT {
693 Err(TooManyHolesError)
694 } else {
695 Ok(())
696 };
697 assert_eq!(res, wanted_res);
698 if res.is_ok() {
699 map = map2;
700 assert_eq!(assr, Assembler::from(contigs));
701 }
702 }
703 }
704 }
705 }
706}