Skip to main content

ps_ecc/long/header/methods/
last_segment_length.rs

1use crate::long::LongEccHeader;
2
3impl LongEccHeader {
4    /// Data length of the final ECC segment, always shorter than `segment_length`.
5    ///
6    /// The constructors enforce `2 * parity < segment_distance`, so the
7    /// subtraction cannot underflow.
8    #[inline]
9    #[must_use]
10    // The remainder is always shorter than `segment_length`, so it fits in `u8`.
11    #[allow(clippy::cast_possible_truncation)]
12    pub const fn last_segment_length(&self) -> u8 {
13        let new_bytes_per_segment = (self.segment_distance() - self.parity_bytes()) as u32;
14        let full_segments = self.segment_count() - 1;
15        let covered = full_segments.saturating_mul(new_bytes_per_segment);
16
17        self.message_length().saturating_sub(covered) as u8
18    }
19}
20
21#[cfg(test)]
22mod tests {
23    use crate::long::{LongEccHeader, OverlapFactor};
24
25    type TestError = Box<dyn std::error::Error>;
26
27    #[test]
28    fn test_last_segment_length_single_segment() -> Result<(), TestError> {
29        let header = LongEccHeader::new(2, OverlapFactor::Simple, 136, 100, 0)?;
30
31        assert_eq!(header.last_segment_length(), 100);
32
33        Ok(())
34    }
35
36    #[test]
37    fn test_last_segment_length_empty_message() -> Result<(), TestError> {
38        let header = LongEccHeader::new(2, OverlapFactor::Simple, 36, 0, 0)?;
39
40        assert_eq!(header.last_segment_length(), 0);
41
42        Ok(())
43    }
44
45    #[test]
46    fn test_last_segment_length_multiple_segments() -> Result<(), TestError> {
47        // Three segments cover 600 bytes; the first two contribute 239 new
48        // bytes each, leaving 600 - 2 * 239 = 122 bytes for the last segment.
49        let header = LongEccHeader::new(4, OverlapFactor::Simple, 656, 600, 0)?;
50
51        assert_eq!(header.last_segment_length(), 122);
52        assert!(header.last_segment_length() < header.segment_length());
53
54        Ok(())
55    }
56
57    #[test]
58    fn test_last_segment_length_boundary_spill() -> Result<(), TestError> {
59        // A 247-byte message with parity 4 spills exactly 247 - 239 = 8 bytes
60        // into the second segment.
61        let header = LongEccHeader::new(4, OverlapFactor::Simple, 295, 247, 0)?;
62
63        assert_eq!(header.last_segment_length(), 8);
64
65        Ok(())
66    }
67}