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 = WordError;
106    type Word = W;
107
108    #[inline(always)]
109    fn read_word(&mut self) -> Result<W, WordError> {
110        let res = self
111            .data
112            .as_ref()
113            .get(self.word_index)
114            .ok_or(WordError::UnexpectedEof {
115                word_pos: self.word_index,
116            })?;
117
118        self.word_index += 1;
119        Ok(*res)
120    }
121}
122
123impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, true> {
124    type Error = Infallible;
125
126    #[inline(always)]
127    fn word_pos(&mut self) -> Result<u64, Infallible> {
128        Ok(self.word_index as u64)
129    }
130
131    #[inline(always)]
132    fn set_word_pos(&mut self, word_index: u64) -> Result<(), Infallible> {
133        // This is dirty but it's infallible
134        self.word_index = word_index.min(usize::MAX as u64) as usize;
135        Ok(())
136    }
137}
138
139impl<W: Word, B: AsRef<[W]>> WordSeek for MemWordReader<W, B, false> {
140    type Error = WordError;
141
142    #[inline(always)]
143    fn word_pos(&mut self) -> Result<u64, WordError> {
144        Ok(self.word_index as u64)
145    }
146    #[inline(always)]
147    fn set_word_pos(&mut self, word_index: u64) -> Result<(), WordError> {
148        if word_index > self.data.as_ref().len() as u64 {
149            Err(WordError::UnexpectedEof {
150                word_pos: self.word_index,
151            })
152        } else {
153            self.word_index = word_index as usize;
154            Ok(())
155        }
156    }
157}
158
159#[test]
160
161fn test_eof_table_read() {
162    use crate::codes::{DeltaReadParam, DeltaWrite};
163    let mut words: [u64; 1] = [0];
164    let mut writer = crate::prelude::BufBitWriter::<crate::prelude::LE, _>::new(
165        MemWordWriterSlice::new(&mut words),
166    );
167    for _ in 0..16 {
168        writer.write_delta(1).unwrap();
169    }
170    writer.flush().unwrap();
171    drop(writer);
172
173    let mut reader =
174        crate::prelude::BufBitReader::<crate::prelude::LE, _>::new(MemWordReader::new(&words));
175    for _ in 0..16 {
176        // Here the last table read make peek_bits return Ok(None)
177        assert_eq!(1, reader.read_delta_param::<true, true>().unwrap());
178    }
179}