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 MIT
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    #[inline(always)]
108    fn read_word_opt(&mut self) -> Option<W> {
109        // Consistently with read_word, reading past the end returns zero,
110        // and the position may grow past the end.
111        let word = self
112            .data
113            .as_ref()
114            .get(self.word_index)
115            .copied()
116            .unwrap_or(W::ZERO);
117        self.word_index = self.word_index.saturating_add(1);
118        Some(word)
119    }
120}
121
122impl<W: Word, B: AsRef<[W]>> WordRead for MemWordReader<W, B, false> {
123    type Error = WordError;
124    type Word = W;
125
126    #[inline(always)]
127    fn read_word(&mut self) -> Result<W, WordError> {
128        let res = self
129            .data
130            .as_ref()
131            .get(self.word_index)
132            .ok_or(WordError::UnexpectedEof {
133                word_pos: self.word_index,
134            })?;
135
136        self.word_index += 1;
137        Ok(*res)
138    }
139
140    #[inline(always)]
141    fn read_word_opt(&mut self) -> Option<W> {
142        let word = self.data.as_ref().get(self.word_index).copied();
143        if word.is_some() {
144            self.word_index += 1;
145        }
146        word
147    }
148}
149
150impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, true> {
151    type Error = Infallible;
152
153    #[inline(always)]
154    fn word_pos(&mut self) -> Result<u64, Infallible> {
155        Ok(self.word_index as u64)
156    }
157
158    #[inline(always)]
159    fn set_word_pos(&mut self, word_index: u64) -> Result<(), Infallible> {
160        // This is dirty but it's infallible
161        self.word_index = word_index.min(usize::MAX as u64) as usize;
162        Ok(())
163    }
164}
165
166impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, false> {
167    type Error = WordError;
168
169    #[inline(always)]
170    fn word_pos(&mut self) -> Result<u64, WordError> {
171        Ok(self.word_index as u64)
172    }
173    #[inline(always)]
174    fn set_word_pos(&mut self, word_index: u64) -> Result<(), WordError> {
175        if word_index > self.data.as_ref().len() as u64 {
176            Err(WordError::UnexpectedEof {
177                word_pos: word_index as usize,
178            })
179        } else {
180            self.word_index = word_index as usize;
181            Ok(())
182        }
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189    use crate::codes::{DeltaWrite, delta::DeltaReadParam};
190
191    #[test]
192    fn test_eof_table_read() {
193        let mut words: [u64; 1] = [0];
194        let mut writer = crate::prelude::BufBitWriter::<crate::prelude::LE, _>::new(
195            MemWordWriterSlice::new(&mut words),
196        );
197        for _ in 0..16 {
198            writer.write_delta(1).unwrap();
199        }
200        writer.flush().unwrap();
201        drop(writer);
202
203        let mut reader = crate::prelude::BufBitReader::<crate::prelude::LE, _>::new(
204            MemWordReader::new_inf(&words),
205        );
206        for _ in 0..16 {
207            // Here the last table read returns zero-extended data
208            assert_eq!(reader.read_delta_param::<true, true>().unwrap(), 1);
209        }
210    }
211}