filesystem/
lib.rs

1//! This crate provides common interfaces for the several file system
2//! implementations. The interfaces can be used to interact with the
3//! no_std implementations in an std environment.
4
5#![no_std]
6
7extern crate alloc;
8
9use alloc::vec;
10
11pub trait BlockDevice {
12    /// Determines the block size of this device.
13    /// The returned value must never change.
14    fn block_size(&self) -> usize;
15
16    /// Determines the amount of blocks that
17    /// this device has available.
18    fn block_count(&self) -> usize;
19
20    /// Reads the block with the given block_index into the given buffer.
21    /// The buffer must be at least as big as the value returned by
22    /// [`BlockDevice::block_size`], otherwise an implementation may
23    /// panic.
24    fn read_block(&self, block_index: usize, buf: &mut [u8]);
25
26    /// Writes the given buffer into the block with the given block
27    /// index. The buffer must be exactly as big as the value returned
28    /// by [`BlockDevice::block_size`], otherwise an implementation may
29    /// panic.
30    fn write_block(&mut self, block_index: usize, buf: &[u8]);
31
32    /// Reads `buf.len()` bytes starting at at the given **byte** offset
33    /// into the given buffer. Returns an error if the read would exceed
34    /// the length of this block device.
35    fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<(), ()> {
36        let block_size = self.block_size();
37
38        if offset % buf.len() == 0 && buf.len() == block_size {
39            // if we read exactly one block, and that read is aligned, delegate to the device impl
40            self.read_block(offset / block_size, buf);
41        }
42
43        let start_block = offset / block_size;
44        let end_block = (offset + buf.len()) / block_size;
45        let relative_offset = offset % block_size;
46        let block_count = if relative_offset == 0 && start_block != end_block {
47            end_block - start_block
48        } else {
49            end_block - start_block + 1
50        };
51
52        // read blocks
53        let mut data = vec![0_u8; block_count * block_size];
54        for i in 0..block_count {
55            let start_index = i * block_size;
56            let end_index = start_index + block_size;
57            let read_block_index = start_block + i;
58
59            self.read_block(read_block_index, &mut data[start_index..end_index]);
60        }
61        buf.copy_from_slice(&data[relative_offset..relative_offset + buf.len()]);
62
63        Ok(())
64    }
65}