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