Skip to main content

ext4_lwext4/blockdev/
memory.rs

1//! In-memory block device implementation.
2
3use crate::error::Result;
4use crate::blockdev::traits::BlockDevice;
5
6/// A block device backed by memory.
7///
8/// This is useful for testing and embedded scenarios where
9/// no persistent storage is available.
10pub struct MemoryBlockDevice {
11    data: Vec<u8>,
12    block_size: u32,
13    block_count: u64,
14}
15
16impl MemoryBlockDevice {
17    /// Create a new in-memory block device.
18    ///
19    /// # Arguments
20    /// * `size` - Total size in bytes
21    /// * `block_size` - Block size in bytes (typically 512 or 4096)
22    ///
23    /// # Returns
24    /// A new MemoryBlockDevice
25    pub fn new(size: u64, block_size: u32) -> Self {
26        let block_count = size / block_size as u64;
27        let actual_size = block_count * block_size as u64;
28
29        Self {
30            data: vec![0u8; actual_size as usize],
31            block_size,
32            block_count,
33        }
34    }
35
36    /// Create a new in-memory block device with default block size (512 bytes).
37    pub fn with_size(size: u64) -> Self {
38        Self::new(size, 512)
39    }
40
41    /// Create a block device from existing data.
42    ///
43    /// # Arguments
44    /// * `data` - The data to wrap
45    /// * `block_size` - Block size in bytes
46    ///
47    /// # Panics
48    /// Panics if data length is not aligned to block_size
49    pub fn from_vec(data: Vec<u8>, block_size: u32) -> Self {
50        assert!(
51            data.len() % block_size as usize == 0,
52            "data length must be aligned to block size"
53        );
54
55        let block_count = data.len() as u64 / block_size as u64;
56
57        Self {
58            data,
59            block_size,
60            block_count,
61        }
62    }
63
64    /// Get the underlying data as a slice.
65    pub fn as_slice(&self) -> &[u8] {
66        &self.data
67    }
68
69    /// Get the underlying data as a mutable slice.
70    pub fn as_mut_slice(&mut self) -> &mut [u8] {
71        &mut self.data
72    }
73
74    /// Consume the device and return the underlying data.
75    pub fn into_vec(self) -> Vec<u8> {
76        self.data
77    }
78}
79
80impl BlockDevice for MemoryBlockDevice {
81    fn read_blocks(&self, block_id: u64, buf: &mut [u8]) -> Result<u32> {
82        let offset = (block_id * self.block_size as u64) as usize;
83        let len = buf.len();
84
85        if offset + len > self.data.len() {
86            return Err(crate::error::Error::Io(std::io::Error::new(
87                std::io::ErrorKind::UnexpectedEof,
88                "read past end of device",
89            )));
90        }
91
92        buf.copy_from_slice(&self.data[offset..offset + len]);
93        Ok((len / self.block_size as usize) as u32)
94    }
95
96    fn write_blocks(&mut self, block_id: u64, buf: &[u8]) -> Result<u32> {
97        let offset = (block_id * self.block_size as u64) as usize;
98        let len = buf.len();
99
100        if offset + len > self.data.len() {
101            return Err(crate::error::Error::Io(std::io::Error::new(
102                std::io::ErrorKind::UnexpectedEof,
103                "write past end of device",
104            )));
105        }
106
107        self.data[offset..offset + len].copy_from_slice(buf);
108        Ok((len / self.block_size as usize) as u32)
109    }
110
111    fn flush(&mut self) -> Result<()> {
112        // No-op for memory device
113        Ok(())
114    }
115
116    fn block_size(&self) -> u32 {
117        self.block_size
118    }
119
120    fn block_count(&self) -> u64 {
121        self.block_count
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128
129    #[test]
130    fn test_memory_device_read_write() {
131        let mut dev = MemoryBlockDevice::new(4096, 512);
132
133        let write_buf = vec![0xAA; 512];
134        dev.write_blocks(0, &write_buf).unwrap();
135
136        let mut read_buf = vec![0u8; 512];
137        dev.read_blocks(0, &mut read_buf).unwrap();
138
139        assert_eq!(write_buf, read_buf);
140    }
141
142    #[test]
143    fn test_memory_device_block_count() {
144        let dev = MemoryBlockDevice::new(8192, 512);
145        assert_eq!(dev.block_count(), 16);
146        assert_eq!(dev.block_size(), 512);
147    }
148}