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}