dsi_bitstream/impls/
mem_word_writer.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
9#[cfg(feature = "alloc")]
10use core::convert::Infallible;
11#[cfg(feature = "mem_dbg")]
12use mem_dbg::{MemDbg, MemSize};
13
14use crate::traits::*;
15
16/// An implementation of [`WordRead`], [`WordWrite`], and [`WordSeek`] for a
17/// mutable slice.
18///
19/// Writing beyond the end of the slice will return an error.
20///
21/// # Example
22/// ```
23/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
24/// use dsi_bitstream::prelude::*;
25///
26/// let mut words: [u64; 2] = [
27///     0x0043b59fcdf16077,
28///     0x702863e6f9739b86,
29/// ];
30///
31/// let mut word_writer = MemWordWriterSlice::new(&mut words);
32///
33/// // the stream is read sequentially
34/// assert_eq!(word_writer.word_pos()?, 0);
35/// assert_eq!(word_writer.read_word()?, 0x0043b59fcdf16077);
36/// assert_eq!(word_writer.word_pos()?, 1);
37/// assert_eq!(word_writer.read_word()?, 0x702863e6f9739b86);
38/// assert_eq!(word_writer.word_pos()?, 2);
39/// assert!(word_writer.read_word().is_err());
40///
41/// // you can change position
42/// assert!(word_writer.set_word_pos(1).is_ok());
43/// assert_eq!(word_writer.word_pos()?, 1);
44/// assert_eq!(word_writer.read_word()?, 0x702863e6f9739b86);
45///
46/// // errored set position doesn't change the current position
47/// assert_eq!(word_writer.word_pos()?, 2);
48/// assert!(word_writer.set_word_pos(100).is_err());
49/// assert_eq!(word_writer.word_pos()?, 2);
50///
51/// // we can write and read back!
52/// assert!(word_writer.set_word_pos(0).is_ok());
53/// assert!(word_writer.write_word(0x0b801b2bf696e8d2).is_ok());
54/// assert_eq!(word_writer.word_pos()?, 1);
55/// assert!(word_writer.set_word_pos(0).is_ok());
56/// assert_eq!(word_writer.read_word()?, 0x0b801b2bf696e8d2);
57/// assert_eq!(word_writer.word_pos()?, 1);
58/// # Ok(())
59/// # }
60/// ```
61#[derive(Debug, PartialEq)]
62#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
63pub struct MemWordWriterSlice<W: Word, B: AsMut<[W]>> {
64    data: B,
65    word_index: usize,
66    _marker: core::marker::PhantomData<W>,
67}
68
69impl<W: Word, B: AsMut<[W]> + AsRef<[W]>> MemWordWriterSlice<W, B> {
70    /// Create a new [`MemWordWriterSlice`] from a slice of **ZERO INITIALIZED** data
71    #[must_use]
72    pub fn new(data: B) -> Self {
73        Self {
74            data,
75            word_index: 0,
76            _marker: Default::default(),
77        }
78    }
79
80    pub fn len(&self) -> usize {
81        self.data.as_ref().len()
82    }
83
84    pub fn is_empty(&self) -> bool {
85        self.len() == 0
86    }
87
88    pub fn into_inner(self) -> B {
89        self.data
90    }
91}
92
93/// An implementation of [`WordRead`], [`WordWrite`], and [`WordSeek`]
94/// for a mutable vector.
95///
96/// The vector will be extended as new data is written.
97///
98/// # Example
99/// ```
100/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
101/// use dsi_bitstream::prelude::*;
102///
103/// let mut words: Vec<u64> = vec![
104///     0x0043b59fcdf16077,
105/// ];
106///
107/// let mut word_writer = MemWordWriterVec::new(&mut words);
108///
109/// // the stream is read sequentially
110/// assert_eq!(word_writer.word_pos()?, 0);
111/// assert!(word_writer.write_word(0).is_ok());
112/// assert_eq!(word_writer.word_pos()?, 1);
113/// assert!(word_writer.write_word(1).is_ok());
114/// assert_eq!(word_writer.word_pos()?, 2);
115/// # Ok(())
116/// # }
117/// ```
118#[derive(Debug, PartialEq)]
119#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
120#[cfg(feature = "alloc")]
121pub struct MemWordWriterVec<W: Word, B: AsMut<alloc::vec::Vec<W>>> {
122    data: B,
123    word_index: usize,
124    _marker: core::marker::PhantomData<W>,
125}
126
127#[cfg(feature = "alloc")]
128impl<W: Word, B: AsMut<alloc::vec::Vec<W>> + AsRef<alloc::vec::Vec<W>>> MemWordWriterVec<W, B> {
129    /// Create a new [`MemWordWriterSlice`] from a slice of **ZERO INITIALIZED** data
130    #[must_use]
131    pub fn new(data: B) -> Self {
132        Self {
133            data,
134            word_index: 0,
135            _marker: Default::default(),
136        }
137    }
138
139    pub fn len(&self) -> usize {
140        self.data.as_ref().len()
141    }
142
143    pub fn is_empty(&self) -> bool {
144        self.len() == 0
145    }
146
147    pub fn into_inner(self) -> B {
148        self.data
149    }
150}
151
152impl<W: Word, B: AsMut<[W]>> WordRead for MemWordWriterSlice<W, B> {
153    type Error = WordError;
154    type Word = W;
155
156    #[inline]
157    fn read_word(&mut self) -> Result<W, WordError> {
158        match self.data.as_mut().get(self.word_index) {
159            Some(word) => {
160                self.word_index += 1;
161                Ok(*word)
162            }
163            None => Err(WordError::UnexpectedEof {
164                word_pos: self.word_index,
165            }),
166        }
167    }
168}
169
170impl<W: Word, B: AsRef<[W]> + AsMut<[W]>> WordSeek for MemWordWriterSlice<W, B> {
171    type Error = WordError;
172
173    #[inline(always)]
174    fn word_pos(&mut self) -> Result<u64, WordError> {
175        Ok(self.word_index as u64)
176    }
177
178    #[inline(always)]
179    fn set_word_pos(&mut self, word_index: u64) -> Result<(), WordError> {
180        if word_index > self.data.as_ref().len() as u64 {
181            Err(WordError::UnexpectedEof {
182                word_pos: self.word_index,
183            })
184        } else {
185            self.word_index = word_index as usize;
186            Ok(())
187        }
188    }
189}
190
191impl<W: Word, B: AsMut<[W]>> WordWrite for MemWordWriterSlice<W, B> {
192    type Error = WordError;
193    type Word = W;
194
195    #[inline]
196    fn write_word(&mut self, word: W) -> Result<(), WordError> {
197        match self.data.as_mut().get_mut(self.word_index) {
198            Some(word_ref) => {
199                self.word_index += 1;
200                *word_ref = word;
201                Ok(())
202            }
203            None => Err(WordError::UnexpectedEof {
204                word_pos: self.word_index,
205            }),
206        }
207    }
208
209    fn flush(&mut self) -> Result<(), Self::Error> {
210        Ok(())
211    }
212}
213
214#[cfg(feature = "alloc")]
215impl<W: Word, B: AsMut<alloc::vec::Vec<W>>> WordWrite for MemWordWriterVec<W, B> {
216    type Error = Infallible;
217    type Word = W;
218
219    #[inline]
220    fn write_word(&mut self, word: W) -> Result<(), Infallible> {
221        if self.word_index >= self.data.as_mut().len() {
222            self.data.as_mut().resize(self.word_index + 1, W::ZERO);
223        }
224        self.data.as_mut()[self.word_index] = word;
225        self.word_index += 1;
226        Ok(())
227    }
228
229    fn flush(&mut self) -> Result<(), Self::Error> {
230        Ok(())
231    }
232}
233
234#[cfg(feature = "alloc")]
235impl<W: Word, B: AsMut<alloc::vec::Vec<W>>> WordRead for MemWordWriterVec<W, B> {
236    type Error = WordError;
237    type Word = W;
238
239    #[inline]
240    fn read_word(&mut self) -> Result<W, WordError> {
241        match self.data.as_mut().get(self.word_index) {
242            Some(word) => {
243                self.word_index += 1;
244                Ok(*word)
245            }
246            None => Err(WordError::UnexpectedEof {
247                word_pos: self.word_index,
248            }),
249        }
250    }
251}
252
253#[cfg(feature = "alloc")]
254impl<W: Word, B: AsMut<alloc::vec::Vec<W>> + AsRef<alloc::vec::Vec<W>>> WordSeek
255    for MemWordWriterVec<W, B>
256{
257    type Error = WordError;
258
259    #[inline(always)]
260    fn word_pos(&mut self) -> Result<u64, WordError> {
261        Ok(self.word_index as u64)
262    }
263
264    #[inline(always)]
265    fn set_word_pos(&mut self, word_index: u64) -> Result<(), WordError> {
266        if word_index > self.data.as_ref().len() as u64 {
267            Err(WordError::UnexpectedEof {
268                word_pos: self.word_index,
269            })
270        } else {
271            self.word_index = word_index as usize;
272            Ok(())
273        }
274    }
275}