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