1 // Copyright 2024 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::io::BufRead; 6 use std::io::Error as IoError; 7 use std::io::ErrorKind as IoErrorKind; 8 use std::io::Read; 9 use std::io::Result as IoResult; 10 use std::mem::size_of; 11 12 use zerocopy::AsBytes; 13 use zerocopy::FromBytes; 14 15 pub struct Reader<'slice> { 16 data: &'slice [u8], 17 } 18 19 impl<'slice> Reader<'slice> { 20 /// Construct a new Reader wrapper over `data`. new(data: &[u8]) -> Reader21 pub fn new(data: &[u8]) -> Reader { 22 Reader { data } 23 } 24 25 /// Reads and consumes an object from the buffer. read_obj<T: FromBytes>(&mut self) -> IoResult<T>26 pub fn read_obj<T: FromBytes>(&mut self) -> IoResult<T> { 27 let obj = <T>::read_from_prefix(self.data.as_bytes()) 28 .ok_or(IoError::from(IoErrorKind::UnexpectedEof))?; 29 self.consume(size_of::<T>()); 30 Ok(obj) 31 } 32 33 #[allow(dead_code)] read(&mut self, buf: &mut [u8]) -> IoResult<usize>34 fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { 35 self.data.read(buf) 36 } 37 available_bytes(&self) -> usize38 pub fn available_bytes(&self) -> usize { 39 self.data.len() 40 } 41 42 /// Reads an object from the buffer without consuming it. peek_obj<T: FromBytes>(&self) -> IoResult<T>43 pub fn peek_obj<T: FromBytes>(&self) -> IoResult<T> { 44 let obj = <T>::read_from_prefix(self.data.as_bytes()) 45 .ok_or(IoError::from(IoErrorKind::UnexpectedEof))?; 46 Ok(obj) 47 } 48 read_exact(&mut self, buf: &mut [u8]) -> IoResult<()>49 pub fn read_exact(&mut self, buf: &mut [u8]) -> IoResult<()> { 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. consume(&mut self, amt: usize)55 pub fn consume(&mut self, amt: usize) { 56 self.data.consume(amt); 57 } 58 } 59 60 pub struct Writer<'slice> { 61 data: &'slice mut [u8], 62 index: usize, 63 } 64 65 impl<'slice> Writer<'slice> { new(data: &mut [u8]) -> Writer66 pub fn new(data: &mut [u8]) -> Writer { 67 Writer { data, index: 0 } 68 } 69 70 /// Writes an object to the buffer. write_obj<T: FromBytes + AsBytes>(&mut self, val: T) -> IoResult<()>71 pub fn write_obj<T: FromBytes + AsBytes>(&mut self, val: T) -> IoResult<()> { 72 self.write_all(val.as_bytes()) 73 } 74 write_all(&mut self, buf: &[u8]) -> IoResult<()>75 pub fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { 76 let new_index = self.index + buf.len(); 77 78 if new_index >= self.data.len() { 79 return Err(IoError::from(IoErrorKind::UnexpectedEof)); 80 } 81 82 self.data[self.index..new_index].copy_from_slice(buf); 83 self.index = new_index; 84 Ok(()) 85 } 86 bytes_written(&self) -> usize87 pub fn bytes_written(&self) -> usize { 88 self.index 89 } 90 } 91