1use crate::block::{BlockDevice, BlockRead};
19use crate::error::{Error, Result};
20use std::sync::Arc;
21
22pub struct SliceReader<'a> {
27 parent: &'a (dyn BlockRead + 'a),
28 start: u64,
29 length: u64,
30}
31
32impl<'a> SliceReader<'a> {
33 pub fn new(parent: &'a (dyn BlockRead + 'a), start: u64, length: u64) -> Self {
34 Self {
35 parent,
36 start,
37 length,
38 }
39 }
40
41 pub fn start(&self) -> u64 {
43 self.start
44 }
45
46 pub fn length(&self) -> u64 {
48 self.length
49 }
50}
51
52impl<'a> BlockRead for SliceReader<'a> {
53 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
54 let want = buf.len() as u64;
55 if offset
56 .checked_add(want)
57 .map(|e| e > self.length)
58 .unwrap_or(true)
59 {
60 return Err(Error::ShortRead {
61 offset,
62 want: buf.len(),
63 got: 0,
64 });
65 }
66 self.parent.read_at(self.start + offset, buf)
67 }
68
69 fn size_bytes(&self) -> u64 {
70 self.length
71 }
72}
73
74impl<'a> BlockDevice for SliceReader<'a> {}
78
79pub struct OwnedSlice {
83 parent: Arc<dyn BlockRead>,
84 start: u64,
85 length: u64,
86}
87
88impl OwnedSlice {
89 pub fn new(parent: Arc<dyn BlockRead>, start: u64, length: u64) -> Self {
90 Self {
91 parent,
92 start,
93 length,
94 }
95 }
96
97 pub fn start(&self) -> u64 {
98 self.start
99 }
100
101 pub fn length(&self) -> u64 {
102 self.length
103 }
104}
105
106impl BlockRead for OwnedSlice {
107 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
108 let want = buf.len() as u64;
109 if offset
110 .checked_add(want)
111 .map(|e| e > self.length)
112 .unwrap_or(true)
113 {
114 return Err(Error::ShortRead {
115 offset,
116 want: buf.len(),
117 got: 0,
118 });
119 }
120 self.parent.read_at(self.start + offset, buf)
121 }
122
123 fn size_bytes(&self) -> u64 {
124 self.length
125 }
126}
127
128impl BlockDevice for OwnedSlice {}
130
131pub struct OwnedRwSlice {
136 parent: Arc<dyn BlockDevice>,
137 start: u64,
138 length: u64,
139}
140
141impl OwnedRwSlice {
142 pub fn new(parent: Arc<dyn BlockDevice>, start: u64, length: u64) -> Self {
143 Self {
144 parent,
145 start,
146 length,
147 }
148 }
149
150 pub fn start(&self) -> u64 {
151 self.start
152 }
153
154 pub fn length(&self) -> u64 {
155 self.length
156 }
157}
158
159impl BlockRead for OwnedRwSlice {
160 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
161 let want = buf.len() as u64;
162 if offset
163 .checked_add(want)
164 .map(|e| e > self.length)
165 .unwrap_or(true)
166 {
167 return Err(Error::ShortRead {
168 offset,
169 want: buf.len(),
170 got: 0,
171 });
172 }
173 self.parent.read_at(self.start + offset, buf)
174 }
175
176 fn size_bytes(&self) -> u64 {
177 self.length
178 }
179}
180
181impl BlockDevice for OwnedRwSlice {
182 fn write_at(&self, offset: u64, buf: &[u8]) -> Result<()> {
183 let want = buf.len() as u64;
184 if offset
185 .checked_add(want)
186 .map(|e| e > self.length)
187 .unwrap_or(true)
188 {
189 return Err(Error::OutOfBounds {
190 offset,
191 len: want,
192 size: self.length,
193 });
194 }
195 if !self.parent.is_writable() {
196 return Err(Error::ReadOnly);
197 }
198 self.parent.write_at(self.start + offset, buf)
199 }
200
201 fn flush(&self) -> Result<()> {
202 self.parent.flush()
203 }
204
205 fn is_writable(&self) -> bool {
206 self.parent.is_writable()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use std::sync::Mutex;
214
215 struct Bytes(Mutex<Vec<u8>>);
216 impl BlockRead for Bytes {
217 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
218 let b = self.0.lock().unwrap();
219 let start = offset as usize;
220 let end = start + buf.len();
221 if end > b.len() {
222 return Err(Error::ShortRead {
223 offset,
224 want: buf.len(),
225 got: b.len().saturating_sub(start),
226 });
227 }
228 buf.copy_from_slice(&b[start..end]);
229 Ok(())
230 }
231 fn size_bytes(&self) -> u64 {
232 self.0.lock().unwrap().len() as u64
233 }
234 }
235
236 #[test]
237 fn slice_reader_rebases_offsets() {
238 let mut v = vec![0u8; 4096];
239 v[2000..2004].copy_from_slice(&[0xAB, 0xCD, 0xEF, 0x01]);
240 let dev = Bytes(Mutex::new(v));
241
242 let slice = SliceReader::new(&dev, 2000, 4);
243 assert_eq!(slice.size_bytes(), 4);
244 assert_eq!(slice.start(), 2000);
245 assert_eq!(slice.length(), 4);
246
247 let mut buf = [0u8; 4];
248 slice.read_at(0, &mut buf).unwrap();
249 assert_eq!(buf, [0xAB, 0xCD, 0xEF, 0x01]);
250 }
251
252 #[test]
253 fn slice_reader_rejects_out_of_bounds() {
254 let dev = Bytes(Mutex::new(vec![0u8; 4096]));
255 let slice = SliceReader::new(&dev, 0, 16);
256 let mut buf = [0u8; 8];
257 match slice.read_at(12, &mut buf) {
258 Err(Error::ShortRead { .. }) => {}
259 other => panic!("expected ShortRead, got {other:?}"),
260 }
261 }
262
263 #[test]
264 fn owned_slice_works_through_arc() {
265 let mut v = vec![0u8; 4096];
266 v[100..104].copy_from_slice(&[0x11, 0x22, 0x33, 0x44]);
267 let dev: Arc<dyn BlockRead> = Arc::new(Bytes(Mutex::new(v)));
268
269 let slice = OwnedSlice::new(dev, 100, 4);
270 assert_eq!(slice.size_bytes(), 4);
271 let mut buf = [0u8; 4];
272 slice.read_at(0, &mut buf).unwrap();
273 assert_eq!(buf, [0x11, 0x22, 0x33, 0x44]);
274 }
275
276 #[test]
277 fn slices_reject_writes_via_blockdevice_default() {
278 let dev = Bytes(Mutex::new(vec![0u8; 16]));
279 let slice = SliceReader::new(&dev, 0, 8);
280 let err = BlockDevice::write_at(&slice, 0, &[1u8; 4]).unwrap_err();
281 assert!(matches!(err, Error::ReadOnly));
282 }
283
284 #[test]
285 fn owned_slice_accessors_report_geometry() {
286 let dev: Arc<dyn BlockRead> = Arc::new(Bytes(Mutex::new(vec![0u8; 4096])));
287 let slice = OwnedSlice::new(dev, 512, 256);
288 assert_eq!(slice.start(), 512);
289 assert_eq!(slice.length(), 256);
290 assert_eq!(slice.size_bytes(), 256);
291 }
292
293 struct RwBytes(Mutex<Vec<u8>>);
295 impl BlockRead for RwBytes {
296 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
297 let b = self.0.lock().unwrap();
298 let start = offset as usize;
299 let end = start + buf.len();
300 if end > b.len() {
301 return Err(Error::ShortRead {
302 offset,
303 want: buf.len(),
304 got: b.len().saturating_sub(start),
305 });
306 }
307 buf.copy_from_slice(&b[start..end]);
308 Ok(())
309 }
310 fn size_bytes(&self) -> u64 {
311 self.0.lock().unwrap().len() as u64
312 }
313 }
314 impl BlockDevice for RwBytes {
315 fn write_at(&self, offset: u64, buf: &[u8]) -> Result<()> {
316 let mut b = self.0.lock().unwrap();
317 let s = offset as usize;
318 b[s..s + buf.len()].copy_from_slice(buf);
319 Ok(())
320 }
321 fn is_writable(&self) -> bool {
322 true
323 }
324 }
325
326 #[test]
327 fn owned_rw_slice_accessors_report_geometry() {
328 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
329 let slice = OwnedRwSlice::new(dev, 16, 32);
330 assert_eq!(slice.start(), 16);
331 assert_eq!(slice.length(), 32);
332 assert_eq!(slice.size_bytes(), 32);
333 assert!(slice.is_writable());
334 }
335
336 #[test]
337 fn owned_rw_slice_rebases_reads_and_writes() {
338 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
339 let slice = OwnedRwSlice::new(dev.clone(), 16, 32);
340
341 slice.write_at(0, &[0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
343 let mut buf = [0u8; 4];
344 slice.read_at(0, &mut buf).unwrap();
345 assert_eq!(buf, [0xDE, 0xAD, 0xBE, 0xEF]);
346
347 let mut pbuf = [0u8; 4];
349 dev.read_at(16, &mut pbuf).unwrap();
350 assert_eq!(pbuf, [0xDE, 0xAD, 0xBE, 0xEF]);
351 }
352
353 #[test]
354 fn owned_rw_slice_rejects_out_of_bounds_write() {
355 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
356 let slice = OwnedRwSlice::new(dev, 0, 8);
357 match slice.write_at(6, &[0u8; 4]) {
358 Err(Error::OutOfBounds { .. }) => {}
359 other => panic!("expected OutOfBounds, got {other:?}"),
360 }
361 }
362
363 #[test]
364 fn owned_rw_slice_flush_delegates_to_parent() {
365 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 8])));
366 let slice = OwnedRwSlice::new(dev, 0, 8);
367 slice.flush().unwrap();
369 }
370}