1use std::ops::Range;
6use std::sync::Arc;
7use thiserror::Error;
8use zerocopy::{FromBytes, IntoBytes};
9
10#[derive(Error, Debug, Clone, PartialEq)]
12pub enum ReaderError {
13 #[error("Failed to set up reader with status: {}", _0)]
14 Setup(zx::Status),
15 #[error("Read error at 0x{:X}..0x{:X} with status: {}", _0.start, _0.end, _1)]
16 Read(Range<u64>, zx::Status),
17 #[error("Out of bound read 0x{:X}..0x{:X} when size is 0x{:X}", _0.start, _0.end, _1)]
18 OutOfBounds(Range<u64>, u64),
19}
20
21pub trait Reader: Send + Sync {
23 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError>;
25}
26
27pub trait ReaderExt {
28 fn read_object<T>(&self, offset: u64) -> Result<T, ReaderError>
29 where
30 T: FromBytes + IntoBytes + Sized;
31}
32
33impl ReaderExt for dyn Reader + '_ {
34 fn read_object<T>(&self, offset: u64) -> Result<T, ReaderError>
35 where
36 T: FromBytes + IntoBytes + Sized,
37 {
38 let mut object = T::new_zeroed();
39 self.read(offset, object.as_mut_bytes())?;
40 Ok(object)
41 }
42}
43
44impl Reader for Box<dyn Reader> {
45 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
46 self.as_ref().read(offset, data)
47 }
48}
49
50impl Reader for Arc<dyn Reader> {
51 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
52 self.as_ref().read(offset, data)
53 }
54}
55
56pub struct VecReader {
58 data: Vec<u8>,
59}
60
61impl Reader for VecReader {
62 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
63 let data_len = data.len() as u64;
64 let self_data_len = self.data.len() as u64;
65 let offset_max = offset + data_len;
66 if offset_max > self_data_len {
67 return Err(ReaderError::OutOfBounds(offset..offset_max, self_data_len));
68 }
69
70 let offset_for_range: usize = offset.try_into().unwrap();
71 let slice = self.data.get(offset_for_range..offset_for_range + data.len()).unwrap();
73 data.clone_from_slice(slice);
74 Ok(())
75 }
76}
77
78impl VecReader {
79 pub fn new(filesystem: Vec<u8>) -> Self {
81 VecReader { data: filesystem }
82 }
83}
84
85pub struct VmoReader {
87 vmo: Arc<zx::Vmo>,
88 size: u64,
89}
90
91impl Reader for VmoReader {
92 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
93 match self.vmo.read(data, offset) {
94 Ok(_) => Ok(()),
95 Err(zx::Status::OUT_OF_RANGE) => {
96 Err(ReaderError::OutOfBounds(offset..offset + data.len() as u64, self.size))
97 }
98 Err(status) => Err(ReaderError::Read(offset..offset + data.len() as u64, status)),
99 }
100 }
101}
102
103impl VmoReader {
104 pub fn new(vmo: Arc<zx::Vmo>) -> Result<Self, ReaderError> {
106 let size = vmo.get_size().map_err(|status| ReaderError::Setup(status))?;
107 Ok(VmoReader { vmo, size })
108 }
109}