1#![no_implicit_prelude]
21
22extern crate core;
23
24use core::default::Default;
25use core::ops::{Deref, DerefMut};
26use core::option::Option::{self, None, Some};
27use core::result::Result::{self, Ok};
28use core::{cmp, unreachable};
29
30use crate::fs::{BlockDevice, DeviceError, Storage};
31
32pub struct BlockBuffer {
33 buf: [Block; 4],
34 status: u8,
35}
36pub struct BlockEntryIter {
37 buf: BlockBuffer,
38 prev: Option<u32>,
39 last: u32,
40 count: u8,
41}
42pub struct BlockCache(Option<u32>);
43pub struct Block([u8; Block::SIZE]);
44
45impl Block {
46 pub const SIZE: usize = 0x200;
47
48 #[inline]
49 pub fn new() -> Block {
50 Block([0u8; 0x200])
51 }
52
53 #[inline(always)]
54 pub fn clear(&mut self) {
55 self.0.fill(0)
56 }
57}
58impl BlockCache {
59 #[inline(always)]
60 pub fn new() -> BlockCache {
61 BlockCache(None)
62 }
63
64 #[inline(always)]
65 pub fn clear(&mut self) {
66 self.0.take();
67 }
68 #[inline]
69 pub fn read_single(&mut self, dev: &Storage<impl BlockDevice>, b: &mut Block, pos: u32) -> Result<(), DeviceError> {
70 match self.0.replace(pos) {
71 Some(v) if v != pos => dev.read_single(b, pos),
72 None => dev.read_single(b, pos),
73 _ => Ok(()),
74 }
75 }
76}
77impl BlockBuffer {
78 pub const COUNT: u8 = 0x4u8;
79 pub const SLOT_A: u8 = 0x0u8;
80 pub const SLOT_B: u8 = 0x1u8;
81 pub const SLOT_C: u8 = 0x2u8;
82 pub const SLOT_D: u8 = 0x3u8;
83
84 #[inline]
85 pub fn new() -> BlockBuffer {
86 BlockBuffer {
87 buf: [Block::new(), Block::new(), Block::new(), Block::new()],
88 status: 0u8,
89 }
90 }
91
92 #[inline]
93 pub fn is_dirty(&self, slot: u8) -> bool {
94 match slot % BlockBuffer::COUNT {
95 BlockBuffer::SLOT_A if self.status & 0x80 != 0 => true,
96 BlockBuffer::SLOT_B if self.status & 0x40 != 0 => true,
97 BlockBuffer::SLOT_C if self.status & 0x20 != 0 => true,
98 BlockBuffer::SLOT_D if self.status & 0x10 != 0 => true,
99 _ => false,
100 }
101 }
102 #[inline]
103 pub fn is_loaded(&self, slot: u8) -> bool {
104 match slot % BlockBuffer::COUNT {
105 BlockBuffer::SLOT_A if self.status & 0x8 != 0 => true,
106 BlockBuffer::SLOT_B if self.status & 0x4 != 0 => true,
107 BlockBuffer::SLOT_C if self.status & 0x2 != 0 => true,
108 BlockBuffer::SLOT_D if self.status & 0x1 != 0 => true,
109 _ => false,
110 }
111 }
112 #[inline]
113 pub fn buffer(&mut self, slot: u8) -> &mut [u8] {
114 match slot % BlockBuffer::COUNT {
115 BlockBuffer::SLOT_A => {
116 self.status |= 0x80;
117 &mut self.buf[0]
118 },
119 BlockBuffer::SLOT_B => {
120 self.status |= 0x40;
121 &mut self.buf[1]
122 },
123 BlockBuffer::SLOT_C => {
124 self.status |= 0x20;
125 &mut self.buf[2]
126 },
127 BlockBuffer::SLOT_D => {
128 self.status |= 0x10;
129 &mut self.buf[3]
130 },
131 _ => unreachable!(),
132 }
133 }
134 pub fn flush(&mut self, dev: &Storage<impl BlockDevice>, start: u32) -> Result<(), DeviceError> {
135 let s = self.status;
136 self.status = s & 0xF;
137 match s {
138 v if (v >> 4) == 0xF => return dev.write(&self.buf, start),
141 v if (v >> 4) == 0xE => return dev.write(&self.buf[0..3], start),
143 v if (v >> 4) == 0xC => return dev.write(&self.buf[0..2], start),
145 v if (v >> 4) == 0x3 => return dev.write(&self.buf[2..], start + 2),
147 v if (v >> 4) == 0x7 => return dev.write(&self.buf[1..], start + 1),
149 v if (v >> 4) == 0x6 => return dev.write(&self.buf[1..3], start + 1),
151 v if (v >> 4) == 1 => return dev.write_single(&self.buf[3], start + 3),
154 v if (v >> 4) == 2 => return dev.write_single(&self.buf[2], start + 2),
156 v if (v >> 4) == 4 => return dev.write_single(&self.buf[1], start + 1),
158 v if (v >> 4) == 8 => return dev.write_single(&self.buf[0], start),
160 _ => (),
161 }
162 if s & 0x80 != 0 {
164 dev.write_single(&self.buf[0], start)?;
165 }
166 if s & 0x40 != 0 {
168 dev.write_single(&self.buf[1], start + 1)?;
169 }
170 if s & 0x20 != 0 {
172 dev.write_single(&self.buf[2], start + 2)?;
173 }
174 if s & 0x10 != 0 {
176 dev.write_single(&self.buf[3], start + 3)?;
177 }
178 Ok(())
179 }
180 #[inline]
181 pub fn read(&mut self, dev: &Storage<impl BlockDevice>, count: u8, start: u32) -> Result<(), DeviceError> {
182 let n = cmp::min(count, BlockBuffer::COUNT);
183 dev.read(&mut self.buf[0..n as usize], start)?;
184 self.status = match n {
185 4 => 0xF,
186 3 => 0xE,
187 2 => 0xC,
188 1 => 0x8,
189 _ => unreachable!(),
190 };
191 Ok(())
192 }
193}
194impl BlockEntryIter {
195 #[inline(always)]
196 pub fn new(count: u8) -> BlockEntryIter {
197 BlockEntryIter {
198 count,
199 buf: BlockBuffer::new(),
200 prev: None,
201 last: 0u32,
202 }
203 }
204
205 #[inline(always)]
206 pub fn pos(&self) -> u32 {
207 self.prev.unwrap_or(0)
208 }
209 #[inline(always)]
210 pub fn is_loaded(&self) -> bool {
211 self.prev.is_none()
212 }
213 #[inline(always)]
214 pub fn in_scope(&self, pos: u32) -> bool {
215 (pos - self.pos()) < BlockBuffer::COUNT as u32
216 }
217 #[inline(always)]
218 pub fn buffer(&mut self, pos: u32) -> &mut [u8] {
219 self.buf.buffer((pos - self.pos()) as u8)
220 }
221 #[inline]
222 pub fn flush(&mut self, dev: &Storage<impl BlockDevice>) -> Result<(), DeviceError> {
223 if let Some(v) = self.prev.take() {
224 self.buf.flush(dev, v)?;
225 }
226 Ok(())
227 }
228 pub fn load(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
229 if self.last != 0 && pos < self.last {
230 return Ok(());
231 }
232 let i = cmp::min(self.count, BlockBuffer::COUNT);
233 self.buf.read(dev, i, pos)?;
234 self.last = self.last.saturating_add(i as u32);
235 self.count = self.count.saturating_sub(i);
236 self.prev = Some(pos);
237 Ok(())
238 }
239 #[inline]
240 pub fn load_and_flush(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
241 self.flush(dev)?;
242 self.load(dev, pos)
243 }
244}
245
246impl Deref for Block {
247 type Target = [u8];
248
249 #[inline(always)]
250 fn deref(&self) -> &[u8] {
251 &self.0
252 }
253}
254impl Default for Block {
255 #[inline]
256 fn default() -> Block {
257 Block([0u8; 0x200])
258 }
259}
260impl DerefMut for Block {
261 #[inline(always)]
262 fn deref_mut(&mut self) -> &mut [u8] {
263 &mut self.0
264 }
265}
266
267impl Default for BlockCache {
268 #[inline(always)]
269 fn default() -> BlockCache {
270 BlockCache(None)
271 }
272}
273
274impl Default for BlockBuffer {
275 #[inline]
276 fn default() -> BlockBuffer {
277 BlockBuffer::new()
278 }
279}