1use crate::block::{BlockDevice, BlockRead};
15use crate::error::Result;
16
17pub struct ReadOnlyDevice<T> {
19 inner: T,
20}
21
22impl<T> ReadOnlyDevice<T> {
23 pub fn new(inner: T) -> Self {
24 Self { inner }
25 }
26
27 pub fn inner(&self) -> &T {
29 &self.inner
30 }
31
32 pub fn into_inner(self) -> T {
34 self.inner
35 }
36}
37
38impl<T: BlockRead> BlockRead for ReadOnlyDevice<T> {
39 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
40 self.inner.read_at(offset, buf)
41 }
42
43 fn size_bytes(&self) -> u64 {
44 self.inner.size_bytes()
45 }
46}
47
48impl<T: BlockRead> BlockDevice for ReadOnlyDevice<T> {}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::error::Error;
57 use crate::test_device::RwBytes as WritableBytes;
58 use std::sync::Mutex;
59
60 #[test]
61 fn read_through_works() {
62 let mut v = vec![0u8; 16];
63 v[4..8].copy_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]);
64 let wrapped = ReadOnlyDevice::new(WritableBytes(Mutex::new(v)));
65
66 let mut buf = [0u8; 4];
67 wrapped.read_at(4, &mut buf).unwrap();
68 assert_eq!(buf, [0xAA, 0xBB, 0xCC, 0xDD]);
69 }
70
71 #[test]
72 fn writes_rejected_even_though_inner_is_writable() {
73 let wrapped = ReadOnlyDevice::new(WritableBytes(Mutex::new(vec![0u8; 16])));
74 assert!(!BlockDevice::is_writable(&wrapped));
75
76 match BlockDevice::write_at(&wrapped, 0, &[0xFFu8; 4]) {
77 Err(Error::ReadOnly) => {}
78 other => panic!("expected ReadOnly, got {other:?}"),
79 }
80 }
81
82 #[test]
83 fn into_inner_returns_unchanged() {
84 let inner = WritableBytes(Mutex::new(vec![0u8; 8]));
85 let wrapped = ReadOnlyDevice::new(inner);
86 let back = wrapped.into_inner();
87 assert!(BlockDevice::is_writable(&back));
89 back.write_at(0, &[0x42; 4]).unwrap();
91 let mut buf = [0u8; 4];
92 back.read_at(0, &mut buf).unwrap();
93 assert_eq!(buf, [0x42; 4]);
94 }
95
96 #[test]
97 fn inner_borrows_without_consuming() {
98 let mut v = vec![0u8; 8];
99 v[0..2].copy_from_slice(&[0x9A, 0xBC]);
100 let wrapped = ReadOnlyDevice::new(WritableBytes(Mutex::new(v)));
101
102 assert!(BlockDevice::is_writable(wrapped.inner()));
105 assert_eq!(wrapped.inner().size_bytes(), 8);
106
107 let mut buf = [0u8; 2];
109 wrapped.read_at(0, &mut buf).unwrap();
110 assert_eq!(buf, [0x9A, 0xBC]);
111 }
112}