file_system/
device.rs

1//! Device abstraction for storage and I/O operations.
2//!
3//! This module provides the core device trait and types for abstracting various
4//! storage devices, peripherals, and I/O endpoints in the file system.
5
6use core::fmt;
7use core::fmt::{Debug, Formatter};
8
9use alloc::sync::Arc;
10use alloc::vec;
11use alloc::vec::Vec;
12
13use crate::{Error, Position, Result, Size};
14
15/// Convenience macro for creating a new [`Device`] from any type implementing [`DeviceTrait`].
16///
17/// This macro wraps the provided device implementation in an `Arc` and creates a `DeviceType`.
18///
19/// # Examples
20///
21/// ```rust
22/// # extern crate alloc;
23/// # use file_system::*;
24///
25/// let memory_device = Memory_device_type::<512>::new(1024);
26/// let device = create_device!(memory_device);
27/// ```
28#[macro_export]
29macro_rules! create_device {
30    ($Device:expr) => {
31        $crate::Device::new(alloc::sync::Arc::new($Device))
32    };
33}
34
35/// Core trait for all device implementations in the file system.
36///
37/// A device represents any storage medium or I/O endpoint that can be read from and written to.
38/// This includes physical storage devices (hard drives, SSDs, SD cards), memory devices for testing,
39/// partition devices, and other specialized I/O devices.
40///
41/// ## Thread Safety
42///
43/// All device implementations must be thread-safe (`Send + Sync`) as they may be accessed
44/// by multiple tasks/threads concurrently. Implementations should use appropriate synchronization
45/// primitives like `RwLock` or `Mutex` to handle concurrent access.
46///
47/// ## Non-Blocking Operations
48///
49/// Devices should never block indefinitely. If an operation would block, implementations should
50/// return [`Error::RessourceBusy`] instead. This means implementations should prefer
51/// `try_read()` and `try_write()` variants of synchronization primitives.
52///
53/// ## Position Management
54///
55/// Devices maintain an internal position cursor that affects read and write operations.
56/// The position can be manipulated using [`DeviceTrait::set_position`].
57///
58/// # Examples
59///
60/// ```rust
61/// # extern crate alloc;
62/// # use file_system::*;
63///
64/// // Create a memory device for testing
65/// let device = create_device!(Memory_device_type::<512>::new(1024));
66///
67/// // Write data
68/// let data = b"Hello, World!";
69/// let bytes_written = device.Write(data).unwrap();
70/// assert_eq!(bytes_written.As_u64(), data.len() as u64);
71///
72/// // Reset position and read back
73/// device.Set_position(&Position_type::Start(0)).unwrap();
74/// let mut buffer = alloc::vec![0u8; data.len()];
75/// let bytes_read = device.Read(&mut buffer).unwrap();
76/// assert_eq!(bytes_read.As_u64(), data.len() as u64);
77/// assert_eq!(&buffer, data);
78/// ```
79pub trait DeviceTrait: Send + Sync {
80    /// Read data from the device at the current position.
81    ///
82    /// Reads up to `Buffer.len()` bytes from the device into the provided buffer.
83    /// The actual number of bytes read may be less than requested.
84    ///
85    /// # Arguments
86    ///
87    /// * `Buffer` - Mutable byte slice to read data into
88    ///
89    /// # Returns
90    ///
91    /// * `Ok(Size)` - Number of bytes successfully read
92    /// * `Err(Error)` - Error if read operation failed
93    ///
94    /// # Errors
95    ///
96    /// * [`Error::InputOutput`] - I/O error during read operation
97    /// * [`Error::RessourceBusy`] - Device is temporarily unavailable
98    /// * [`Error::InvalidParameter`] - Invalid buffer or device state
99    fn read(&self, buffer: &mut [u8]) -> Result<Size>;
100
101    /// Write data to the device at the current position.
102    ///
103    /// Writes up to `Buffer.len()` bytes from the buffer to the device.
104    /// The actual number of bytes written may be less than requested.
105    ///
106    /// # Arguments
107    ///
108    /// * `Buffer` - Byte slice containing data to write
109    ///
110    /// # Returns
111    ///
112    /// * `Ok(Size)` - Number of bytes successfully written
113    /// * `Err(Error)` - Error if write operation failed
114    ///
115    /// # Errors
116    ///
117    /// * [`Error::InputOutput`] - I/O error during write operation
118    /// * [`Error::NoSpaceLeft`] - Device is full
119    /// * [`Error::RessourceBusy`] - Device is temporarily unavailable
120    /// * [`Error::PermissionDenied`] - Device is read-only
121    fn write(&self, buffer: &[u8]) -> Result<Size>;
122
123    /// Get the total size of the device in bytes.
124    ///
125    /// Returns the maximum amount of data that can be stored on or read from the device.
126    ///
127    /// # Returns
128    ///
129    /// * `Ok(Size)` - Total device size in bytes
130    /// * `Err(Error)` - Error if size cannot be determined
131    fn get_size(&self) -> Result<Size>;
132
133    /// Set the current position cursor for read/write operations.
134    ///
135    /// The position affects where subsequent read and write operations will occur.
136    /// Different position types allow for absolute positioning, relative positioning,
137    /// and positioning from the end of the device.
138    ///
139    /// # Arguments
140    ///
141    /// * `Position` - The new position to set
142    ///
143    /// # Returns
144    ///
145    /// * `Ok(Size)` - The new absolute position after the operation
146    /// * `Err(Error)` - Error if position is invalid
147    ///
148    /// # Errors
149    ///
150    /// * [`Error::InvalidParameter`] - Position is beyond device bounds
151    fn set_position(&self, position: &Position) -> Result<Size>;
152
153    /// Flush any buffered data to the underlying storage.
154    ///
155    /// Ensures that all pending write operations are committed to the physical device.
156    /// This is important for data integrity, especially on buffered devices.
157    ///
158    /// # Returns
159    ///
160    /// * `Ok(())` - Flush completed successfully
161    /// * `Err(Error)` - Error during flush operation
162    fn flush(&self) -> Result<()>;
163
164    /// Erase the entire device.
165    ///
166    /// This operation is primarily intended for flash memory devices and similar
167    /// storage that requires explicit erase operations. For most devices, this
168    /// operation is not supported and will return [`Error::UnsupportedOperation`].
169    ///
170    /// # Returns
171    ///
172    /// * `Ok(())` - Erase completed successfully
173    /// * `Err(Error::UnsupportedOperation)` - Device doesn't support erase
174    /// * `Err(Error)` - Error during erase operation
175    fn erase(&self) -> Result<()> {
176        Err(Error::UnsupportedOperation)
177    }
178
179    /// Get the block size of the device in bytes.
180    ///
181    /// For block devices, this returns the minimum unit of data transfer.
182    /// Operations should ideally be aligned to block boundaries for optimal performance.
183    ///
184    /// # Returns
185    ///
186    /// * `Ok(usize)` - Block size in bytes
187    /// * `Err(Error::UnsupportedOperation)` - Device doesn't have a block size
188    fn get_block_size(&self) -> Result<usize> {
189        Err(Error::UnsupportedOperation)
190    }
191
192    /// Check if this device represents a terminal/console device.
193    ///
194    /// # Returns
195    ///
196    /// * `true` - Device is a terminal
197    /// * `false` - Device is not a terminal
198    fn is_a_terminal(&self) -> bool {
199        false
200    }
201
202    /// Check if this device is a block device.
203    ///
204    /// Block devices support fixed-size block operations and typically represent
205    /// physical storage media like hard drives or SSDs.
206    ///
207    /// # Returns
208    ///
209    /// * `true` - Device is a block device
210    /// * `false` - Device is not a block device
211    fn is_a_block_device(&self) -> bool {
212        false
213    }
214
215    /// Create a complete dump of the device contents.
216    ///
217    /// Reads the entire device contents into a vector. This is primarily useful
218    /// for debugging, testing, and creating backups of small devices.
219    ///
220    /// # Returns
221    ///
222    /// * `Ok(Vec<u8>)` - Complete device contents
223    /// * `Err(Error)` - Error reading device
224    ///
225    /// # Note
226    ///
227    /// This operation can consume significant memory for large devices.
228    /// Use with caution on production systems.
229    fn dump_device(&self) -> Result<Vec<u8>> {
230        let size = self.get_size()?;
231
232        let mut buffer = vec![0; size.into()];
233
234        self.read(&mut buffer)?;
235
236        Ok(buffer)
237    }
238}
239
240/// Thread-safe wrapper for device implementations.
241///
242/// `DeviceType` provides a unified interface for all device implementations by wrapping
243/// them in an `Arc<dyn DeviceTrait>`. This allows for efficient cloning and sharing of
244/// device references across threads while maintaining type erasure.
245///
246/// # Examples
247///
248/// ```rust
249/// # extern crate alloc;
250/// # use file_system::*;
251/// # use alloc::sync::Arc;
252///
253/// // Create a device using the convenience macro
254/// let device1 = create_device!(Memory_device_type::<512>::new(1024));
255///
256/// // Create a device manually
257/// let memory_device = Memory_device_type::<512>::new(1024);
258/// let device2 = DeviceType::new(Arc::new(memory_device));
259///
260/// // Clone the device (cheap operation - only clones the Arc)
261/// let device_clone = device1.clone();
262/// ```
263#[derive(Clone)]
264#[repr(transparent)]
265pub struct Device(Arc<dyn DeviceTrait>);
266
267impl Debug for Device {
268    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
269        write!(formatter, "Device")
270    }
271}
272
273impl Device {
274    /// Create a new device wrapper from any implementation of [`DeviceTrait`].
275    ///
276    /// # Arguments
277    ///
278    /// * `Device` - Arc containing the device implementation
279    ///
280    /// # Examples
281    ///
282    /// ```rust
283    /// # extern crate alloc;
284    /// # use file_system::*;
285    /// # use alloc::sync::Arc;
286    ///
287    /// let memory_device = Memory_device_type::<512>::new(1024);
288    /// let device = DeviceType::new(Arc::new(memory_device));
289    /// ```
290    pub fn new(device: Arc<dyn DeviceTrait>) -> Self {
291        Device(device)
292    }
293
294    /// Read data from the device at the current position.
295    ///
296    /// See [`DeviceTrait::read`] for detailed documentation.
297    pub fn read(&self, buffer: &mut [u8]) -> Result<Size> {
298        self.0.read(buffer)
299    }
300
301    /// Write data to the device at the current position.
302    ///
303    /// See [`DeviceTrait::write`] for detailed documentation.
304    pub fn write(&self, buffer: &[u8]) -> Result<Size> {
305        self.0.write(buffer)
306    }
307
308    /// Get the total size of the device in bytes.
309    ///
310    /// See [`DeviceTrait::get_size`] for detailed documentation.
311    pub fn get_size(&self) -> Result<Size> {
312        self.0.get_size()
313    }
314
315    /// Set the current position cursor for read/write operations.
316    ///
317    /// See [`DeviceTrait::set_position`] for detailed documentation.
318    pub fn set_position(&self, position: &Position) -> Result<Size> {
319        self.0.set_position(position)
320    }
321
322    /// Flush any buffered data to the underlying storage.
323    ///
324    /// See [`DeviceTrait::flush`] for detailed documentation.
325    pub fn flush(&self) -> Result<()> {
326        self.0.flush()
327    }
328
329    /// Erase the entire device.
330    ///
331    /// See [`DeviceTrait::erase`] for detailed documentation.
332    pub fn erase(&self) -> Result<()> {
333        self.0.erase()
334    }
335
336    /// Get the block size of the device in bytes.
337    ///
338    /// See [`DeviceTrait::get_block_size`] for detailed documentation.
339    pub fn get_block_size(&self) -> Result<usize> {
340        self.0.get_block_size()
341    }
342
343    /// Check if this device represents a terminal/console device.
344    ///
345    /// See [`DeviceTrait::is_a_terminal`] for detailed documentation.
346    pub fn is_a_terminal(&self) -> bool {
347        self.0.is_a_terminal()
348    }
349
350    /// Check if this device is a block device.
351    ///
352    /// See [`DeviceTrait::is_a_block_device`] for detailed documentation.
353    pub fn is_a_block_device(&self) -> bool {
354        self.0.is_a_block_device()
355    }
356
357    /// Create a complete dump of the device contents.
358    ///
359    /// See [`DeviceTrait::dump_device`] for detailed documentation.
360    pub fn dump_device(&self) -> Result<Vec<u8>> {
361        self.0.dump_device()
362    }
363}