Skip to main content

msrtc_rans_core/
source.rs

1// Copyright (c) Infinity Abundance.
2// Licensed under the MIT license.
3
4//! Source traits for rANS decoder input.
5//!
6//! A source provides units (bytes or words) to the decoder during
7//! initialization and renormalization.
8
9/// Trait for a source that provides rANS units to the decoder.
10///
11/// Equivalent to the `operator(unit_t&)` call on the C++ source type,
12/// simplified to a `bool` return since the decoder uses boolean outcomes.
13pub trait Source<Unit>: Sized {
14    /// Read the next unit from the source.
15    /// Returns `true` if a unit was available, `false` if exhausted.
16    fn read(&mut self, unit: &mut Unit) -> bool;
17
18    /// Check whether the source has been fully consumed.
19    fn is_exhausted(&self) -> bool;
20}
21
22/// A simple slice-based source that reads units from a `&[Unit]`.
23///
24/// Equivalent to the C++ `span<const unit_t>` based source used by
25/// `RansDecoder` and `RansDecoderStreamImpl`.
26#[derive(Debug, Clone)]
27pub struct SliceSource<'a, Unit> {
28    data: &'a [Unit],
29    pos: usize,
30}
31
32impl<'a, Unit: Copy> SliceSource<'a, Unit> {
33    /// Create a new source reading from the given slice.
34    pub fn new(data: &'a [Unit]) -> Self {
35        Self { data, pos: 0 }
36    }
37
38    /// Current read position.
39    pub fn position(&self) -> usize {
40        self.pos
41    }
42
43    /// Remaining units in the source.
44    pub fn remaining(&self) -> usize {
45        self.data.len().saturating_sub(self.pos)
46    }
47}
48
49impl<'a, Unit: Copy> Source<Unit> for SliceSource<'a, Unit> {
50    #[inline]
51    fn read(&mut self, unit: &mut Unit) -> bool {
52        if self.pos < self.data.len() {
53            *unit = self.data[self.pos];
54            self.pos += 1;
55            true
56        } else {
57            false
58        }
59    }
60
61    #[inline]
62    fn is_exhausted(&self) -> bool {
63        self.pos >= self.data.len()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_slice_source_basic() {
73        let data = [1u8, 2, 3, 4];
74        let mut source = SliceSource::new(&data);
75
76        let mut unit = 0u8;
77        assert!(source.read(&mut unit));
78        assert_eq!(unit, 1);
79        assert!(source.read(&mut unit));
80        assert_eq!(unit, 2);
81        assert!(source.read(&mut unit));
82        assert_eq!(unit, 3);
83        assert!(source.read(&mut unit));
84        assert_eq!(unit, 4);
85
86        assert!(!source.read(&mut unit));
87        assert!(source.is_exhausted());
88    }
89
90    #[test]
91    fn test_empty_source() {
92        let data: [u8; 0] = [];
93        let mut source = SliceSource::new(&data);
94        let mut unit = 0u8;
95        assert!(!source.read(&mut unit));
96        assert!(source.is_exhausted());
97    }
98}