1use crate::block::{BlockDevice, BlockRead};
56use crate::error::{Error, Result};
57use std::sync::Arc;
58
59#[derive(Clone, Copy)]
67struct SliceGeometry {
68 start: u64,
69 length: u64,
70}
71
72impl SliceGeometry {
73 fn new(start: u64, length: u64) -> Self {
74 Self { start, length }
75 }
76
77 fn rebase(&self, offset: u64, len: u64) -> Option<u64> {
87 let end = offset.checked_add(len)?;
88 if end > self.length {
89 return None;
90 }
91 Some(self.start + offset)
92 }
93
94 fn rebase_read(&self, offset: u64, len: usize) -> Result<u64> {
100 self.rebase(offset, len as u64).ok_or(Error::ShortRead {
101 offset,
102 want: len,
103 got: 0,
104 })
105 }
106
107 fn rebase_write(&self, offset: u64, len: usize) -> Result<u64> {
112 self.rebase(offset, len as u64).ok_or(Error::OutOfBounds {
113 offset,
114 len: len as u64,
115 size: self.length,
116 })
117 }
118}
119
120pub struct SliceReader<'a> {
125 parent: &'a (dyn BlockRead + 'a),
126 geom: SliceGeometry,
127}
128
129impl<'a> SliceReader<'a> {
130 pub fn new(parent: &'a (dyn BlockRead + 'a), start: u64, length: u64) -> Self {
131 Self {
132 parent,
133 geom: SliceGeometry::new(start, length),
134 }
135 }
136
137 pub fn start(&self) -> u64 {
139 self.geom.start
140 }
141
142 pub fn length(&self) -> u64 {
144 self.geom.length
145 }
146}
147
148impl<'a> BlockRead for SliceReader<'a> {
149 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
150 let at = self.geom.rebase_read(offset, buf.len())?;
151 self.parent.read_at(at, buf)
152 }
153
154 fn size_bytes(&self) -> u64 {
155 self.geom.length
156 }
157}
158
159impl<'a> BlockDevice for SliceReader<'a> {}
163
164pub struct OwnedSlice {
170 parent: Arc<dyn BlockRead>,
171 geom: SliceGeometry,
172}
173
174impl OwnedSlice {
175 pub fn new(parent: Arc<dyn BlockRead>, start: u64, length: u64) -> Self {
176 Self {
177 parent,
178 geom: SliceGeometry::new(start, length),
179 }
180 }
181
182 pub fn start(&self) -> u64 {
184 self.geom.start
185 }
186
187 pub fn length(&self) -> u64 {
189 self.geom.length
190 }
191}
192
193impl BlockRead for OwnedSlice {
194 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
195 let at = self.geom.rebase_read(offset, buf.len())?;
196 self.parent.read_at(at, buf)
197 }
198
199 fn size_bytes(&self) -> u64 {
200 self.geom.length
201 }
202}
203
204impl BlockDevice for OwnedSlice {}
206
207pub struct OwnedRwSlice {
215 parent: Arc<dyn BlockDevice>,
216 geom: SliceGeometry,
217}
218
219impl OwnedRwSlice {
220 pub fn new(parent: Arc<dyn BlockDevice>, start: u64, length: u64) -> Self {
221 Self {
222 parent,
223 geom: SliceGeometry::new(start, length),
224 }
225 }
226
227 pub fn start(&self) -> u64 {
229 self.geom.start
230 }
231
232 pub fn length(&self) -> u64 {
234 self.geom.length
235 }
236}
237
238impl BlockRead for OwnedRwSlice {
239 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
240 let at = self.geom.rebase_read(offset, buf.len())?;
241 self.parent.read_at(at, buf)
242 }
243
244 fn size_bytes(&self) -> u64 {
245 self.geom.length
246 }
247}
248
249impl BlockDevice for OwnedRwSlice {
250 fn write_at(&self, offset: u64, buf: &[u8]) -> Result<()> {
256 let at = self.geom.rebase_write(offset, buf.len())?;
257 if !self.parent.is_writable() {
258 return Err(Error::ReadOnly);
259 }
260 self.parent.write_at(at, buf)
261 }
262
263 fn flush(&self) -> Result<()> {
264 self.parent.flush()
265 }
266
267 fn is_writable(&self) -> bool {
268 self.parent.is_writable()
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275 use std::sync::Mutex;
276
277 struct Bytes(Mutex<Vec<u8>>);
278 impl BlockRead for Bytes {
279 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
280 let b = self.0.lock().unwrap();
281 let start = offset as usize;
282 let end = start + buf.len();
283 if end > b.len() {
284 return Err(Error::ShortRead {
285 offset,
286 want: buf.len(),
287 got: b.len().saturating_sub(start),
288 });
289 }
290 buf.copy_from_slice(&b[start..end]);
291 Ok(())
292 }
293 fn size_bytes(&self) -> u64 {
294 self.0.lock().unwrap().len() as u64
295 }
296 }
297
298 #[test]
299 fn slice_reader_rebases_offsets() {
300 let mut v = vec![0u8; 4096];
301 v[2000..2004].copy_from_slice(&[0xAB, 0xCD, 0xEF, 0x01]);
302 let dev = Bytes(Mutex::new(v));
303
304 let slice = SliceReader::new(&dev, 2000, 4);
305 assert_eq!(slice.size_bytes(), 4);
306 assert_eq!(slice.start(), 2000);
307 assert_eq!(slice.length(), 4);
308
309 let mut buf = [0u8; 4];
310 slice.read_at(0, &mut buf).unwrap();
311 assert_eq!(buf, [0xAB, 0xCD, 0xEF, 0x01]);
312 }
313
314 #[test]
315 fn slice_reader_rejects_out_of_bounds() {
316 let dev = Bytes(Mutex::new(vec![0u8; 4096]));
317 let slice = SliceReader::new(&dev, 0, 16);
318 let mut buf = [0u8; 8];
319 match slice.read_at(12, &mut buf) {
320 Err(Error::ShortRead { .. }) => {}
321 other => panic!("expected ShortRead, got {other:?}"),
322 }
323 }
324
325 #[test]
326 fn owned_slice_works_through_arc() {
327 let mut v = vec![0u8; 4096];
328 v[100..104].copy_from_slice(&[0x11, 0x22, 0x33, 0x44]);
329 let dev: Arc<dyn BlockRead> = Arc::new(Bytes(Mutex::new(v)));
330
331 let slice = OwnedSlice::new(dev, 100, 4);
332 assert_eq!(slice.size_bytes(), 4);
333 let mut buf = [0u8; 4];
334 slice.read_at(0, &mut buf).unwrap();
335 assert_eq!(buf, [0x11, 0x22, 0x33, 0x44]);
336 }
337
338 #[test]
339 fn slices_reject_writes_via_blockdevice_default() {
340 let dev = Bytes(Mutex::new(vec![0u8; 16]));
341 let slice = SliceReader::new(&dev, 0, 8);
342 let err = BlockDevice::write_at(&slice, 0, &[1u8; 4]).unwrap_err();
343 assert!(matches!(err, Error::ReadOnly));
344 }
345
346 #[test]
347 fn owned_slice_accessors_report_geometry() {
348 let dev: Arc<dyn BlockRead> = Arc::new(Bytes(Mutex::new(vec![0u8; 4096])));
349 let slice = OwnedSlice::new(dev, 512, 256);
350 assert_eq!(slice.start(), 512);
351 assert_eq!(slice.length(), 256);
352 assert_eq!(slice.size_bytes(), 256);
353 }
354
355 struct RwBytes(Mutex<Vec<u8>>);
357 impl BlockRead for RwBytes {
358 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
359 let b = self.0.lock().unwrap();
360 let start = offset as usize;
361 let end = start + buf.len();
362 if end > b.len() {
363 return Err(Error::ShortRead {
364 offset,
365 want: buf.len(),
366 got: b.len().saturating_sub(start),
367 });
368 }
369 buf.copy_from_slice(&b[start..end]);
370 Ok(())
371 }
372 fn size_bytes(&self) -> u64 {
373 self.0.lock().unwrap().len() as u64
374 }
375 }
376 impl BlockDevice for RwBytes {
377 fn write_at(&self, offset: u64, buf: &[u8]) -> Result<()> {
378 let mut b = self.0.lock().unwrap();
379 let s = offset as usize;
380 b[s..s + buf.len()].copy_from_slice(buf);
381 Ok(())
382 }
383 fn is_writable(&self) -> bool {
384 true
385 }
386 }
387
388 #[test]
389 fn owned_rw_slice_accessors_report_geometry() {
390 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
391 let slice = OwnedRwSlice::new(dev, 16, 32);
392 assert_eq!(slice.start(), 16);
393 assert_eq!(slice.length(), 32);
394 assert_eq!(slice.size_bytes(), 32);
395 assert!(slice.is_writable());
396 }
397
398 #[test]
399 fn owned_rw_slice_rebases_reads_and_writes() {
400 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
401 let slice = OwnedRwSlice::new(dev.clone(), 16, 32);
402
403 slice.write_at(0, &[0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
405 let mut buf = [0u8; 4];
406 slice.read_at(0, &mut buf).unwrap();
407 assert_eq!(buf, [0xDE, 0xAD, 0xBE, 0xEF]);
408
409 let mut pbuf = [0u8; 4];
411 dev.read_at(16, &mut pbuf).unwrap();
412 assert_eq!(pbuf, [0xDE, 0xAD, 0xBE, 0xEF]);
413 }
414
415 #[test]
416 fn owned_rw_slice_rejects_out_of_bounds_write() {
417 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
418 let slice = OwnedRwSlice::new(dev, 0, 8);
419 match slice.write_at(6, &[0u8; 4]) {
420 Err(Error::OutOfBounds { .. }) => {}
421 other => panic!("expected OutOfBounds, got {other:?}"),
422 }
423 }
424
425 #[test]
430 fn same_out_of_range_span_is_short_read_for_a_read_and_out_of_bounds_for_a_write() {
431 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 64])));
432 let slice = OwnedRwSlice::new(dev, 16, 8);
433
434 let mut buf = [0u8; 4];
435 match slice.read_at(6, &mut buf) {
436 Err(Error::ShortRead { offset, want, got }) => {
437 assert_eq!((offset, want, got), (6, 4, 0));
438 }
439 other => panic!("expected ShortRead, got {other:?}"),
440 }
441
442 match slice.write_at(6, &[0u8; 4]) {
443 Err(Error::OutOfBounds { offset, len, size }) => {
444 assert_eq!((offset, len, size), (6, 4, 8));
445 }
446 other => panic!("expected OutOfBounds, got {other:?}"),
447 }
448 }
449
450 #[test]
451 fn owned_rw_slice_flush_delegates_to_parent() {
452 let dev: Arc<dyn BlockDevice> = Arc::new(RwBytes(Mutex::new(vec![0u8; 8])));
453 let slice = OwnedRwSlice::new(dev, 0, 8);
454 slice.flush().unwrap();
456 }
457}