bonsai_disk/lib.rs
1#![deny(unconditional_recursion)]
2#![no_std]
3
4
5
6use generic_array::ArrayLength;
7
8
9
10/// Represents a disk that can be read from and written to.
11///
12/// The disk is divided into blocks of a fixed size.
13///
14/// Reads and writes are in bytes but must be aligned to the disk's write granularity.
15///
16/// Erases are in full block units.
17///
18/// The first byte of the disk is at offset `0`, which is also the start of the
19/// first block with index `0`.
20///
21pub trait Disk: embedded_io::ErrorType {
22 /// The size of an erasable block in bytes.
23 const ERASE_BLOCK_SIZE: usize;
24
25 /// The minimum size of a write operation in bytes.
26 ///
27 /// Also defines the write alignment.
28 ///
29 /// Currently, also used for read granularity.
30 #[allow(non_camel_case_types)]
31 type WRITE_GRANULARITY: ArrayLength;
32
33 /// Reads data from the disk into the buffer.
34 ///
35 /// The given offset is in bytes and must be aligned to `WRITE_GRANULARITY`.
36 /// The buffer must be at least `WRITE_GRANULARITY` bytes long.
37 fn read(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize, Self::Error>;
38
39 /// Writes data from the buffer to the disk.
40 ///
41 /// The given offset is in bytes and must be aligned to `WRITE_GRANULARITY`.
42 /// The buffer must be at least `WRITE_GRANULARITY` bytes long.
43 ///
44 /// A write should only happen on a section of a block that has been
45 /// previously erased and not yet written to.
46 /// It is permissible to write independent sections of a block in any order.
47 fn write(&mut self, offset: usize, buf: &[u8]) -> Result<usize, Self::Error>;
48
49 /// Erases the block at the given block index.
50 ///
51 /// The block index is in units of `ERASE_BLOCK_SIZE`.
52 ///
53 /// The first block has index `0` and the last block has index
54 /// `self.block_count() - 1`.
55 fn erase(&mut self, block: usize) -> Result<(), Self::Error>;
56
57 /// Returns the number of blocks on the disk.
58 ///
59 /// The number of blocks is fixed and does not change.
60 fn block_count(&self) -> usize;
61
62 /// Reads the exact number of bytes required to fill the buffer.
63 ///
64 /// The given offset is in bytes and must be aligned to `WRITE_GRANULARITY`.
65 /// The buffer size must be a multiple of `WRITE_GRANULARITY`.
66 ///
67 /// If the buffer cannot be completely filled, an error is returned.
68 #[track_caller]
69 fn read_exact(
70 &mut self,
71 mut offset: usize,
72 mut buf: &mut [u8],
73 ) -> Result<(), embedded_io::ReadExactError<Self::Error>> {
74 while !buf.is_empty() {
75 let bytes_read = self.read(offset, buf)?;
76 if bytes_read == 0 {
77 return Err(embedded_io::ReadExactError::UnexpectedEof);
78 }
79 offset += bytes_read;
80 buf = &mut buf[bytes_read..];
81 }
82 Ok(())
83 }
84
85 /// Writes the exact number of bytes from the buffer to the disk.
86 ///
87 /// The given offset is in bytes and must be aligned to `WRITE_GRANULARITY`.
88 /// The buffer size must be a multiple of `WRITE_GRANULARITY`.
89 ///
90 /// If the buffer cannot be completely written, an error is returned.
91 #[track_caller]
92 fn write_all(&mut self, mut offset: usize, mut buf: &[u8]) -> Result<(), Self::Error> {
93 while !buf.is_empty() {
94 let bytes_written = self.write(offset, buf)?;
95 if bytes_written == 0 {
96 panic!("write() returned Ok(0)");
97 }
98 offset += bytes_written;
99 buf = &buf[bytes_written..];
100 }
101 Ok(())
102 }
103}
104
105impl<T: Disk> Disk for &mut T {
106 type WRITE_GRANULARITY = T::WRITE_GRANULARITY;
107
108 const ERASE_BLOCK_SIZE: usize = T::ERASE_BLOCK_SIZE;
109
110 #[track_caller]
111 fn read(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize, Self::Error> {
112 (**self).read(offset, buf)
113 }
114
115 #[track_caller]
116 fn write(&mut self, offset: usize, buf: &[u8]) -> Result<usize, Self::Error> {
117 (**self).write(offset, buf)
118 }
119
120 #[track_caller]
121 fn erase(&mut self, block: usize) -> Result<(), Self::Error> {
122 (**self).erase(block)
123 }
124
125 #[track_caller]
126 fn block_count(&self) -> usize {
127 (**self).block_count()
128 }
129}