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/**
15
16An implementation of [`WordRead`] and [`WordSeek`] for a slice.
17
18The implementation depends on the `INF` parameter: if true, the reader will
19behave as if the slice is infinitely extended with zeros.
20If false, the reader will return an error when reading
21beyond the end of the slice. You can create a zero-extended
22reader with [`MemWordReader::new`] and a strict reader with
23[`MemWordReader::new_strict`].
24
25The zero-extended reader is usually much faster than the strict reader, but
26it might loop infinitely when reading beyond the end of the slice.
27
28# Examples
29
30```rust
31# fn main() -> Result<(), Box<dyn std::error::Error>> {
32use dsi_bitstream::prelude::*;
33
34let words: [u32; 2] = [1, 2];
35
36let mut word_reader = MemWordReader::new(&words);
37assert_eq!(1, word_reader.read_word()?);
38assert_eq!(2, word_reader.read_word()?);
39assert_eq!(0, word_reader.read_word()?);
40assert_eq!(0, word_reader.read_word()?);
41
42let mut word_reader = MemWordReader::new_strict(&words);
43assert_eq!(1, word_reader.read_word()?);
44assert_eq!(2, word_reader.read_word()?);
45assert!(word_reader.read_word().is_err());
46# Ok(())
47# }
48```
49*/
50#[derive(Debug, Clone, PartialEq)]
51#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
52pub struct MemWordReader<W: Word, B: AsRef<[W]>, const INF: bool = true> {
53    data: B,
54    word_index: usize,
55    _marker: core::marker::PhantomData<W>,
56}
57
58impl<W: Word, B: AsRef<[W]>> MemWordReader<W, B> {
59    /// Create a new [`MemWordReader`] from a slice of data
60    #[must_use]
61    pub fn new(data: B) -> Self {
62        Self {
63            data,
64            word_index: 0,
65            _marker: Default::default(),
66        }
67    }
68
69    pub fn into_inner(self) -> B {
70        self.data
71    }
72}
73
74impl<W: Word, B: AsRef<[W]>> MemWordReader<W, B, false> {
75    /// Create a new [`MemWordReader`] from a slice of data
76    #[must_use]
77    pub fn new_strict(data: B) -> Self {
78        Self {
79            data,
80            word_index: 0,
81            _marker: Default::default(),
82        }
83    }
84}
85
86impl<W: Word, B: AsRef<[W]>> WordRead for MemWordReader<W, B, true> {
87    type Error = Infallible;
88    type Word = W;
89
90    #[inline(always)]
91    fn read_word(&mut self) -> Result<W, Infallible> {
92        let res = self
93            .data
94            .as_ref()
95            .get(self.word_index)
96            .copied()
97            .unwrap_or(Self::Word::ZERO);
98
99        self.word_index += 1;
100        Ok(res)
101    }
102}
103
104impl<W: Word, B: AsRef<[W]>> WordRead for MemWordReader<W, B, false> {
105    type Error = std::io::Error;
106    type Word = W;
107
108    #[inline(always)]
109    fn read_word(&mut self) -> Result<W, std::io::Error> {
110        let res = self
111            .data
112            .as_ref()
113            .get(self.word_index)
114            .ok_or(std::io::Error::new(
115                std::io::ErrorKind::UnexpectedEof,
116                "Unexpected end of slice",
117            ))?;
118
119        self.word_index += 1;
120        Ok(*res)
121    }
122}
123
124impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, true> {
125    type Error = Infallible;
126
127    #[inline(always)]
128    fn word_pos(&mut self) -> Result<u64, Infallible> {
129        Ok(self.word_index as u64)
130    }
131
132    #[inline(always)]
133    fn set_word_pos(&mut self, word_index: u64) -> Result<(), Infallible> {
134        // This is dirty but it's infallible
135        self.word_index = word_index.min(usize::MAX as u64) as usize;
136        Ok(())
137    }
138}
139
140impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, false> {
141    type Error = std::io::Error;
142
143    #[inline(always)]
144    fn word_pos(&mut self) -> Result<u64, std::io::Error> {
145        Ok(self.word_index as u64)
146    }
147    #[inline(always)]
148    fn set_word_pos(&mut self, word_index: u64) -> Result<(), std::io::Error> {
149        if word_index > self.data.as_ref().len() as u64 {
150            Err(std::io::Error::new(
151                std::io::ErrorKind::UnexpectedEof,
152                format_args!(
153                    "Position beyond end of slice: {} > {}",
154                    word_index,
155                    self.data.as_ref().len()
156                )
157                .to_string(),
158            ))
159        } else {
160            self.word_index = word_index as usize;
161            Ok(())
162        }
163    }
164}
165
166#[test]
167
168fn test_eof_table_read() {
169    use crate::codes::{DeltaReadParam, DeltaWrite};
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 =
181        crate::prelude::BufBitReader::<crate::prelude::LE, _>::new(MemWordReader::new(&words));
182    for _ in 0..16 {
183        // Here the last table read make peek_bits return Ok(None)
184        assert_eq!(1, reader.read_delta_param::<true, true>().unwrap());
185    }
186}