Skip to main content

mesa3d_util/bytestream/
mod.rs

1// Copyright 2025 Google
2// SPDX-License-Identifier: MIT
3
4use std::io::BufRead;
5use std::io::Error;
6use std::io::ErrorKind;
7use std::io::Read;
8use std::io::Result;
9use std::mem::size_of;
10
11use zerocopy::FromBytes;
12use zerocopy::Immutable;
13use zerocopy::IntoBytes;
14
15pub struct Reader<'slice> {
16    data: &'slice [u8],
17}
18
19impl<'slice> Reader<'slice> {
20    /// Construct a new Reader wrapper over `data`.
21    pub fn new(data: &[u8]) -> Reader<'_> {
22        Reader { data }
23    }
24
25    /// Reads and consumes an object from the buffer.
26    pub fn read_obj<T: FromBytes>(&mut self) -> Result<T> {
27        let obj = <T>::read_from_prefix(self.data.as_bytes())
28            .map_err(|_e| Error::from(ErrorKind::UnexpectedEof))?;
29        self.consume(size_of::<T>());
30        Ok(obj.0)
31    }
32
33    #[allow(dead_code)]
34    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
35        self.data.read(buf)
36    }
37
38    pub fn available_bytes(&self) -> usize {
39        self.data.len()
40    }
41
42    /// Reads an object from the buffer without consuming it.
43    pub fn peek_obj<T: FromBytes>(&self) -> Result<T> {
44        let obj = <T>::read_from_prefix(self.data.as_bytes())
45            .map_err(|_e| Error::from(ErrorKind::UnexpectedEof))?;
46        Ok(obj.0)
47    }
48
49    pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
50        self.data.read_exact(buf)
51    }
52
53    /// Consumes `amt` bytes from the underlying buffer. If `amt` is larger than the
54    /// remaining data left in this `Reader`, then all remaining data will be consumed.
55    pub fn consume(&mut self, amt: usize) {
56        self.data.consume(amt);
57    }
58}
59
60pub struct Writer<'slice> {
61    data: &'slice mut [u8],
62    index: usize,
63}
64
65impl<'slice> Writer<'slice> {
66    pub fn new(data: &mut [u8]) -> Writer<'_> {
67        Writer { data, index: 0 }
68    }
69
70    /// Writes an object to the buffer.
71    pub fn write_obj<T: FromBytes + IntoBytes + Immutable>(&mut self, val: T) -> Result<()> {
72        self.write_all(val.as_bytes())
73    }
74
75    pub fn write_all(&mut self, buf: &[u8]) -> Result<()> {
76        let new_index = self.index + buf.len();
77
78        let Some(data) = self.data.get_mut(self.index..new_index) else {
79            return Err(Error::from(ErrorKind::UnexpectedEof));
80        };
81
82        data.copy_from_slice(buf);
83        self.index = new_index;
84        Ok(())
85    }
86
87    pub fn bytes_written(&self) -> usize {
88        self.index
89    }
90}