file_system/memory_device.rs
1//! In-memory device implementation for testing and simulation.
2
3//!
4//! This module provides a memory-based device implementation that stores data
5//! in RAM instead of on physical storage. It's primarily used for testing,
6//! simulation, and development purposes where you need a device that behaves
7//! like storage but doesn't require actual hardware.
8
9use alloc::vec;
10use alloc::vec::Vec;
11use futures::block_on;
12use synchronization::{blocking_mutex::raw::CriticalSectionRawMutex, rwlock::RwLock};
13
14use crate::{DeviceTrait, Position, Size};
15
16/// In-memory device implementation with configurable block size.
17///
18/// This device stores all data in memory using a `Vec<u8>` and provides the same
19/// interface as physical storage devices. It's thread-safe and supports all standard
20/// device operations. The block size is configurable at compile time through the
21/// const generic parameter.
22///
23/// # Type Parameters
24///
25/// * `Block_size` - The block size in bytes (must be a power of 2, typically 512)
26///
27/// # Examples
28///
29/// ```rust
30/// # extern crate alloc;
31/// # use file_system::*;
32///
33/// // Create a 1MB memory device with 512-byte blocks
34/// let device = Memory_device_type::<512>::new(1024 * 1024);
35/// let device = create_device!(device);
36///
37/// // Write some data
38/// let data = b"Hello, Memory Device!";
39/// device.Write(data).unwrap();
40///
41/// // Reset position and read back
42/// device.Set_position(&Position_type::Start(0)).unwrap();
43/// let mut buffer = alloc::vec![0u8; data.len()];
44/// device.Read(&mut buffer).unwrap();
45/// assert_eq!(&buffer, data);
46/// ```
47///
48/// # Thread Safety
49///
50/// The device uses an `RwLock` to ensure thread-safe access to the underlying data.
51/// Multiple readers can access the device simultaneously, but writes are exclusive.
52pub struct MemoryDevice<const BLOCK_SIZE: usize>(RwLock<CriticalSectionRawMutex, (Vec<u8>, usize)>);
53
54impl<const BLOCK_SIZE: usize> MemoryDevice<BLOCK_SIZE> {
55 /// Create a new memory device with the specified size.
56 ///
57 /// The device will be initialized with zeros and have the specified total size.
58 /// The size must be a multiple of the block size.
59 ///
60 /// # Arguments
61 ///
62 /// * `Size` - Total size of the device in bytes
63 ///
64 /// # Panics
65 ///
66 /// Panics if `Size` is not a multiple of `Block_size`.
67 ///
68 /// # Examples
69 ///
70 /// ```rust
71 /// # extern crate alloc;
72 /// # use file_system::Memory_device_type;
73 ///
74 /// // Create a 4KB device with 512-byte blocks
75 /// let device = Memory_device_type::<512>::new(4096);
76 /// ```
77 pub fn new(size: usize) -> Self {
78 assert!(size.is_multiple_of(BLOCK_SIZE));
79
80 let data: Vec<u8> = vec![0; size];
81
82 Self(RwLock::new((data, 0)))
83 }
84
85 /// Create a memory device from existing data.
86 ///
87 /// This allows you to create a device with pre-populated data, useful for
88 /// testing with known data patterns or loading device images.
89 ///
90 /// # Arguments
91 ///
92 /// * `Data` - Vector containing the initial device data
93 ///
94 /// # Panics
95 ///
96 /// Panics if the data length is not a multiple of `Block_size`.
97 ///
98 /// # Examples
99 ///
100 /// ```rust
101 /// # extern crate alloc;
102 /// # use file_system::Memory_device_type;
103 /// # use alloc::vec;
104 ///
105 /// // Create device with specific data
106 /// let data = vec![0x42; 1024]; // 1KB of 0x42 bytes
107 /// let device = Memory_device_type::<512>::From_vec(data);
108 /// ```
109 pub fn from_vec(data: Vec<u8>) -> Self {
110 assert!(data.len().is_multiple_of(BLOCK_SIZE));
111
112 Self(RwLock::new((data, 0)))
113 }
114
115 /// Get the number of blocks in this device.
116 ///
117 /// Returns the total number of blocks of size `Block_size` that fit in the device.
118 ///
119 /// # Returns
120 ///
121 /// The number of blocks in the device.
122 ///
123 /// # Examples
124 ///
125 /// ```rust
126 /// # extern crate alloc;
127 /// # use file_system::Memory_device_type;
128 ///
129 /// let device = Memory_device_type::<512>::new(2048);
130 /// assert_eq!(device.get_block_count(), 4); // 2048 / 512 = 4
131 /// ```
132 pub fn get_block_count(&self) -> usize {
133 let inner = block_on(self.0.read());
134
135 inner.0.len() / BLOCK_SIZE
136 }
137}
138
139impl<const BLOCK_SIZE: usize> DeviceTrait for MemoryDevice<BLOCK_SIZE> {
140 /// Read data from the memory device.
141 ///
142 /// Reads data from the current position into the provided buffer.
143 /// The position is automatically advanced by the number of bytes read.
144 fn read(&self, buffer: &mut [u8]) -> crate::Result<Size> {
145 let mut inner = self
146 .0
147 .try_write()
148 .map_err(|_| crate::Error::RessourceBusy)?;
149 let (data, position) = &mut *inner;
150
151 let read_size = buffer.len().min(data.len().saturating_sub(*position));
152 buffer[..read_size].copy_from_slice(&data[*position..*position + read_size]);
153 *position += read_size;
154 Ok(read_size.into())
155 }
156
157 fn write(&self, buffer: &[u8]) -> crate::Result<Size> {
158 let mut inner = block_on(self.0.write());
159 let (data, position) = &mut *inner;
160
161 data[*position..*position + buffer.len()].copy_from_slice(buffer);
162 *position += buffer.len();
163 Ok(buffer.len().into())
164 }
165
166 fn get_size(&self) -> crate::Result<Size> {
167 let inner = block_on(self.0.read());
168
169 Ok(Size::new(inner.0.len() as u64))
170 }
171
172 fn set_position(&self, position: &Position) -> crate::Result<Size> {
173 let mut inner = block_on(self.0.write());
174 let (data, device_position) = &mut *inner;
175
176 match position {
177 Position::Start(position) => *device_position = *position as usize,
178 Position::Current(position) => {
179 *device_position = (*device_position as isize + *position as isize) as usize
180 }
181 Position::End(position) => {
182 *device_position = (data.len() as isize - *position as isize) as usize
183 }
184 }
185
186 Ok(Size::new(*device_position as u64))
187 }
188
189 fn erase(&self) -> crate::Result<()> {
190 let mut inner = block_on(self.0.write());
191
192 let (data, position) = &mut *inner;
193
194 data[*position..*position + BLOCK_SIZE].fill(0);
195
196 Ok(())
197 }
198
199 fn flush(&self) -> crate::Result<()> {
200 Ok(())
201 }
202
203 fn get_block_size(&self) -> crate::Result<usize> {
204 Ok(BLOCK_SIZE)
205 }
206
207 fn dump_device(&self) -> crate::Result<Vec<u8>> {
208 let inner = block_on(self.0.read());
209
210 Ok(inner.0.clone())
211 }
212
213 fn is_a_terminal(&self) -> bool {
214 false
215 }
216
217 fn is_a_block_device(&self) -> bool {
218 false
219 }
220}