Skip to main content

dsi_bitstream/impls/
mem_word_reader.rs

1/*
2 * SPDX-FileCopyrightText: 2023 Tommaso Fontana
3 * SPDX-FileCopyrightText: 2023 Inria
4 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
5 *
6 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7 */
8
9use crate::prelude::*;
10use core::convert::Infallible;
11#[cfg(feature = "mem_dbg")]
12use mem_dbg::{MemDbg, MemSize};
13
14/// An implementation of [`WordRead`] and [`WordSeek`] for a slice.
15///
16/// The implementation depends on the `INF` parameter: if true, the reader will
17/// behave as if the slice is infinitely extended with zeros.
18/// If false (default), the reader will return an error when reading
19/// beyond the end of the slice. You can create a strict
20/// reader with [`MemWordReader::new`] and a zero-extended
21/// reader with [`MemWordReader::new_inf`].
22///
23/// The zero-extended reader might loop infinitely when reading beyond the end
24/// of the slice. It is mainly of historical value.
25///
26/// # Examples
27///
28/// ```rust
29/// # fn main() -> Result<(), Box<dyn core::error::Error>> {
30/// use dsi_bitstream::prelude::*;
31///
32/// let words: [u32; 2] = [1, 2];
33///
34/// let mut word_reader = MemWordReader::new(&words);
35/// assert_eq!(word_reader.read_word()?, 1);
36/// assert_eq!(word_reader.read_word()?, 2);
37/// assert!(word_reader.read_word().is_err());
38///
39/// let mut word_reader = MemWordReader::new_inf(&words);
40/// assert_eq!(word_reader.read_word()?, 1);
41/// assert_eq!(word_reader.read_word()?, 2);
42/// assert_eq!(word_reader.read_word()?, 0);
43/// assert_eq!(word_reader.read_word()?, 0);
44/// # Ok(())
45/// # }
46/// ```
47#[derive(Debug, Clone, PartialEq)]
48#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
49pub struct MemWordReader<W: Word, B, const INF: bool = false> {
50    data: B,
51    word_index: usize,
52    _marker: core::marker::PhantomData<W>,
53}
54
55impl<W: Word, B, const INF: bool> MemWordReader<W, B, INF> {
56    /// Consumes this reader and returns the underlying data.
57    #[must_use]
58    pub fn into_inner(self) -> B {
59        self.data
60    }
61}
62
63impl<W: Word, B: AsRef<[W]>> MemWordReader<W, B> {
64    /// Creates a new [`MemWordReader`] from a slice of data.
65    #[must_use]
66    pub const fn new(data: B) -> Self {
67        Self {
68            data,
69            word_index: 0,
70            _marker: core::marker::PhantomData,
71        }
72    }
73}
74
75impl<W: Word, B: AsRef<[W]>> MemWordReader<W, B, true> {
76    /// Creates a new [`MemWordReader`] from a slice of data.
77    ///
78    /// The resulting reader behaves as if the slice is infinitely
79    /// extended with zeros.
80    #[must_use]
81    pub const fn new_inf(data: B) -> Self {
82        Self {
83            data,
84            word_index: 0,
85            _marker: core::marker::PhantomData,
86        }
87    }
88}
89
90impl<W: Word, B: AsRef<[W]>> WordRead for MemWordReader<W, B, true> {
91    type Error = Infallible;
92    type Word = W;
93
94    #[inline(always)]
95    fn read_word(&mut self) -> Result<W, Infallible> {
96        let res = self
97            .data
98            .as_ref()
99            .get(self.word_index)
100            .copied()
101            .unwrap_or(Self::Word::ZERO);
102
103        self.word_index += 1;
104        Ok(res)
105    }
106}
107
108impl<W: Word, B: AsRef<[W]>> WordRead for MemWordReader<W, B, false> {
109    type Error = WordError;
110    type Word = W;
111
112    #[inline(always)]
113    fn read_word(&mut self) -> Result<W, WordError> {
114        let res = self
115            .data
116            .as_ref()
117            .get(self.word_index)
118            .ok_or(WordError::UnexpectedEof {
119                word_pos: self.word_index,
120            })?;
121
122        self.word_index += 1;
123        Ok(*res)
124    }
125}
126
127impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, true> {
128    type Error = Infallible;
129
130    #[inline(always)]
131    fn word_pos(&mut self) -> Result<u64, Infallible> {
132        Ok(self.word_index as u64)
133    }
134
135    #[inline(always)]
136    fn set_word_pos(&mut self, word_index: u64) -> Result<(), Infallible> {
137        // This is dirty but it's infallible
138        self.word_index = word_index.min(usize::MAX as u64) as usize;
139        Ok(())
140    }
141}
142
143impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, false> {
144    type Error = WordError;
145
146    #[inline(always)]
147    fn word_pos(&mut self) -> Result<u64, WordError> {
148        Ok(self.word_index as u64)
149    }
150    #[inline(always)]
151    fn set_word_pos(&mut self, word_index: u64) -> Result<(), WordError> {
152        if word_index > self.data.as_ref().len() as u64 {
153            Err(WordError::UnexpectedEof {
154                word_pos: self.word_index,
155            })
156        } else {
157            self.word_index = word_index as usize;
158            Ok(())
159        }
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166    use crate::codes::{DeltaWrite, delta::DeltaReadParam};
167
168    #[test]
169    fn test_eof_table_read() {
170        let mut words: [u64; 1] = [0];
171        let mut writer = crate::prelude::BufBitWriter::<crate::prelude::LE, _>::new(
172            MemWordWriterSlice::new(&mut words),
173        );
174        for _ in 0..16 {
175            writer.write_delta(1).unwrap();
176        }
177        writer.flush().unwrap();
178        drop(writer);
179
180        let mut reader = crate::prelude::BufBitReader::<crate::prelude::LE, _>::new(
181            MemWordReader::new_inf(&words),
182        );
183        for _ in 0..16 {
184            // Here the last table read returns zero-extended data
185            assert_eq!(reader.read_delta_param::<true, true>().unwrap(), 1);
186        }
187    }
188}