#![no_implicit_prelude]
extern crate core;
use core::clone::Clone;
use core::iter::{IntoIterator, Iterator};
use core::marker::Copy;
use core::ops::FnMut;
use core::option::Option::{self, None, Some};
use core::result::Result::{Err, Ok};
use crate::Slice;
use crate::fs::{Block, BlockCache, BlockDevice, BlockPtr, Cache, Cluster, ClusterIndex, DevResult, DirEntry, DirEntryFull, DirEntryPtr, Directory, Volume};
pub struct Range {
sel: [RangeIndex; 10], sum: u8, index: u8, }
pub struct RangeIter {
cur: RangeIndex,
pos: u8,
range: Range,
}
pub struct RangeIndex(u32, u32, u32); pub struct DirectoryIndex<'a, B: BlockDevice> {
buf: BlockPtr,
val: DirEntryFull,
vol: &'a Volume<'a, B>,
block: u32,
cache: BlockCache,
entry: u32,
blocks: u32,
cluster: ClusterIndex,
}
pub struct DirectoryIter<'a, B: BlockDevice>(DirectoryIndex<'a, B>);
pub struct DirectoryIterMut<'b, 'a: 'b, B: BlockDevice>(&'b mut DirectoryIndex<'a, B>);
pub type RangeEntry = (u32, u32, bool, usize);
impl Range {
#[inline]
pub fn blocks(&self) -> u8 {
self.index
}
#[inline]
pub(super) fn new() -> Range {
Range {
sel: [const { RangeIndex::new() }; 10],
sum: 0u8,
index: 0u8,
}
}
#[inline]
pub(super) fn clear(&mut self) {
(self.sum, self.index) = (0u8, 0u8)
}
#[inline]
pub(super) fn finish(&mut self, c: u32, b: u32, e: u32) {
unsafe { self.sel.get_unchecked_mut(self.index as usize) }.set(c, b, e);
}
pub(super) fn mark(&mut self, c: u32, b: u32, e: u32) -> u8 {
if self.index == 0 {
unsafe { self.sel.get_unchecked_mut(0) }.set(c, b, e);
(self.index, self.sum) = (1, 1);
} else {
let v = &self.sel[self.index as usize - 1];
if v.0 != c || v.1 != b {
if self.index >= 9 {
self.clear(); }
unsafe { self.sel.get_unchecked_mut(self.index as usize) }.set(c, b, e);
self.index += 1;
}
self.sum += 1;
}
self.sum
}
}
impl RangeIter {
#[inline]
fn is_next(&self) -> bool {
if self.cur.2 >= DirEntry::SIZE_PER_BLOCK {
return true;
}
if self.pos + 1 < self.range.index {
return false;
}
let v = unsafe { self.range.sel.get_unchecked(self.pos as usize + 1).2 };
v == 0 || self.cur.2 > v
}
}
impl RangeIndex {
#[inline]
const fn new() -> RangeIndex {
RangeIndex(0u32, 0u32, 0u32)
}
#[inline]
fn set(&mut self, c: u32, b: u32, e: u32) {
(self.0, self.1, self.2) = (c, b, e);
}
}
impl<'b, 'a: 'b, B: BlockDevice> DirectoryIndex<'a, B> {
#[inline]
pub fn into_iter_mut(&'b mut self) -> DirectoryIterMut<'b, 'a, B> {
DirectoryIterMut(self)
}
#[inline]
pub fn reset(&mut self, dir: &Directory<'a, B>) -> DevResult<()> {
unsafe { self.reset_cluster(dir.cluster()) }
}
#[inline]
pub fn iter(&mut self, mut func: impl FnMut(&DirEntryFull)) -> DevResult<()> {
loop {
match self.next(true)? {
Some(v) => func(v),
None => break,
}
}
Ok(())
}
#[inline]
pub fn find(&mut self, mut func: impl FnMut(&DirEntryFull) -> bool) -> DevResult<Option<DirEntry>> {
loop {
match self.next(true)? {
Some(v) if func(v) => return Ok(Some(v.entry())),
Some(_) => continue,
None => break,
}
}
Ok(None)
}
#[inline]
pub unsafe fn reset_cluster(&mut self, dir: Cluster) -> DevResult<()> {
self.entry = 0;
self.cache.clear();
self.cluster = self.vol.root(dir);
self.block = self.vol.block_pos_at(self.cluster);
self.blocks = self.block + self.vol.entries(dir);
self.cache.read_single(self.vol.dev, &mut self.buf, self.block)
}
#[inline]
pub(super) fn new(vol: &'a Volume<'a, B>) -> DirectoryIndex<'a, B> {
DirectoryIndex {
vol,
buf: Cache::block_b(),
val: DirEntryFull::new(),
cache: BlockCache::new(),
entry: 0u32,
block: 0u32,
blocks: 0u32,
cluster: ClusterIndex::EMPTY,
}
}
#[inline]
fn is_loop_done(&self) -> bool {
self.entry >= DirEntry::SIZE_PER_BLOCK
}
fn is_complete(&mut self) -> DevResult<bool> {
if !self.is_loop_done() {
return Ok(false);
}
(self.entry, self.block) = (0, self.block + 1);
if self.block < self.blocks {
self.cache.read_single(self.vol.dev, &mut self.buf, self.block)?;
return Ok(false);
}
self.cluster = match self.vol.next(&mut self.buf, &mut self.cache, self.cluster)? {
None => return Ok(true),
Some(v) => v,
};
let i = self.vol.block_pos_at(self.cluster);
(self.block, self.blocks) = (i, i + self.vol.block.blocks());
self.cache.read_single(self.vol.dev, &mut self.buf, self.block)?;
Ok(false)
}
fn next(&'b mut self, r: bool) -> DevResult<Option<&'b mut DirEntryFull>> {
if self.is_complete()? {
return Ok(None);
}
if r {
self.val.reset();
}
while !self.is_loop_done() {
let s = self.entry as usize * DirEntry::SIZE;
if s + DirEntry::SIZE > Block::SIZE || self.buf.read_u8(s) == 0 {
return Ok(None);
}
self.entry += 1;
let v = self.buf.read_u8(s + 11);
if v & 0xF == 0xF {
self.val.fill(unsafe { self.buf.get_unchecked(s..) });
continue;
}
if (v & 0x8 != 0 && self.buf.read_u8(s + 28) == 0) || self.buf.read_u8(s) == 0xE5 {
continue;
}
self.val.load(
self.vol.ver.is_fat32(),
unsafe { self.buf.get_unchecked(s..) },
self.block,
s as u32,
);
return Ok(Some(&mut self.val));
}
self.next(false)
}
}
impl Copy for RangeIndex {}
impl Clone for RangeIndex {
#[inline]
fn clone(&self) -> RangeIndex {
RangeIndex(self.0, self.1, self.2)
}
}
impl Clone for Range {
#[inline]
fn clone(&self) -> Range {
Range {
sel: self.sel.clone(),
sum: self.sum,
index: self.index,
}
}
}
impl IntoIterator for Range {
type Item = RangeEntry;
type IntoIter = RangeIter;
#[inline]
fn into_iter(self) -> RangeIter {
RangeIter {
pos: 0u8,
cur: unsafe { *self.sel.get_unchecked(0) },
range: self,
}
}
}
impl Iterator for RangeIter {
type Item = RangeEntry;
#[inline]
fn next(&mut self) -> Option<RangeEntry> {
let n = if self.is_next() {
self.pos += 1;
if self.pos >= self.range.index {
return None;
}
self.cur = unsafe { *self.range.sel.get_unchecked(self.pos as usize) };
true
} else {
false || unsafe { self.range.sel.get_unchecked(self.pos as usize).2 == self.cur.2 }
};
let e = self.cur.2 as usize;
self.cur.2 += 1;
Some((self.cur.0, self.cur.1, n, e))
}
}
impl<'a, B: BlockDevice> Iterator for DirectoryIter<'a, B> {
type Item = DevResult<DirEntry>;
#[inline]
fn next(&mut self) -> Option<DevResult<DirEntry>> {
match self.0.next(true) {
Ok(Some(v)) => Some(Ok(v.entry())),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
}
impl<'b, 'a: 'b, B: BlockDevice> Iterator for DirectoryIterMut<'b, 'a, B> {
type Item = DevResult<DirEntryPtr<'b>>;
#[inline]
fn next(&mut self) -> Option<DevResult<DirEntryPtr<'b>>> {
match self.0.next(true) {
Ok(Some(v)) => Some(Ok(v.ptr())),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
}
impl<'a, B: BlockDevice> IntoIterator for DirectoryIndex<'a, B> {
type Item = DevResult<DirEntry>;
type IntoIter = DirectoryIter<'a, B>;
#[inline]
fn into_iter(self) -> DirectoryIter<'a, B> {
DirectoryIter(self)
}
}
impl<'b, 'a: 'b, B: BlockDevice> IntoIterator for &'b mut DirectoryIndex<'a, B> {
type Item = DevResult<DirEntryPtr<'b>>;
type IntoIter = DirectoryIterMut<'b, 'a, B>;
#[inline]
fn into_iter(self) -> DirectoryIterMut<'b, 'a, B> {
DirectoryIterMut(self)
}
}