1use crate::Result;
7
8pub trait Device: Send {
9 fn size_bytes(&self) -> Result<u64>;
11
12 fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> Result<()>;
14
15 fn write_at(&mut self, offset: u64, buf: &[u8]) -> Result<()>;
17
18 fn sync(&mut self) -> Result<()>;
20
21 fn describe(&self) -> String;
24}
25
26pub fn read_vec<D: Device + ?Sized>(dev: &mut D, offset: u64, len: usize) -> Result<Vec<u8>> {
29 let mut buf = vec![0u8; len];
30 dev.read_at(offset, &mut buf)?;
31 Ok(buf)
32}
33
34pub fn write_and_verify<D: Device + ?Sized>(
41 dev: &mut D,
42 offset: u64,
43 buf: &[u8],
44) -> Result<()> {
45 dev.write_at(offset, buf)?;
46 let mut check = vec![0u8; buf.len()];
47 dev.read_at(offset, &mut check)?;
48 if check != buf {
49 let first_bad = check
50 .iter()
51 .zip(buf.iter())
52 .position(|(a, b)| a != b)
53 .unwrap_or(0);
54 return Err(crate::Error::VerifyMismatch {
55 offset: offset + first_bad as u64,
56 expected: buf[first_bad..(first_bad + 16).min(buf.len())].to_vec(),
57 actual: check[first_bad..(first_bad + 16).min(check.len())].to_vec(),
58 });
59 }
60 Ok(())
61}
62
63pub struct MemoryDevice {
65 pub bytes: Vec<u8>,
66 pub label: String,
67}
68
69impl MemoryDevice {
70 pub fn new(size: u64) -> Self {
71 Self {
72 bytes: vec![0u8; size as usize],
73 label: format!("in-memory device ({size} bytes)"),
74 }
75 }
76}
77
78impl Device for MemoryDevice {
79 fn size_bytes(&self) -> Result<u64> {
80 Ok(self.bytes.len() as u64)
81 }
82
83 fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> Result<()> {
84 let end = offset as usize + buf.len();
85 if end > self.bytes.len() {
86 return Err(crate::Error::Io(std::io::Error::new(
87 std::io::ErrorKind::UnexpectedEof,
88 "read past end of memory device",
89 )));
90 }
91 buf.copy_from_slice(&self.bytes[offset as usize..end]);
92 Ok(())
93 }
94
95 fn write_at(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
96 let end = offset as usize + buf.len();
97 if end > self.bytes.len() {
98 return Err(crate::Error::Io(std::io::Error::new(
99 std::io::ErrorKind::UnexpectedEof,
100 "write past end of memory device",
101 )));
102 }
103 self.bytes[offset as usize..end].copy_from_slice(buf);
104 Ok(())
105 }
106
107 fn sync(&mut self) -> Result<()> {
108 Ok(())
109 }
110
111 fn describe(&self) -> String {
112 self.label.clone()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn memory_device_round_trip() {
122 let mut d = MemoryDevice::new(4096);
123 write_and_verify(&mut d, 100, b"hello world").unwrap();
124 assert_eq!(&d.bytes[100..111], b"hello world");
125 }
126
127 #[test]
128 fn memory_device_rejects_past_end() {
129 let mut d = MemoryDevice::new(16);
130 assert!(d.write_at(8, b"more than 8 bytes").is_err());
131 }
132}