1use spacepackets::cfdp::{LargeFileFlag, pdu::nak::NakPduCreatorWithReservedSeqReqsBuf};
14
15#[derive(Debug, PartialEq, Eq, thiserror::Error)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[non_exhaustive]
19pub enum LostSegmentError {
20    #[error("store is full")]
21    StoreFull,
22    #[error("segment is empty")]
23    EmptySegment,
24    #[error("segment start {0} is larger than segment end {1}")]
25    StartLargerThanEnd(u64, u64),
26    #[error("large file segments are not supported")]
27    LargeFileSegmentNotSupported,
28    #[error("invalid segment boundary detected for lost segment ({0}, {1})")]
29    InvalidSegmentBoundary(u64, u64),
30}
31
32#[derive(Debug, PartialEq, Eq, thiserror::Error)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35#[non_exhaustive]
36pub enum LostSegmentWriteError {
37    #[error("number of segments mismatch: expected {expected}, actual {actual}")]
38    NumberOfSegmentsMismatch { expected: usize, actual: usize },
39    #[error("buffer size not equal to required size")]
40    BufferSizeMissmatch { expected: usize, actual: usize },
41    #[error("large file segment not compatible to normal file size")]
42    LargeSegmentForNormalFileSize,
43}
44
45pub trait LostSegmentStore {
50    type Iter<'a>: Iterator<Item = (u64, u64)> + 'a
52    where
53        Self: 'a;
54
55    fn iter(&self) -> Self::Iter<'_>;
57
58    fn number_of_segments(&self) -> usize;
60
61    fn supports_large_file_size(&self) -> bool;
64    fn capacity(&self) -> Option<usize>;
65    fn reset(&mut self);
66
67    fn segment_in_store(&self, segment: (u64, u64)) -> bool;
72
73    fn add_lost_segment(&mut self, lost_seg: (u64, u64)) -> Result<(), LostSegmentError>;
80
81    fn remove_lost_segment(
89        &mut self,
90        segment_to_remove: (u64, u64),
91    ) -> Result<bool, LostSegmentError>;
92
93    fn coalesce_lost_segments(&mut self) -> Result<(), LostSegmentError>;
96
97    #[inline]
98    fn is_empty(&self) -> bool {
99        self.number_of_segments() == 0
100    }
101
102    fn write_segments_to_bytes(
105        &self,
106        buf: &mut [u8],
107        file_flag: LargeFileFlag,
108    ) -> Result<usize, LostSegmentWriteError> {
109        let len_per_segment = if file_flag == LargeFileFlag::Large {
110            16
111        } else {
112            8
113        };
114        let written_len = self.number_of_segments() * len_per_segment;
115        if written_len != buf.len() {
116            return Err(LostSegmentWriteError::BufferSizeMissmatch {
117                expected: written_len,
118                actual: buf.len(),
119            });
120        }
121        let mut current_index = 0;
122        for segment in self.iter() {
123            match file_flag {
124                LargeFileFlag::Normal => {
125                    if segment.0 > u32::MAX as u64 || segment.1 > u32::MAX as u64 {
126                        return Err(LostSegmentWriteError::LargeSegmentForNormalFileSize);
127                    }
128                    buf[current_index..current_index + 4]
129                        .copy_from_slice(&(segment.0 as u32).to_be_bytes());
130                    current_index += 4;
131                    buf[current_index..current_index + 4]
132                        .copy_from_slice(&(segment.1 as u32).to_be_bytes());
133                    current_index += 4;
134                }
135                LargeFileFlag::Large => {
136                    buf[current_index..current_index + 8]
137                        .copy_from_slice(&(segment.0).to_be_bytes());
138                    current_index += 8;
139                    buf[current_index..current_index + 8]
140                        .copy_from_slice(&(segment.1).to_be_bytes());
141                    current_index += 8;
142                }
143            }
144        }
145        Ok(current_index)
146    }
147
148    fn write_to_nak_segment_list(
155        &self,
156        nak_builder: &mut NakPduCreatorWithReservedSeqReqsBuf,
157        first_segment_request_for_metadata: bool,
158    ) -> Result<usize, LostSegmentWriteError> {
159        let file_flag = nak_builder.pdu_header().common_pdu_conf().file_flag;
160        let mut relevant_size = self.number_of_segments();
161        if first_segment_request_for_metadata {
162            relevant_size += 1;
163        }
164        if nak_builder.num_segment_reqs() != relevant_size {
165            return Err(LostSegmentWriteError::NumberOfSegmentsMismatch {
166                expected: self.number_of_segments(),
167                actual: nak_builder.num_segment_reqs(),
168            });
169        }
170        let mut buf = nak_builder.segment_request_buffer_mut();
171        let mut written_len = 0;
172        if first_segment_request_for_metadata {
173            match file_flag {
174                LargeFileFlag::Normal => {
175                    buf[0..8].fill(0);
176                    buf = &mut buf[8..];
177                    written_len += 8;
178                }
179                LargeFileFlag::Large => {
180                    buf[0..16].fill(0);
181                    buf = &mut buf[16..];
182                    written_len += 16;
183                }
184            }
185        }
186        written_len += self.write_segments_to_bytes(buf, file_flag)?;
187        Ok(written_len)
188    }
189}
190
191#[cfg(feature = "alloc")]
196#[derive(Debug, Default)]
197pub struct LostSegmentsList {
198    list: alloc::vec::Vec<(u64, u64)>,
199    opt_capacity: Option<usize>,
200}
201
202#[cfg(feature = "alloc")]
203impl LostSegmentsList {
204    pub fn new(opt_capacity: Option<usize>) -> Self {
205        Self {
206            list: alloc::vec::Vec::new(),
207            opt_capacity,
208        }
209    }
210}
211
212#[cfg(feature = "alloc")]
213impl LostSegmentStore for LostSegmentsList {
214    type Iter<'a>
215        = core::iter::Cloned<core::slice::Iter<'a, (u64, u64)>>
216    where
217        Self: 'a;
218
219    fn iter(&self) -> Self::Iter<'_> {
220        self.list.iter().cloned()
221    }
222
223    #[inline]
224    fn number_of_segments(&self) -> usize {
225        self.list.len()
226    }
227
228    #[inline]
229    fn supports_large_file_size(&self) -> bool {
230        true
231    }
232
233    #[inline]
234    fn capacity(&self) -> Option<usize> {
235        self.opt_capacity
236    }
237
238    #[inline]
239    fn reset(&mut self) {
240        self.list.clear();
241    }
242
243    fn segment_in_store(&self, segment: (u64, u64)) -> bool {
244        for (seg_start, seg_end) in &self.list {
245            if segment.0 >= *seg_start && segment.1 <= *seg_end {
246                return true;
247            }
248        }
249        false
250    }
251
252    #[inline]
253    fn add_lost_segment(&mut self, lost_seg: (u64, u64)) -> Result<(), LostSegmentError> {
254        if lost_seg.1 == lost_seg.0 {
255            return Err(LostSegmentError::EmptySegment);
256        }
257        if lost_seg.0 > lost_seg.1 {
258            return Err(LostSegmentError::StartLargerThanEnd(lost_seg.0, lost_seg.1));
259        }
260        if let Some(capacity) = self.opt_capacity {
261            if self.list.len() == capacity {
262                return Err(LostSegmentError::StoreFull);
263            }
264        }
265        self.list.push((lost_seg.0, lost_seg.1));
266        Ok(())
267    }
268
269    fn coalesce_lost_segments(&mut self) -> Result<(), LostSegmentError> {
270        self.list.retain(|&(s, e)| e > s);
272        if self.list.len() <= 1 {
273            return Ok(());
274        }
275
276        self.list
278            .as_mut_slice()
279            .sort_unstable_by_key(|&(start, _)| start);
280
281        let mut w = 0usize;
283        for i in 0..self.list.len() {
284            if w == 0 {
285                self.list[w] = self.list[i];
286                w = 1;
287                continue;
288            }
289
290            let (prev_s, mut prev_e) = self.list[w - 1];
291            let (s, e) = self.list[i];
292
293            if s <= prev_e {
294                if e > prev_e {
296                    prev_e = e;
297                    self.list[w - 1] = (prev_s, prev_e);
298                }
299            } else {
300                self.list[w] = (s, e);
302                w += 1;
303            }
304        }
305
306        self.list.truncate(w);
308        Ok(())
309    }
310
311    #[inline]
312    fn remove_lost_segment(
313        &mut self,
314        segment_to_remove: (u64, u64),
315    ) -> Result<bool, LostSegmentError> {
316        if segment_to_remove.1 == segment_to_remove.0 {
317            return Err(LostSegmentError::EmptySegment);
318        }
319        if segment_to_remove.0 > segment_to_remove.1 {
320            return Err(LostSegmentError::StartLargerThanEnd(
321                segment_to_remove.0,
322                segment_to_remove.1,
323            ));
324        }
325
326        let idx = match self
328            .list
329            .binary_search_by_key(&segment_to_remove.0, |&(s, _)| s)
330        {
331            Ok(idx) => idx,
332            Err(insertion) => insertion.saturating_sub(1),
333        };
334
335        let mut i = idx;
337        let list_len = self.list.len();
338        while i < self.list.len() && self.list[i].0 <= segment_to_remove.1 {
339            let seg = &mut self.list[i];
340
341            if seg.1 < segment_to_remove.0 {
343                i += 1;
344                continue;
345            }
346
347            if seg == &segment_to_remove {
349                self.list.remove(i);
350                return Ok(true);
352            }
353
354            if (segment_to_remove.0 < seg.0 && segment_to_remove.1 > seg.0)
356                || (segment_to_remove.1 > seg.1 && segment_to_remove.0 < seg.1)
357            {
358                return Err(LostSegmentError::InvalidSegmentBoundary(
359                    segment_to_remove.0,
360                    segment_to_remove.1,
361                ));
362            }
363
364            let mut changed = false;
367
368            if segment_to_remove.1 == seg.1 {
370                seg.1 = segment_to_remove.0;
371                changed = true;
372            }
373            if segment_to_remove.0 == seg.0 {
375                seg.0 = segment_to_remove.1;
376                changed = true;
377            }
378            if segment_to_remove.0 > seg.0 && segment_to_remove.1 < seg.1 {
380                if list_len == self.opt_capacity.unwrap_or(usize::MAX) {
381                    return Err(LostSegmentError::StoreFull);
382                }
383                let end_of_right_remainder = seg.1;
385                seg.1 = segment_to_remove.0;
387                self.list
388                    .insert(i + 1, (segment_to_remove.1, end_of_right_remainder));
389                changed = true;
390            }
391
392            if changed {
394                return Ok(true);
395            }
396
397            i += 1;
398        }
399        Ok(false)
400    }
401}
402
403#[derive(Default, Debug)]
405pub struct LostSegmentsListHeapless<const N: usize, T> {
406    list: heapless::vec::Vec<(T, T), N>,
407}
408
409pub type LostSegmentsListNormalFilesHeapless<const N: usize> = LostSegmentsListHeapless<N, u32>;
412
413impl<const N: usize, T> LostSegmentsListHeapless<N, T> {
414    pub fn new() -> Self {
415        Self {
416            list: heapless::Vec::new(),
417        }
418    }
419
420    #[inline]
421    fn num_lost_segments(&self) -> usize {
422        self.list.len()
423    }
424
425    #[inline]
426    fn capacity(&self) -> Option<usize> {
427        Some(N)
428    }
429
430    #[inline]
431    fn reset(&mut self) {
432        self.list.clear();
433    }
434}
435
436impl<const N: usize, T: Copy + Clone + Ord> LostSegmentsListHeapless<N, T> {
437    fn coalesce_lost_segments(&mut self) -> Result<(), LostSegmentError> {
438        self.list.retain(|&(s, e)| e > s);
440        if self.list.len() <= 1 {
441            return Ok(());
442        }
443
444        self.list
446            .as_mut_slice()
447            .sort_unstable_by(|a, b| a.0.cmp(&b.0).then(a.1.cmp(&b.1)));
448
449        let mut w = 0usize;
451        for i in 0..self.list.len() {
452            if w == 0 {
453                self.list[w] = self.list[i];
454                w = 1;
455                continue;
456            }
457
458            let (prev_s, mut prev_e) = self.list[w - 1];
459            let (s, e) = self.list[i];
460
461            if s <= prev_e {
462                if e > prev_e {
464                    prev_e = e;
465                    self.list[w - 1] = (prev_s, prev_e);
466                }
467            } else {
468                self.list[w] = (s, e);
470                w += 1;
471            }
472        }
473
474        self.list.truncate(w);
476        Ok(())
477    }
478}
479
480impl<const N: usize> LostSegmentStore for LostSegmentsListHeapless<N, u64> {
481    type Iter<'a>
482        = core::iter::Cloned<core::slice::Iter<'a, (u64, u64)>>
483    where
484        Self: 'a;
485
486    fn iter(&self) -> Self::Iter<'_> {
487        self.list.iter().cloned()
488    }
489
490    fn add_lost_segment(&mut self, lost_seg: (u64, u64)) -> Result<(), LostSegmentError> {
491        if lost_seg.1 == lost_seg.0 {
492            return Err(LostSegmentError::EmptySegment);
493        }
494        if lost_seg.0 > lost_seg.1 {
495            return Err(LostSegmentError::StartLargerThanEnd(lost_seg.0, lost_seg.1));
496        }
497        if self.list.is_full() {
498            return Err(LostSegmentError::StoreFull);
499        }
500        self.list.push(lost_seg).ok();
501        Ok(())
502    }
503
504    fn remove_lost_segment(
505        &mut self,
506        segment_to_remove: (u64, u64),
507    ) -> Result<bool, LostSegmentError> {
508        if segment_to_remove.1 == segment_to_remove.0 {
509            return Err(LostSegmentError::EmptySegment);
510        }
511        if segment_to_remove.0 > segment_to_remove.1 {
512            return Err(LostSegmentError::StartLargerThanEnd(
513                segment_to_remove.0,
514                segment_to_remove.1,
515            ));
516        }
517
518        let idx = match self
520            .list
521            .binary_search_by_key(&segment_to_remove.0, |&(s, _)| s)
522        {
523            Ok(idx) => idx,
524            Err(insertion) => insertion.saturating_sub(1),
525        };
526
527        let mut i = idx;
529        let list_len = self.list.len();
530        while i < self.list.len() && self.list[i].0 <= segment_to_remove.1 {
531            let seg = &mut self.list[i];
532
533            if seg.1 < segment_to_remove.0 {
535                i += 1;
536                continue;
537            }
538
539            if seg == &segment_to_remove {
541                self.list.remove(i);
542                return Ok(true);
543            }
544
545            if (segment_to_remove.0 < seg.0 && segment_to_remove.1 > seg.0)
547                || (segment_to_remove.1 > seg.1 && segment_to_remove.0 < seg.1)
548            {
549                return Err(LostSegmentError::InvalidSegmentBoundary(
550                    segment_to_remove.0,
551                    segment_to_remove.1,
552                ));
553            }
554
555            let mut changed = false;
558
559            if segment_to_remove.1 == seg.1 {
561                seg.1 = segment_to_remove.0;
562                changed = true;
563            }
564            if segment_to_remove.0 == seg.0 {
566                seg.0 = segment_to_remove.1;
567                changed = true;
568            }
569            if segment_to_remove.0 > seg.0 && segment_to_remove.1 < seg.1 {
571                if list_len == N {
572                    return Err(LostSegmentError::StoreFull);
573                }
574                let end_of_right_remainder = seg.1;
576                seg.1 = segment_to_remove.0;
578                self.list
579                    .insert(i + 1, (segment_to_remove.1, end_of_right_remainder))
580                    .unwrap();
581                changed = true;
582            }
583
584            if changed {
586                return Ok(true);
587            }
588
589            i += 1;
590        }
591        Ok(false)
592    }
593
594    fn coalesce_lost_segments(&mut self) -> Result<(), LostSegmentError> {
595        self.coalesce_lost_segments()
596    }
597
598    fn number_of_segments(&self) -> usize {
599        self.num_lost_segments()
600    }
601
602    fn supports_large_file_size(&self) -> bool {
603        true
604    }
605
606    fn capacity(&self) -> Option<usize> {
607        self.capacity()
608    }
609
610    fn reset(&mut self) {
611        self.reset();
612    }
613
614    fn segment_in_store(&self, segment: (u64, u64)) -> bool {
615        for (seg_start, seg_end) in &self.list {
616            if segment.0 >= *seg_start && segment.1 <= *seg_end {
617                return true;
618            }
619        }
620        false
621    }
622}
623
624impl<const N: usize> LostSegmentStore for LostSegmentsListHeapless<N, u32> {
625    type Iter<'a>
626        = core::iter::Map<core::slice::Iter<'a, (u32, u32)>, fn(&(u32, u32)) -> (u64, u64)>
627    where
628        Self: 'a;
629
630    fn iter(&self) -> Self::Iter<'_> {
631        self.list.iter().map(|pair| (pair.0 as u64, pair.1 as u64))
632    }
633
634    fn add_lost_segment(&mut self, lost_seg: (u64, u64)) -> Result<(), LostSegmentError> {
635        if lost_seg.1 == lost_seg.0 {
636            return Err(LostSegmentError::EmptySegment);
637        }
638        if lost_seg.0 > lost_seg.1 {
639            return Err(LostSegmentError::StartLargerThanEnd(lost_seg.0, lost_seg.1));
640        }
641        if lost_seg.1 > u32::MAX as u64 || lost_seg.0 > u32::MAX as u64 {
642            return Err(LostSegmentError::LargeFileSegmentNotSupported);
643        }
644        if self.list.is_full() {
645            return Err(LostSegmentError::StoreFull);
646        }
647        self.list.push((lost_seg.0 as u32, lost_seg.1 as u32)).ok();
648        Ok(())
649    }
650
651    fn remove_lost_segment(
652        &mut self,
653        segment_to_remove: (u64, u64),
654    ) -> Result<bool, LostSegmentError> {
655        if segment_to_remove.0 > u32::MAX as u64 || segment_to_remove.1 > u32::MAX as u64 {
656            return Err(LostSegmentError::LargeFileSegmentNotSupported);
657        }
658        if segment_to_remove.1 == segment_to_remove.0 {
659            return Err(LostSegmentError::EmptySegment);
660        }
661        if segment_to_remove.0 > segment_to_remove.1 {
662            return Err(LostSegmentError::StartLargerThanEnd(
663                segment_to_remove.0,
664                segment_to_remove.1,
665            ));
666        }
667
668        let idx = match self
670            .list
671            .binary_search_by_key(&segment_to_remove.0, |&(s, _)| s as u64)
672        {
673            Ok(idx) => idx,
674            Err(insertion) => insertion.saturating_sub(1),
675        };
676
677        let mut i = idx;
679        let list_len = self.list.len();
680        while i < self.list.len() && self.list[i].0 as u64 <= segment_to_remove.1 {
681            let seg = &mut self.list[i];
682
683            if (seg.1 as u64) < segment_to_remove.0 {
685                i += 1;
686                continue;
687            }
688
689            if seg.0 as u64 == segment_to_remove.0 && seg.1 as u64 == segment_to_remove.1 {
691                self.list.remove(i);
692                return Ok(true);
693            }
694
695            if (segment_to_remove.0 < seg.0 as u64 && segment_to_remove.1 > seg.0 as u64)
697                || (segment_to_remove.1 > seg.1 as u64 && segment_to_remove.0 < seg.1 as u64)
698            {
699                return Err(LostSegmentError::InvalidSegmentBoundary(
700                    segment_to_remove.0,
701                    segment_to_remove.1,
702                ));
703            }
704
705            let mut changed = false;
708
709            if segment_to_remove.1 == seg.1 as u64 {
711                seg.1 = segment_to_remove.0 as u32;
712                changed = true;
713            }
714            if segment_to_remove.0 == seg.0 as u64 {
716                seg.0 = segment_to_remove.1 as u32;
717                changed = true;
718            }
719            if segment_to_remove.0 > seg.0 as u64 && segment_to_remove.1 < seg.1 as u64 {
721                if list_len == N {
722                    return Err(LostSegmentError::StoreFull);
723                }
724                let end_of_right_remainder = seg.1;
726                seg.1 = segment_to_remove.0 as u32;
728                self.list
729                    .insert(i + 1, (segment_to_remove.1 as u32, end_of_right_remainder))
730                    .unwrap();
731                changed = true;
732            }
733
734            if changed {
736                return Ok(true);
737            }
738
739            i += 1;
740        }
741        Ok(false)
742    }
743
744    fn coalesce_lost_segments(&mut self) -> Result<(), LostSegmentError> {
745        self.coalesce_lost_segments()
746    }
747
748    #[inline]
749    fn number_of_segments(&self) -> usize {
750        self.num_lost_segments()
751    }
752
753    #[inline]
754    fn supports_large_file_size(&self) -> bool {
755        false
756    }
757
758    #[inline]
759    fn capacity(&self) -> Option<usize> {
760        self.capacity()
761    }
762
763    #[inline]
764    fn reset(&mut self) {
765        self.reset();
766    }
767
768    fn segment_in_store(&self, segment: (u64, u64)) -> bool {
769        for (seg_start, seg_end) in &self.list {
770            if segment.0 >= *seg_start as u64 && segment.1 <= *seg_end as u64 {
771                return true;
772            }
773        }
774        false
775    }
776}
777
778#[cfg(test)]
779mod tests {
780    use std::vec::Vec;
781
782    use super::*;
783
784    fn generic_basic_state_test(
785        store: &impl LostSegmentStore,
786        supports_large_file_size: bool,
787        capacity: Option<usize>,
788    ) {
789        assert_eq!(store.supports_large_file_size(), supports_large_file_size);
790        assert_eq!(store.number_of_segments(), 0);
791        assert!(store.is_empty());
792        assert_eq!(store.capacity(), capacity);
793        assert_eq!(store.iter().count(), 0);
794    }
795
796    fn generic_error_tests(store: &mut impl LostSegmentStore) {
797        matches!(
798            store.add_lost_segment((0, 0)).unwrap_err(),
799            LostSegmentError::EmptySegment
800        );
801        matches!(
802            store.add_lost_segment((10, 0)).unwrap_err(),
803            LostSegmentError::StartLargerThanEnd(10, 0)
804        );
805        matches!(
806            store.remove_lost_segment((0, 0)).unwrap_err(),
807            LostSegmentError::EmptySegment
808        );
809        matches!(
810            store.remove_lost_segment((10, 0)).unwrap_err(),
811            LostSegmentError::StartLargerThanEnd(10, 0)
812        );
813    }
814
815    fn generic_add_segments_test(store: &mut impl LostSegmentStore) {
816        store.add_lost_segment((0, 20)).unwrap();
817        assert_eq!(store.number_of_segments(), 1);
818        for segment in store.iter() {
819            assert_eq!(segment, (0, 20));
820        }
821        store.add_lost_segment((20, 40)).unwrap();
822        let mut segments: Vec<(u64, u64)> = store.iter().collect();
823        segments.sort_unstable();
824        assert_eq!(segments.len(), 2);
825        assert_eq!(segments[0], (0, 20));
826        assert_eq!(segments[1], (20, 40));
827    }
828
829    fn generic_reset_test(store: &mut impl LostSegmentStore) {
830        store.add_lost_segment((0, 20)).unwrap();
831        assert_eq!(store.number_of_segments(), 1);
832        store.reset();
833        assert_eq!(store.number_of_segments(), 0);
834        assert!(store.is_empty());
835        assert_eq!(store.iter().count(), 0);
836    }
837
838    fn generic_removal_test(store: &mut impl LostSegmentStore) {
839        store.add_lost_segment((0, 20)).unwrap();
840        store.add_lost_segment((20, 40)).unwrap();
841        assert_eq!(store.number_of_segments(), 2);
842        assert!(store.remove_lost_segment((0, 20)).unwrap());
843        assert_eq!(store.number_of_segments(), 1);
844        assert!(!store.remove_lost_segment((0, 20)).unwrap());
845        assert_eq!(store.number_of_segments(), 1);
846        assert!(store.remove_lost_segment((20, 40)).unwrap());
847        assert_eq!(store.number_of_segments(), 0);
848    }
849
850    fn generic_partial_removal_test_right_aligned(store: &mut impl LostSegmentStore) {
851        store.add_lost_segment((0, 20)).unwrap();
852        assert_eq!(store.number_of_segments(), 1);
853        store.remove_lost_segment((0, 10)).unwrap();
854        assert_eq!(store.number_of_segments(), 1);
855        for list in store.iter() {
856            assert_eq!(list, (10, 20));
857        }
858        store.remove_lost_segment((10, 20)).unwrap();
859        assert!(store.is_empty());
860    }
861
862    fn generic_partial_removal_test_left_aligned(store: &mut impl LostSegmentStore) {
863        store.add_lost_segment((0, 20)).unwrap();
864        assert_eq!(store.number_of_segments(), 1);
865        store.remove_lost_segment((10, 20)).unwrap();
866        assert_eq!(store.number_of_segments(), 1);
867        for list in store.iter() {
868            assert_eq!(list, (0, 10));
869        }
870        store.remove_lost_segment((0, 10)).unwrap();
871        assert!(store.is_empty());
872    }
873
874    fn generic_partial_removal_test_fully_contained(store: &mut impl LostSegmentStore) {
875        store.add_lost_segment((0, 20)).unwrap();
876        assert_eq!(store.number_of_segments(), 1);
877        store.remove_lost_segment((5, 15)).unwrap();
878        assert_eq!(store.number_of_segments(), 2);
879        let seg_list = store.iter().collect::<Vec<(u64, u64)>>();
880        assert!(seg_list.contains(&(0, 5)));
881        assert!(seg_list.contains(&(15, 20)));
882        store.remove_lost_segment((0, 5)).unwrap();
883        assert_eq!(store.number_of_segments(), 1);
884        store.remove_lost_segment((15, 20)).unwrap();
885        assert!(store.is_empty());
886    }
887
888    fn generic_partial_removal_fails_test_0(store: &mut impl LostSegmentStore) {
889        store.add_lost_segment((10, 20)).unwrap();
890        assert_eq!(store.number_of_segments(), 1);
891        assert_eq!(
892            store.remove_lost_segment((5, 15)).unwrap_err(),
893            LostSegmentError::InvalidSegmentBoundary(5, 15)
894        );
895    }
896
897    fn generic_partial_removal_fails_test_1(store: &mut impl LostSegmentStore) {
898        store.add_lost_segment((10, 20)).unwrap();
899        assert_eq!(store.number_of_segments(), 1);
900        assert_eq!(
901            store.remove_lost_segment((15, 25)).unwrap_err(),
902            LostSegmentError::InvalidSegmentBoundary(15, 25)
903        );
904    }
905
906    fn generic_partial_removal_fails_test_2(store: &mut impl LostSegmentStore) {
907        store.add_lost_segment((10, 20)).unwrap();
908        assert_eq!(store.number_of_segments(), 1);
909        assert_eq!(
910            store.remove_lost_segment((10, 25)).unwrap_err(),
911            LostSegmentError::InvalidSegmentBoundary(10, 25)
912        );
913    }
914
915    fn generic_partial_removal_fails_test_3(store: &mut impl LostSegmentStore) {
916        store.add_lost_segment((10, 20)).unwrap();
917        assert_eq!(store.number_of_segments(), 1);
918        assert_eq!(
919            store.remove_lost_segment((5, 20)).unwrap_err(),
920            LostSegmentError::InvalidSegmentBoundary(5, 20)
921        );
922    }
923
924    fn generic_coalescing_simple_test(store: &mut impl LostSegmentStore) {
925        store.add_lost_segment((0, 20)).unwrap();
926        store.add_lost_segment((20, 40)).unwrap();
927        store.add_lost_segment((40, 60)).unwrap();
928        store.coalesce_lost_segments().unwrap();
929        for segment in store.iter() {
930            assert_eq!(segment, (0, 60));
931        }
932        assert_eq!(store.number_of_segments(), 1);
933    }
934
935    fn generic_coalescing_simple_with_gaps_test(store: &mut impl LostSegmentStore) {
936        store.add_lost_segment((0, 20)).unwrap();
937        store.add_lost_segment((20, 40)).unwrap();
938        store.add_lost_segment((40, 60)).unwrap();
939
940        store.add_lost_segment((80, 100)).unwrap();
941        store.add_lost_segment((110, 120)).unwrap();
942        store.add_lost_segment((120, 130)).unwrap();
943        store.coalesce_lost_segments().unwrap();
944        let mut segments: Vec<(u64, u64)> = store.iter().collect();
945        segments.sort_unstable();
946        assert_eq!(segments.len(), 3);
947        assert_eq!(segments[0], (0, 60));
948        assert_eq!(segments[1], (80, 100));
949        assert_eq!(segments[2], (110, 130));
950    }
951
952    fn generic_coalescing_overlapping_simple_test(store: &mut impl LostSegmentStore) {
953        store.add_lost_segment((0, 20)).unwrap();
954        store.add_lost_segment((10, 30)).unwrap();
955        store.coalesce_lost_segments().unwrap();
956        for segment in store.iter() {
957            assert_eq!(segment, (0, 30));
958        }
959        assert_eq!(store.number_of_segments(), 1);
960    }
961
962    fn generic_coalescing_overlapping_adjacent_test(store: &mut impl LostSegmentStore) {
963        store.add_lost_segment((0, 20)).unwrap();
964        store.add_lost_segment((10, 30)).unwrap();
965        store.add_lost_segment((20, 40)).unwrap();
966        store.coalesce_lost_segments().unwrap();
967        for segment in store.iter() {
968            assert_eq!(segment, (0, 40));
969        }
970        assert_eq!(store.number_of_segments(), 1);
971    }
972
973    fn generic_useless_coalescing_test(store: &mut impl LostSegmentStore) {
974        assert!(store.coalesce_lost_segments().is_ok());
976        assert_eq!(store.number_of_segments(), 0);
977        assert!(store.is_empty());
978        store.add_lost_segment((10, 20)).unwrap();
979        assert!(store.coalesce_lost_segments().is_ok());
981        for segment in store.iter() {
982            assert_eq!(segment, (10, 20));
983        }
984    }
985
986    #[test]
987    fn test_basic_map_state_list() {
988        let store = LostSegmentsList::default();
989        generic_basic_state_test(&store, true, None);
990    }
991
992    #[test]
993    fn test_basic_errors_list() {
994        let mut store = LostSegmentsList::default();
995        generic_error_tests(&mut store);
996    }
997
998    #[test]
999    fn test_add_segments_list() {
1000        let mut store = LostSegmentsList::default();
1001        generic_add_segments_test(&mut store);
1002    }
1003
1004    #[test]
1005    fn test_reset_list() {
1006        let mut store = LostSegmentsList::default();
1007        generic_reset_test(&mut store);
1008    }
1009
1010    #[test]
1011    fn test_removal_map() {
1012        let mut store = LostSegmentsList::default();
1013        generic_removal_test(&mut store);
1014    }
1015
1016    #[test]
1017    fn test_partial_removal_list_0() {
1018        let mut store = LostSegmentsList::default();
1019        generic_partial_removal_test_right_aligned(&mut store);
1020    }
1021
1022    #[test]
1023    fn test_partial_removal_list_1() {
1024        let mut store = LostSegmentsList::default();
1025        generic_partial_removal_test_left_aligned(&mut store);
1026    }
1027
1028    #[test]
1029    fn test_partial_removal_list_2() {
1030        let mut store = LostSegmentsList::default();
1031        generic_partial_removal_test_fully_contained(&mut store);
1032    }
1033
1034    #[test]
1035    fn test_partial_removal_list_fails_0() {
1036        let mut store = LostSegmentsList::default();
1037        generic_partial_removal_fails_test_0(&mut store);
1038    }
1039
1040    #[test]
1041    fn test_partial_removal_list_fails_1() {
1042        let mut store = LostSegmentsList::default();
1043        generic_partial_removal_fails_test_1(&mut store);
1044    }
1045
1046    #[test]
1047    fn test_partial_removal_list_fails_2() {
1048        let mut store = LostSegmentsList::default();
1049        generic_partial_removal_fails_test_2(&mut store);
1050    }
1051
1052    #[test]
1053    fn test_partial_removal_list_fails_3() {
1054        let mut store = LostSegmentsList::default();
1055        generic_partial_removal_fails_test_3(&mut store);
1056    }
1057
1058    #[test]
1059    fn test_cap_limit_list() {
1060        let mut store = LostSegmentsList::new(Some(4));
1061        for i in 0..4 {
1062            store.add_lost_segment((i * 20, (i + 1) * 20)).unwrap();
1063        }
1064        matches!(
1065            store.add_lost_segment((80, 100)),
1066            Err(LostSegmentError::StoreFull)
1067        );
1068    }
1069
1070    #[test]
1071    fn test_basic_list_state_list() {
1072        let store = LostSegmentsListNormalFilesHeapless::<12>::default();
1073        generic_basic_state_test(&store, false, Some(12));
1074        let store = LostSegmentsListNormalFilesHeapless::<12>::new();
1075        generic_basic_state_test(&store, false, Some(12));
1076    }
1077    #[test]
1078    fn test_basic_errors_list_heapless() {
1079        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1080        generic_error_tests(&mut store);
1081    }
1082
1083    #[test]
1084    fn test_add_segments_list_heapless() {
1085        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1086        generic_add_segments_test(&mut store);
1087    }
1088
1089    #[test]
1090    fn test_reset_list_heapless() {
1091        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1092        generic_reset_test(&mut store);
1093    }
1094
1095    #[test]
1096    fn test_removal_list() {
1097        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1098        generic_removal_test(&mut store);
1099    }
1100
1101    #[test]
1102    fn test_partial_removal_list_heapless_0() {
1103        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1104        generic_partial_removal_test_right_aligned(&mut store);
1105    }
1106
1107    #[test]
1108    fn test_partial_removal_list_heapless_1() {
1109        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1110        generic_partial_removal_test_left_aligned(&mut store);
1111    }
1112
1113    #[test]
1114    fn test_partial_removal_list_heapless_2() {
1115        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1116        generic_partial_removal_test_fully_contained(&mut store);
1117    }
1118
1119    #[test]
1120    fn test_partial_removal_heapless_list_fails_0() {
1121        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1122        generic_partial_removal_fails_test_0(&mut store);
1123    }
1124
1125    #[test]
1126    fn test_partial_removal_heapless_list_fails_1() {
1127        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1128        generic_partial_removal_fails_test_1(&mut store);
1129    }
1130
1131    #[test]
1132    fn test_partial_removal_heapless_list_fails_2() {
1133        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1134        generic_partial_removal_fails_test_2(&mut store);
1135    }
1136
1137    #[test]
1138    fn test_partial_removal_heapless_list_fails_3() {
1139        let mut store = LostSegmentsListNormalFilesHeapless::<12>::default();
1140        generic_partial_removal_fails_test_3(&mut store);
1141    }
1142
1143    fn generic_cap_limit_list_by_removal_test(store: &mut impl LostSegmentStore) {
1144        for i in 0..4 {
1145            store.add_lost_segment((i * 20, (i + 1) * 20)).unwrap();
1146        }
1147        matches!(
1149            store.remove_lost_segment((85, 95)),
1150            Err(LostSegmentError::StoreFull)
1151        );
1152    }
1153
1154    fn generic_cap_limit_list_by_addition_test(store: &mut impl LostSegmentStore) {
1155        for i in 0..4 {
1156            store.add_lost_segment((i * 20, (i + 1) * 20)).unwrap();
1157        }
1158        matches!(
1160            store.add_lost_segment((100, 120)),
1161            Err(LostSegmentError::StoreFull)
1162        );
1163    }
1164
1165    #[test]
1166    fn test_cap_limit_list_by_removal() {
1167        let mut store = LostSegmentsList::new(Some(4));
1168        generic_cap_limit_list_by_removal_test(&mut store);
1169    }
1170
1171    #[test]
1172    fn test_cap_limit_list_heapless_by_removal() {
1173        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1174        generic_cap_limit_list_by_removal_test(&mut store);
1175    }
1176
1177    #[test]
1178    fn test_cap_limit_list_heapless() {
1179        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1180        generic_cap_limit_list_by_addition_test(&mut store);
1181    }
1182
1183    #[test]
1184    fn test_large_file_size_unsupported() {
1185        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1186        matches!(
1187            store.add_lost_segment((0, u32::MAX as u64 + 1)),
1188            Err(LostSegmentError::LargeFileSegmentNotSupported)
1189        );
1190    }
1191
1192    #[test]
1193    fn test_large_file_size_unsupported_2() {
1194        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1195        matches!(
1196            store.remove_lost_segment((0, u32::MAX as u64 + 1)),
1197            Err(LostSegmentError::LargeFileSegmentNotSupported)
1198        );
1199    }
1200
1201    #[test]
1202    fn test_basic_list_state_list_large() {
1203        let store = LostSegmentsListHeapless::<12, u64>::default();
1204        generic_basic_state_test(&store, true, Some(12));
1205    }
1206    #[test]
1207    fn test_basic_errors_list_large() {
1208        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1209        generic_error_tests(&mut store);
1210    }
1211
1212    #[test]
1213    fn test_add_segments_list_large() {
1214        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1215        generic_add_segments_test(&mut store);
1216    }
1217
1218    #[test]
1219    fn test_reset_list_large() {
1220        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1221        generic_reset_test(&mut store);
1222    }
1223
1224    #[test]
1225    fn test_removal_list_large() {
1226        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1227        generic_removal_test(&mut store);
1228    }
1229
1230    #[test]
1231    fn test_partial_removal_list_heapless_large_0() {
1232        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1233        generic_partial_removal_test_right_aligned(&mut store);
1234    }
1235
1236    #[test]
1237    fn test_partial_removal_list_heapless_large_1() {
1238        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1239        generic_partial_removal_test_left_aligned(&mut store);
1240    }
1241
1242    #[test]
1243    fn test_partial_removal_list_heapless_large_2() {
1244        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1245        generic_partial_removal_test_fully_contained(&mut store);
1246    }
1247
1248    #[test]
1249    fn test_partial_removal_heapless_list_large_fails_0() {
1250        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1251        generic_partial_removal_fails_test_0(&mut store);
1252    }
1253
1254    #[test]
1255    fn test_partial_removal_heapless_list_large_fails_1() {
1256        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1257        generic_partial_removal_fails_test_1(&mut store);
1258    }
1259
1260    #[test]
1261    fn test_partial_removal_heapless_list_large_fails_2() {
1262        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1263        generic_partial_removal_fails_test_2(&mut store);
1264    }
1265
1266    #[test]
1267    fn test_partial_removal_heapless_list_large_fails_3() {
1268        let mut store = LostSegmentsListHeapless::<12, u64>::default();
1269        generic_partial_removal_fails_test_3(&mut store);
1270    }
1271
1272    #[test]
1273    fn test_cap_limit_list_large() {
1274        let mut store = LostSegmentsListHeapless::<4, u64>::default();
1275        generic_cap_limit_list_by_removal_test(&mut store);
1276    }
1277
1278    #[test]
1279    fn test_coalescing_simple_in_map() {
1280        let mut store = LostSegmentsList::default();
1281        generic_coalescing_simple_test(&mut store);
1282    }
1283
1284    #[test]
1285    fn test_useless_coalescing_map() {
1286        let mut store = LostSegmentsList::default();
1287        generic_useless_coalescing_test(&mut store);
1288    }
1289
1290    #[test]
1291    fn test_useless_coalescing_list() {
1292        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1293        generic_useless_coalescing_test(&mut store);
1294    }
1295
1296    #[test]
1297    fn test_coalescing_simple_in_list() {
1298        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1299        generic_coalescing_simple_test(&mut store);
1300    }
1301
1302    #[test]
1303    fn test_coalescing_simple_in_list_large() {
1304        let mut store = LostSegmentsListHeapless::<4, u64>::default();
1305        generic_coalescing_simple_test(&mut store);
1306    }
1307
1308    #[test]
1309    fn test_coalescing_overlapping_simple_in_map() {
1310        let mut store = LostSegmentsList::default();
1311        generic_coalescing_overlapping_simple_test(&mut store);
1312    }
1313
1314    #[test]
1315    fn test_coalescing_overlapping_simple_in_list() {
1316        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1317        generic_coalescing_overlapping_simple_test(&mut store);
1318    }
1319
1320    #[test]
1321    fn test_coalescing_overlapping_simple_in_list_large() {
1322        let mut store = LostSegmentsListHeapless::<4, u64>::default();
1323        generic_coalescing_overlapping_simple_test(&mut store);
1324    }
1325
1326    #[test]
1327    fn test_coalescing_overlapping_adjacent_in_map() {
1328        let mut store = LostSegmentsList::default();
1329        generic_coalescing_overlapping_adjacent_test(&mut store);
1330    }
1331
1332    #[test]
1333    fn test_coalescing_overlapping_adjacent_in_list() {
1334        let mut store = LostSegmentsListNormalFilesHeapless::<4>::default();
1335        generic_coalescing_overlapping_adjacent_test(&mut store);
1336    }
1337
1338    #[test]
1339    fn test_coalescing_overlapping_adjacent_in_list_large() {
1340        let mut store = LostSegmentsListHeapless::<4, u64>::default();
1341        generic_coalescing_overlapping_adjacent_test(&mut store);
1342    }
1343
1344    #[test]
1345    fn test_coalescing_simple_with_gaps_in_map() {
1346        let mut store = LostSegmentsList::default();
1347        generic_coalescing_simple_with_gaps_test(&mut store);
1348    }
1349
1350    #[test]
1351    fn test_coalescing_simple_with_gaps_in_list() {
1352        let mut store = LostSegmentsListNormalFilesHeapless::<8>::default();
1353        generic_coalescing_simple_with_gaps_test(&mut store);
1354    }
1355
1356    #[test]
1357    fn test_coalescing_simple_with_gaps_in_list_large() {
1358        let mut store = LostSegmentsListHeapless::<8, u64>::default();
1359        generic_coalescing_simple_with_gaps_test(&mut store);
1360    }
1361}