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) -> impl Iterator<Item = (usize, usize)> + '_ {
327 let mut offset = 0;
328 self.contigs.iter().filter_map(move |contig| {
329 offset += contig.hole_size;
330 let left = offset;
331 offset += contig.data_size;
332 let right = offset;
333 if left < right {
334 Some((left, right))
335 } else {
336 None
337 }
338 })
339 }
340}
341
342#[cfg(test)]
343mod test {
344 use super::*;
345 use std::vec::Vec;
346
347 impl From<Vec<(usize, usize)>> for Assembler {
348 fn from(vec: Vec<(usize, usize)>) -> Assembler {
349 const EMPTY: Contig = Contig::empty();
350
351 let mut contigs = [EMPTY; ASSEMBLER_MAX_SEGMENT_COUNT];
352 for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
353 contigs[i] = Contig {
354 hole_size,
355 data_size,
356 };
357 }
358 Assembler { contigs }
359 }
360 }
361
362 macro_rules! contigs {
363 [$( $x:expr ),*] => ({
364 Assembler::from(vec![$( $x ),*])
365 })
366 }
367
368 #[test]
369 fn test_new() {
370 let assr = Assembler::new();
371 assert_eq!(assr, contigs![]);
372 }
373
374 #[test]
375 fn test_empty_add_full() {
376 let mut assr = Assembler::new();
377 assert_eq!(assr.add(0, 16), Ok(()));
378 assert_eq!(assr, contigs![(0, 16)]);
379 }
380
381 #[test]
382 fn test_empty_add_front() {
383 let mut assr = Assembler::new();
384 assert_eq!(assr.add(0, 4), Ok(()));
385 assert_eq!(assr, contigs![(0, 4)]);
386 }
387
388 #[test]
389 fn test_empty_add_back() {
390 let mut assr = Assembler::new();
391 assert_eq!(assr.add(12, 4), Ok(()));
392 assert_eq!(assr, contigs![(12, 4)]);
393 }
394
395 #[test]
396 fn test_empty_add_mid() {
397 let mut assr = Assembler::new();
398 assert_eq!(assr.add(4, 8), Ok(()));
399 assert_eq!(assr, contigs![(4, 8)]);
400 }
401
402 #[test]
403 fn test_partial_add_front() {
404 let mut assr = contigs![(4, 8)];
405 assert_eq!(assr.add(0, 4), Ok(()));
406 assert_eq!(assr, contigs![(0, 12)]);
407 }
408
409 #[test]
410 fn test_partial_add_back() {
411 let mut assr = contigs![(4, 8)];
412 assert_eq!(assr.add(12, 4), Ok(()));
413 assert_eq!(assr, contigs![(4, 12)]);
414 }
415
416 #[test]
417 fn test_partial_add_front_overlap() {
418 let mut assr = contigs![(4, 8)];
419 assert_eq!(assr.add(0, 8), Ok(()));
420 assert_eq!(assr, contigs![(0, 12)]);
421 }
422
423 #[test]
424 fn test_partial_add_front_overlap_split() {
425 let mut assr = contigs![(4, 8)];
426 assert_eq!(assr.add(2, 6), Ok(()));
427 assert_eq!(assr, contigs![(2, 10)]);
428 }
429
430 #[test]
431 fn test_partial_add_back_overlap() {
432 let mut assr = contigs![(4, 8)];
433 assert_eq!(assr.add(8, 8), Ok(()));
434 assert_eq!(assr, contigs![(4, 12)]);
435 }
436
437 #[test]
438 fn test_partial_add_back_overlap_split() {
439 let mut assr = contigs![(4, 8)];
440 assert_eq!(assr.add(10, 4), Ok(()));
441 assert_eq!(assr, contigs![(4, 10)]);
442 }
443
444 #[test]
445 fn test_partial_add_both_overlap() {
446 let mut assr = contigs![(4, 8)];
447 assert_eq!(assr.add(0, 16), Ok(()));
448 assert_eq!(assr, contigs![(0, 16)]);
449 }
450
451 #[test]
452 fn test_partial_add_both_overlap_split() {
453 let mut assr = contigs![(4, 8)];
454 assert_eq!(assr.add(2, 12), Ok(()));
455 assert_eq!(assr, contigs![(2, 12)]);
456 }
457
458 #[test]
459 fn test_rejected_add_keeps_state() {
460 let mut assr = Assembler::new();
461 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
462 assert_eq!(assr.add(c * 10, 3), Ok(()));
463 }
464 let assr_before = assr.clone();
466 assert_eq!(assr.add(1, 3), Err(TooManyHolesError));
467 assert_eq!(assr_before, assr);
468 }
469
470 #[test]
471 fn test_empty_remove_front() {
472 let mut assr = contigs![];
473 assert_eq!(assr.remove_front(), 0);
474 }
475
476 #[test]
477 fn test_trailing_hole_remove_front() {
478 let mut assr = contigs![(0, 4)];
479 assert_eq!(assr.remove_front(), 4);
480 assert_eq!(assr, contigs![]);
481 }
482
483 #[test]
484 fn test_trailing_data_remove_front() {
485 let mut assr = contigs![(0, 4), (4, 4)];
486 assert_eq!(assr.remove_front(), 4);
487 assert_eq!(assr, contigs![(4, 4)]);
488 }
489
490 #[test]
491 fn test_boundary_case_remove_front() {
492 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
493 vec[0] = (0, 2);
494 let mut assr = Assembler::from(vec);
495 assert_eq!(assr.remove_front(), 2);
496 let mut vec = vec![(1, 1); ASSEMBLER_MAX_SEGMENT_COUNT];
497 vec[ASSEMBLER_MAX_SEGMENT_COUNT - 1] = (0, 0);
498 let exp_assr = Assembler::from(vec);
499 assert_eq!(assr, exp_assr);
500 }
501
502 #[test]
503 fn test_shrink_next_hole() {
504 let mut assr = Assembler::new();
505 assert_eq!(assr.add(100, 10), Ok(()));
506 assert_eq!(assr.add(50, 10), Ok(()));
507 assert_eq!(assr.add(40, 30), Ok(()));
508 assert_eq!(assr, contigs![(40, 30), (30, 10)]);
509 }
510
511 #[test]
512 fn test_join_two() {
513 let mut assr = Assembler::new();
514 assert_eq!(assr.add(10, 10), Ok(()));
515 assert_eq!(assr.add(50, 10), Ok(()));
516 assert_eq!(assr.add(15, 40), Ok(()));
517 assert_eq!(assr, contigs![(10, 50)]);
518 }
519
520 #[test]
521 fn test_join_two_reversed() {
522 let mut assr = Assembler::new();
523 assert_eq!(assr.add(50, 10), Ok(()));
524 assert_eq!(assr.add(10, 10), Ok(()));
525 assert_eq!(assr.add(15, 40), Ok(()));
526 assert_eq!(assr, contigs![(10, 50)]);
527 }
528
529 #[test]
530 fn test_join_two_overlong() {
531 let mut assr = Assembler::new();
532 assert_eq!(assr.add(50, 10), Ok(()));
533 assert_eq!(assr.add(10, 10), Ok(()));
534 assert_eq!(assr.add(15, 60), Ok(()));
535 assert_eq!(assr, contigs![(10, 65)]);
536 }
537
538 #[test]
539 fn test_iter_empty() {
540 let assr = Assembler::new();
541 let segments: Vec<_> = assr.iter_data().collect();
542 assert_eq!(segments, vec![]);
543 }
544
545 #[test]
546 fn test_iter_full() {
547 let mut assr = Assembler::new();
548 assert_eq!(assr.add(0, 16), Ok(()));
549 let segments: Vec<_> = assr.iter_data().collect();
550 assert_eq!(segments, vec![(0, 16)]);
551 }
552
553 #[test]
554 fn test_iter_one_front() {
555 let mut assr = Assembler::new();
556 assert_eq!(assr.add(0, 4), Ok(()));
557 let segments: Vec<_> = assr.iter_data().collect();
558 assert_eq!(segments, vec![(0, 4)]);
559 }
560
561 #[test]
562 fn test_iter_one_back() {
563 let mut assr = Assembler::new();
564 assert_eq!(assr.add(12, 4), Ok(()));
565 let segments: Vec<_> = assr.iter_data().collect();
566 assert_eq!(segments, vec![(12, 16)]);
567 }
568
569 #[test]
570 fn test_iter_one_mid() {
571 let mut assr = Assembler::new();
572 assert_eq!(assr.add(4, 8), Ok(()));
573 let segments: Vec<_> = assr.iter_data().collect();
574 assert_eq!(segments, vec![(4, 12)]);
575 }
576
577 #[test]
578 fn test_iter_one_trailing_gap() {
579 let assr = contigs![(4, 8)];
580 let segments: Vec<_> = assr.iter_data().collect();
581 assert_eq!(segments, vec![(4, 12)]);
582 }
583
584 #[test]
585 fn test_iter_two_split() {
586 let assr = contigs![(2, 6), (4, 1)];
587 let segments: Vec<_> = assr.iter_data().collect();
588 assert_eq!(segments, vec![(2, 8), (12, 13)]);
589 }
590
591 #[test]
592 fn test_iter_three_split() {
593 let assr = contigs![(2, 6), (2, 1), (2, 2)];
594 let segments: Vec<_> = assr.iter_data().collect();
595 assert_eq!(segments, vec![(2, 8), (10, 11), (13, 15)]);
596 }
597
598 #[test]
599 fn test_issue_694() {
600 let mut assr = Assembler::new();
601 assert_eq!(assr.add(0, 1), Ok(()));
602 assert_eq!(assr.add(2, 1), Ok(()));
603 assert_eq!(assr.add(1, 1), Ok(()));
604 }
605
606 #[test]
607 fn test_add_then_remove_front() {
608 let mut assr = Assembler::new();
609 assert_eq!(assr.add(50, 10), Ok(()));
610 assert_eq!(assr.add_then_remove_front(10, 10), Ok(0));
611 assert_eq!(assr, contigs![(10, 10), (30, 10)]);
612 }
613
614 #[test]
615 fn test_add_then_remove_front_at_front() {
616 let mut assr = Assembler::new();
617 assert_eq!(assr.add(50, 10), Ok(()));
618 assert_eq!(assr.add_then_remove_front(0, 10), Ok(10));
619 assert_eq!(assr, contigs![(40, 10)]);
620 }
621
622 #[test]
623 fn test_add_then_remove_front_at_front_touch() {
624 let mut assr = Assembler::new();
625 assert_eq!(assr.add(50, 10), Ok(()));
626 assert_eq!(assr.add_then_remove_front(0, 50), Ok(60));
627 assert_eq!(assr, contigs![]);
628 }
629
630 #[test]
631 fn test_add_then_remove_front_at_front_full() {
632 let mut assr = Assembler::new();
633 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
634 assert_eq!(assr.add(c * 10, 3), Ok(()));
635 }
636 let assr_before = assr.clone();
638 assert_eq!(assr.add_then_remove_front(1, 3), Err(TooManyHolesError));
639 assert_eq!(assr_before, assr);
640 }
641
642 #[test]
643 fn test_add_then_remove_front_at_front_full_offset_0() {
644 let mut assr = Assembler::new();
645 for c in 1..=ASSEMBLER_MAX_SEGMENT_COUNT {
646 assert_eq!(assr.add(c * 10, 3), Ok(()));
647 }
648 assert_eq!(assr.add_then_remove_front(0, 3), Ok(3));
649 }
650
651 #[test]
653 fn test_random() {
654 use rand::Rng;
655
656 const MAX_INDEX: usize = 256;
657
658 for max_size in [2, 5, 10, 100] {
659 for _ in 0..300 {
660 let mut assr = Assembler::new();
662 let mut map = [false; MAX_INDEX];
663
664 for _ in 0..60 {
665 let offset = rand::thread_rng().gen_range(0..MAX_INDEX - max_size - 1);
666 let size = rand::thread_rng().gen_range(1..=max_size);
667
668 let res = assr.add(offset, size);
671
672 let mut map2 = map;
674 map2[offset..][..size].fill(true);
675
676 let mut contigs = vec![];
677 let mut hole: usize = 0;
678 let mut data: usize = 0;
679 for b in map2 {
680 if b {
681 data += 1;
682 } else {
683 if data != 0 {
684 contigs.push((hole, data));
685 hole = 0;
686 data = 0;
687 }
688 hole += 1;
689 }
690 }
691
692 let wanted_res = if contigs.len() > ASSEMBLER_MAX_SEGMENT_COUNT {
694 Err(TooManyHolesError)
695 } else {
696 Ok(())
697 };
698 assert_eq!(res, wanted_res);
699 if res.is_ok() {
700 map = map2;
701 assert_eq!(assr, Assembler::from(contigs));
702 }
703 }
704 }
705 }
706 }
707}