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