1use fuchsia_sync::Mutex;
6use std::io::{Read, Seek, SeekFrom};
7use std::sync::Arc;
8use thiserror::Error;
9
10#[cfg(target_os = "fuchsia")]
11pub use self::fuchsia::*;
12
13#[derive(Error, Debug, PartialEq)]
14pub enum ReaderError {
15 #[error("Read error at: 0x{:X}", _0)]
16 Read(u64),
17 #[error("Out of bound read 0x{:X} when size is 0x{:X}", _0, _1)]
18 OutOfBounds(u64, u64),
19 #[error("Write error at: 0x{:X}", _0)]
20 Write(u64),
21 #[error("{} not supported", _0)]
22 NotSupported(String),
23 #[error("Write flush error")]
24 WriteFlush,
25}
26
27pub trait Reader: Send + Sync {
28 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError>;
29}
30
31impl Reader for Box<dyn Reader> {
35 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
36 self.as_ref().read(offset, data)
37 }
38}
39
40impl Reader for Arc<dyn Reader> {
41 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
42 self.as_ref().read(offset, data)
43 }
44}
45
46pub trait ReaderWriter: Reader {
48 fn write(&self, _offset: u64, _data: &[u8]) -> Result<(), ReaderError> {
49 Err(ReaderError::NotSupported("Write".to_string()))
50 }
51 fn sync(&self) -> Result<(), ReaderError> {
52 Ok(())
53 }
54}
55
56impl Reader for Box<dyn ReaderWriter> {
57 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
58 self.as_ref().read(offset, data)
59 }
60}
61
62impl ReaderWriter for Box<dyn ReaderWriter> {
63 fn write(&self, offset: u64, data: &[u8]) -> Result<(), ReaderError> {
64 self.as_ref().write(offset, data)
65 }
66 fn sync(&self) -> Result<(), ReaderError> {
67 self.as_ref().sync()
68 }
69}
70
71impl Reader for Arc<dyn ReaderWriter> {
72 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
73 self.as_ref().read(offset, data)
74 }
75}
76
77impl ReaderWriter for Arc<dyn ReaderWriter> {
78 fn write(&self, offset: u64, data: &[u8]) -> Result<(), ReaderError> {
79 self.as_ref().write(offset, data)
80 }
81 fn sync(&self) -> Result<(), ReaderError> {
82 self.as_ref().sync()
83 }
84}
85
86pub struct IoAdapter<T>(Mutex<T>);
88
89impl<T> IoAdapter<T> {
90 pub fn new(inner: T) -> Self {
91 Self(Mutex::new(inner))
92 }
93}
94
95impl<T: Read + Seek + Send + Sync> Reader for IoAdapter<T> {
96 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
97 let mut reader = self.0.lock();
98 reader.seek(SeekFrom::Start(offset)).map_err(|_| ReaderError::Read(offset))?;
99 reader.read_exact(data).map_err(|_| ReaderError::Read(offset))
100 }
101}
102
103impl<T: Read + Seek + Send + Sync> ReaderWriter for IoAdapter<T> {}
104
105pub struct VecReader {
106 data: Vec<u8>,
107}
108
109impl Reader for VecReader {
110 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
111 let data_len = data.len() as u64;
112 let self_data_len = self.data.len() as u64;
113 let offset_max = offset + data_len;
114 if offset_max > self_data_len {
115 return Err(ReaderError::OutOfBounds(offset_max, self_data_len));
116 }
117
118 let offset_for_range: usize = offset.try_into().unwrap();
119
120 match self.data.get(offset_for_range..offset_for_range + data.len()) {
121 Some(slice) => {
122 data.clone_from_slice(slice);
123 Ok(())
124 }
125 None => Err(ReaderError::Read(offset)),
126 }
127 }
128}
129
130impl ReaderWriter for VecReader {
131 fn write(&self, _offset: u64, _data: &[u8]) -> Result<(), ReaderError> {
132 Err(ReaderError::NotSupported("Write".to_string()))
133 }
134}
135
136impl VecReader {
137 pub fn new(filesystem: Vec<u8>) -> Self {
138 VecReader { data: filesystem }
139 }
140}
141
142#[cfg(target_os = "fuchsia")]
143mod fuchsia {
144 use super::{Reader, ReaderError, ReaderWriter};
145 use anyhow::Error;
146 use block_client::{Cache, RemoteBlockClientSync};
147 use fidl::endpoints::ClientEnd;
148 use fidl_fuchsia_storage_block::BlockMarker;
149 use fuchsia_sync::Mutex;
150 use log::error;
151 use std::io::Write as _;
152 use std::sync::Arc;
153
154 pub struct VmoReader {
155 vmo: Arc<zx::Vmo>,
156 }
157
158 impl Reader for VmoReader {
159 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
160 match self.vmo.read(data, offset) {
161 Ok(_) => Ok(()),
162 Err(zx::Status::OUT_OF_RANGE) => {
163 let size = self.vmo.get_size().map_err(|_| ReaderError::Read(u64::MAX))?;
164 Err(ReaderError::OutOfBounds(offset, size))
165 }
166 Err(_) => Err(ReaderError::Read(offset)),
167 }
168 }
169 }
170
171 impl ReaderWriter for VmoReader {
172 fn write(&self, _offset: u64, _data: &[u8]) -> Result<(), ReaderError> {
173 Err(ReaderError::NotSupported("Write".to_string()))
174 }
175 }
176
177 impl VmoReader {
178 pub fn new(vmo: Arc<zx::Vmo>) -> Self {
179 VmoReader { vmo }
180 }
181 }
182
183 pub struct BlockDeviceReader {
184 block_cache: Mutex<Cache>,
185 }
186
187 impl Reader for BlockDeviceReader {
188 fn read(&self, offset: u64, data: &mut [u8]) -> Result<(), ReaderError> {
189 self.block_cache.lock().read_at(data, offset).map_err(|e| {
190 error!("Encountered error while reading block device: {}", e);
191 ReaderError::Read(offset)
192 })
193 }
194 }
195
196 impl ReaderWriter for BlockDeviceReader {
197 fn write(&self, offset: u64, data: &[u8]) -> Result<(), ReaderError> {
198 self.block_cache.lock().write_at(data, offset).map_err(|e| {
199 error!("Encountered error while writing block device: {}", e);
200 ReaderError::Write(offset)
201 })
202 }
203
204 fn sync(&self) -> Result<(), ReaderError> {
205 self.block_cache.lock().flush().map_err(|e| {
206 error!("Encountered error while flushing block cache: {}", e);
207 ReaderError::WriteFlush
208 })
209 }
210 }
211
212 impl BlockDeviceReader {
213 pub fn from_client_end(client_end: ClientEnd<BlockMarker>) -> Result<Self, Error> {
214 Ok(Self {
215 block_cache: Mutex::new(Cache::new(RemoteBlockClientSync::new(client_end)?)?),
216 })
217 }
218 }
219}