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() {
155 0
156 } else {
157 front.data_size
158 }
159 }
160
161 fn back(&self) -> Contig {
162 self.contigs[self.contigs.len() - 1]
163 }
164
165 pub fn is_empty(&self) -> bool {
167 !self.front().has_data()
168 }
169
170 fn remove_contig_at(&mut self, at: usize) {
172 debug_assert!(self.contigs[at].has_data());
173
174 for i in at..self.contigs.len() - 1 {
175 if !self.contigs[i].has_data() {
176 return;
177 }
178 self.contigs[i] = self.contigs[i + 1];
179 }
180
181 self.contigs[self.contigs.len() - 1] = Contig::empty();
183 }
184
185 fn add_contig_at(&mut self, at: usize) -> Result<&mut Contig, TooManyHolesError> {
187 if self.back().has_data() {
188 return Err(TooManyHolesError);
189 }
190
191 for i in (at + 1..self.contigs.len()).rev() {
192 self.contigs[i] = self.contigs[i - 1];
193 }
194
195 self.contigs[at] = Contig::empty();
196 Ok(&mut self.contigs[at])
197 }
198
199 pub fn add(&mut self, mut offset: usize, size: usize) -> Result<(), TooManyHolesError> {
202 if size == 0 {
203 return Ok(());
204 }
205
206 let mut i = 0;
207
208 loop {
210 if i == self.contigs.len() {
211 return Err(TooManyHolesError);
213 }
214 let contig = &mut self.contigs[i];
215 if !contig.has_data() {
216 *contig = Contig::hole_and_data(offset, size);
218 return Ok(());
219 }
220 if offset <= contig.total_size() {
221 break;
222 }
223 offset -= contig.total_size();
224 i += 1;
225 }
226
227 let contig = &mut self.contigs[i];
228 if offset < contig.hole_size {
229 if offset + size < contig.hole_size {
232 let new_contig = self.add_contig_at(i)?;
234 new_contig.hole_size = offset;
235 new_contig.data_size = size;
236
237 self.contigs[i + 1].shrink_hole_by(offset + size);
239 return Ok(());
240 }
241
242 contig.shrink_hole_to(offset);
245 }
246
247 let mut j = i + 1;
249 while j < self.contigs.len()
250 && self.contigs[j].has_data()
251 && offset + size >= self.contigs[i].total_size() + self.contigs[j].hole_size
252 {
253 self.contigs[i].data_size += self.contigs[j].total_size();
254 j += 1;
255 }
256 let shift = j - i - 1;
257 if shift != 0 {
258 for x in i + 1..self.contigs.len() {
259 if !self.contigs[x].has_data() {
260 break;
261 }
262
263 self.contigs[x] = self
264 .contigs
265 .get(x + shift)
266 .copied()
267 .unwrap_or_else(Contig::empty);
268 }
269 }
270
271 if offset + size > self.contigs[i].total_size() {
272 let left = offset + size - self.contigs[i].total_size();
274 self.contigs[i].data_size += left;
275
276 if i + 1 < self.contigs.len() && self.contigs[i + 1].has_data() {
278 self.contigs[i + 1].hole_size -= left;
279 }
280 }
281
282 Ok(())
283 }
284
285 pub fn remove_front(&mut self) -> usize {
288 let front = self.front();
289 if front.has_hole() || !front.has_data() {
290 0
291 } else {
292 self.remove_contig_at(0);
293 debug_assert!(front.data_size > 0);
294 front.data_size
295 }
296 }
297
298 pub fn add_then_remove_front(
305 &mut self,
306 offset: usize,
307 size: usize,
308 ) -> Result<usize, TooManyHolesError> {
309 if offset == 0 && size < self.contigs[0].hole_size {
313 self.contigs[0].hole_size -= size;
314 return Ok(size);
315 }
316
317 self.add(offset, size)?;
318 Ok(self.remove_front())
319 }
320
321 pub fn iter_data(&self, first_offset: usize) -> AssemblerIter {
331 AssemblerIter::new(self, first_offset)
332 }
333}
334
335pub struct AssemblerIter<'a> {
336 assembler: &'a Assembler,
337 offset: usize,
338 index: usize,
339 left: usize,
340 right: usize,
341}
342
343impl<'a> AssemblerIter<'a> {
344 fn new(assembler: &'a Assembler, offset: usize) -> AssemblerIter<'a> {
345 AssemblerIter {
346 assembler,
347 offset,
348 index: 0,
349 left: 0,
350 right: 0,
351 }
352 }
353}
354
355impl<'a> Iterator for AssemblerIter<'a> {
356 type Item = (usize, usize);
357
358 fn next(&mut self) -> Option<(usize, usize)> {
359 let mut data_range = None;
360 while data_range.is_none() && self.index < self.assembler.contigs.len() {
361 let contig = self.assembler.contigs[self.index];
362 self.left += contig.hole_size;
363 self.right = self.left + contig.data_size;
364 data_range = if self.left < self.right {
365 let data_range = (self.left + self.offset, self.right + self.offset);
366 self.left = self.right;
367 Some(data_range)
368 } else {
369 None
370 };
371 self.index += 1;
372 }
373 data_range
374 }
375}
376
377#[cfg(test)]
378mod test {
379 use super::*;
380 use std::vec::Vec;
381
382 impl From<Vec<(usize, usize)>> for Assembler {
383 fn from(vec: Vec<(usize, usize)>) -> Assembler {
384 const EMPTY: Contig = Contig::empty();
385
386 let mut contigs = [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT];
387 for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
388 contigs[i] = Contig {
389 hole_size,
390 data_size,
391 };
392 }
393 Assembler { contigs }
394 }
395 }
396
397 macro_rules! contigs {
398 [$( $x:expr ),*] => ({
399 Assembler::from(vec![$( $x ),*])
400 })
401 }
402
403 #[test]
404 fn test_new() {
405 let assr = Assembler::new();
406 assert_eq!(assr, contigs![]);
407 }
408
409 #[test]
410 fn test_empty_add_full() {
411 let mut assr = Assembler::new();
412 assert_eq!(assr.add(0, 16), Ok(()));
413 assert_eq!(assr, contigs![(0, 16)]);
414 }
415
416 #[test]
417 fn test_empty_add_front() {
418 let mut assr = Assembler::new();
419 assert_eq!(assr.add(0, 4), Ok(()));
420 assert_eq!(assr, contigs![(0, 4)]);
421 }
422
423 #[test]
424 fn test_empty_add_back() {
425 let mut assr = Assembler::new();
426 assert_eq!(assr.add(12, 4), Ok(()));
427 assert_eq!(assr, contigs![(12, 4)]);
428 }
429
430 #[test]
431 fn test_empty_add_mid() {
432 let mut assr = Assembler::new();
433 assert_eq!(assr.add(4, 8), Ok(()));
434 assert_eq!(assr, contigs![(4, 8)]);
435 }
436
437 #[test]
438 fn test_partial_add_front() {
439 let mut assr = contigs![(4, 8)];
440 assert_eq!(assr.add(0, 4), Ok(()));
441 assert_eq!(assr, contigs![(0, 12)]);
442 }
443
444 #[test]
445 fn test_partial_add_back() {
446 let mut assr = contigs![(4, 8)];
447 assert_eq!(assr.add(12, 4), Ok(()));
448 assert_eq!(assr, contigs![(4, 12)]);
449 }
450
451 #[test]
452 fn test_partial_add_front_overlap() {
453 let mut assr = contigs![(4, 8)];
454 assert_eq!(assr.add(0, 8), Ok(()));
455 assert_eq!(assr, contigs![(0, 12)]);
456 }
457
458 #[test]
459 fn test_partial_add_front_overlap_split() {
460 let mut assr = contigs![(4, 8)];
461 assert_eq!(assr.add(2, 6), Ok(()));
462 assert_eq!(assr, contigs![(2, 10)]);
463 }
464
465 #[test]
466 fn test_partial_add_back_overlap() {
467 let mut assr = contigs![(4, 8)];
468 assert_eq!(assr.add(8, 8), Ok(()));
469 assert_eq!(assr, contigs![(4, 12)]);
470 }
471
472 #[test]
473 fn test_partial_add_back_overlap_split() {
474 let mut assr = contigs![(4, 8)];
475 assert_eq!(assr.add(10, 4), Ok(()));
476 assert_eq!(assr, contigs![(4, 10)]);
477 }
478
479 #[test]
480 fn test_partial_add_both_overlap() {
481 let mut assr = contigs![(4, 8)];
482 assert_eq!(assr.add(0, 16), Ok(()));
483 assert_eq!(assr, contigs![(0, 16)]);
484 }
485
486 #[test]
487 fn test_partial_add_both_overlap_split() {
488 let mut assr = contigs![(4, 8)];
489 assert_eq!(assr.add(2, 12), Ok(()));
490 assert_eq!(assr, contigs![(2, 12)]);
491 }
492
493 #[test]
494 fn test_rejected_add_keeps_state() {
495 let mut assr = Assembler::new();
496 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
497 assert_eq!(assr.add(c * 10, 3), Ok(()));
498 }
499 let assr_before = assr.clone();
501 assert_eq!(assr.add(1, 3), Err(TooManyHolesError));
502 assert_eq!(assr_before, assr);
503 }
504
505 #[test]
506 fn test_empty_remove_front() {
507 let mut assr = contigs![];
508 assert_eq!(assr.remove_front(), 0);
509 }
510
511 #[test]
512 fn test_trailing_hole_remove_front() {
513 let mut assr = contigs![(0, 4)];
514 assert_eq!(assr.remove_front(), 4);
515 assert_eq!(assr, contigs![]);
516 }
517
518 #[test]
519 fn test_trailing_data_remove_front() {
520 let mut assr = contigs![(0, 4), (4, 4)];
521 assert_eq!(assr.remove_front(), 4);
522 assert_eq!(assr, contigs![(4, 4)]);
523 }
524
525 #[test]
526 fn test_boundary_case_remove_front() {
527 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
528 vec[0] = (0, 2);
529 let mut assr = Assembler::from(vec);
530 assert_eq!(assr.remove_front(), 2);
531 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
532 vec[ASSEMBLER_MAX_SEGMENT_COUNT - 1] = (0, 0);
533 let exp_assr = Assembler::from(vec);
534 assert_eq!(assr, exp_assr);
535 }
536
537 #[test]
538 fn test_shrink_next_hole() {
539 let mut assr = Assembler::new();
540 assert_eq!(assr.add(100, 10), Ok(()));
541 assert_eq!(assr.add(50, 10), Ok(()));
542 assert_eq!(assr.add(40, 30), Ok(()));
543 assert_eq!(assr, contigs![(40, 30), (30, 10)]);
544 }
545
546 #[test]
547 fn test_join_two() {
548 let mut assr = Assembler::new();
549 assert_eq!(assr.add(10, 10), Ok(()));
550 assert_eq!(assr.add(50, 10), Ok(()));
551 assert_eq!(assr.add(15, 40), Ok(()));
552 assert_eq!(assr, contigs![(10, 50)]);
553 }
554
555 #[test]
556 fn test_join_two_reversed() {
557 let mut assr = Assembler::new();
558 assert_eq!(assr.add(50, 10), Ok(()));
559 assert_eq!(assr.add(10, 10), Ok(()));
560 assert_eq!(assr.add(15, 40), Ok(()));
561 assert_eq!(assr, contigs![(10, 50)]);
562 }
563
564 #[test]
565 fn test_join_two_overlong() {
566 let mut assr = Assembler::new();
567 assert_eq!(assr.add(50, 10), Ok(()));
568 assert_eq!(assr.add(10, 10), Ok(()));
569 assert_eq!(assr.add(15, 60), Ok(()));
570 assert_eq!(assr, contigs![(10, 65)]);
571 }
572
573 #[test]
574 fn test_iter_empty() {
575 let assr = Assembler::new();
576 let segments: Vec<_> = assr.iter_data(10).collect();
577 assert_eq!(segments, vec![]);
578 }
579
580 #[test]
581 fn test_iter_full() {
582 let mut assr = Assembler::new();
583 assert_eq!(assr.add(0, 16), Ok(()));
584 let segments: Vec<_> = assr.iter_data(10).collect();
585 assert_eq!(segments, vec![(10, 26)]);
586 }
587
588 #[test]
589 fn test_iter_offset() {
590 let mut assr = Assembler::new();
591 assert_eq!(assr.add(0, 16), Ok(()));
592 let segments: Vec<_> = assr.iter_data(100).collect();
593 assert_eq!(segments, vec![(100, 116)]);
594 }
595
596 #[test]
597 fn test_iter_one_front() {
598 let mut assr = Assembler::new();
599 assert_eq!(assr.add(0, 4), Ok(()));
600 let segments: Vec<_> = assr.iter_data(10).collect();
601 assert_eq!(segments, vec![(10, 14)]);
602 }
603
604 #[test]
605 fn test_iter_one_back() {
606 let mut assr = Assembler::new();
607 assert_eq!(assr.add(12, 4), Ok(()));
608 let segments: Vec<_> = assr.iter_data(10).collect();
609 assert_eq!(segments, vec![(22, 26)]);
610 }
611
612 #[test]
613 fn test_iter_one_mid() {
614 let mut assr = Assembler::new();
615 assert_eq!(assr.add(4, 8), Ok(()));
616 let segments: Vec<_> = assr.iter_data(10).collect();
617 assert_eq!(segments, vec![(14, 22)]);
618 }
619
620 #[test]
621 fn test_iter_one_trailing_gap() {
622 let assr = contigs![(4, 8)];
623 let segments: Vec<_> = assr.iter_data(100).collect();
624 assert_eq!(segments, vec![(104, 112)]);
625 }
626
627 #[test]
628 fn test_iter_two_split() {
629 let assr = contigs![(2, 6), (4, 1)];
630 let segments: Vec<_> = assr.iter_data(100).collect();
631 assert_eq!(segments, vec![(102, 108), (112, 113)]);
632 }
633
634 #[test]
635 fn test_iter_three_split() {
636 let assr = contigs![(2, 6), (2, 1), (2, 2)];
637 let segments: Vec<_> = assr.iter_data(100).collect();
638 assert_eq!(segments, vec![(102, 108), (110, 111), (113, 115)]);
639 }
640
641 #[test]
642 fn test_issue_694() {
643 let mut assr = Assembler::new();
644 assert_eq!(assr.add(0, 1), Ok(()));
645 assert_eq!(assr.add(2, 1), Ok(()));
646 assert_eq!(assr.add(1, 1), Ok(()));
647 }
648
649 #[test]
650 fn test_add_then_remove_front() {
651 let mut assr = Assembler::new();
652 assert_eq!(assr.add(50, 10), Ok(()));
653 assert_eq!(assr.add_then_remove_front(10, 10), Ok(0));
654 assert_eq!(assr, contigs![(10, 10), (30, 10)]);
655 }
656
657 #[test]
658 fn test_add_then_remove_front_at_front() {
659 let mut assr = Assembler::new();
660 assert_eq!(assr.add(50, 10), Ok(()));
661 assert_eq!(assr.add_then_remove_front(0, 10), Ok(10));
662 assert_eq!(assr, contigs![(40, 10)]);
663 }
664
665 #[test]
666 fn test_add_then_remove_front_at_front_touch() {
667 let mut assr = Assembler::new();
668 assert_eq!(assr.add(50, 10), Ok(()));
669 assert_eq!(assr.add_then_remove_front(0, 50), Ok(60));
670 assert_eq!(assr, contigs![]);
671 }
672
673 #[test]
674 fn test_add_then_remove_front_at_front_full() {
675 let mut assr = Assembler::new();
676 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
677 assert_eq!(assr.add(c * 10, 3), Ok(()));
678 }
679 let assr_before = assr.clone();
681 assert_eq!(assr.add_then_remove_front(1, 3), Err(TooManyHolesError));
682 assert_eq!(assr_before, assr);
683 }
684
685 #[test]
686 fn test_add_then_remove_front_at_front_full_offset_0() {
687 let mut assr = Assembler::new();
688 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
689 assert_eq!(assr.add(c * 10, 3), Ok(()));
690 }
691 assert_eq!(assr.add_then_remove_front(0, 3), Ok(3));
692 }
693
694 #[test]
696 fn test_random() {
697 use rand::Rng;
698
699 const MAX_INDEX: usize = 256;
700
701 for max_size in [2, 5, 10, 100] {
702 for _ in 0..300 {
703 let mut assr = Assembler::new();
705 let mut map = [false; MAX_INDEX];
706
707 for _ in 0..60 {
708 let offset = rand::thread_rng().gen_range(0..MAX_INDEX - max_size - 1);
709 let size = rand::thread_rng().gen_range(1..=max_size);
710
711 let res = assr.add(offset, size);
714
715 let mut map2 = map;
717 map2[offset..][..size].fill(true);
718
719 let mut contigs = vec![];
720 let mut hole: usize = 0;
721 let mut data: usize = 0;
722 for b in map2 {
723 if b {
724 data += 1;
725 } else {
726 if data != 0 {
727 contigs.push((hole, data));
728 hole = 0;
729 data = 0;
730 }
731 hole += 1;
732 }
733 }
734
735 let wanted_res = if contigs.len() > ASSEMBLER_MAX_SEGMENT_COUNT {
737 Err(TooManyHolesError)
738 } else {
739 Ok(())
740 };
741 assert_eq!(res, wanted_res);
742 if res.is_ok() {
743 map = map2;
744 assert_eq!(assr, Assembler::from(contigs));
745 }
746 }
747 }
748 }
749 }
750}