rust-fatfs/src/table.rs

98 lines
2.8 KiB
Rust
Raw Normal View History

2017-09-23 20:16:02 +08:00
use std::io;
use byteorder::{LittleEndian, ReadBytesExt};
use fs::{FatType, DiskSlice, ReadSeek};
2017-10-02 03:31:44 +08:00
use core::iter;
2017-09-23 20:16:02 +08:00
fn get_next_cluster(rdr: &mut ReadSeek, fat_type: FatType, cluster: u32) -> io::Result<Option<u32>> {
match fat_type {
FatType::Fat12 => get_next_cluster_12(rdr, cluster),
FatType::Fat16 => get_next_cluster_16(rdr, cluster),
FatType::Fat32 => get_next_cluster_32(rdr, cluster),
2017-09-23 20:16:02 +08:00
}
}
fn get_next_cluster_12(rdr: &mut ReadSeek, cluster: u32) -> io::Result<Option<u32>> {
let fat_offset = cluster + (cluster / 2);
let mut bytes = [0;2];
rdr.seek(io::SeekFrom::Start(fat_offset as u64))?;
rdr.read(&mut bytes)?;
let (val1, val2) = (bytes[0] as u16, bytes[1] as u16);
2017-10-02 03:31:44 +08:00
let val = if cluster & 1 == 1 {
(val1 >> 4) | (val2 << 4)
} else {
val1 | (val2 & 0x0F)
};
if val <= 1 || val >= 0xFF7 {
Ok(None)
} else {
Ok(Some(val as u32))
}
}
fn get_next_cluster_16(rdr: &mut ReadSeek, cluster: u32) -> io::Result<Option<u32>> {
rdr.seek(io::SeekFrom::Start((cluster*2) as u64))?;
let val = rdr.read_u16::<LittleEndian>()?;
if val <= 1 || val >= 0xFFF7 {
Ok(None)
} else {
Ok(Some(val as u32))
2017-09-23 20:16:02 +08:00
}
}
fn get_next_cluster_32(rdr: &mut ReadSeek, cluster: u32) -> io::Result<Option<u32>> {
rdr.seek(io::SeekFrom::Start((cluster*4) as u64))?;
let val = rdr.read_u32::<LittleEndian>()? & 0x0FFFFFFF;
if val <= 1 || val >= 0x0FFFFFF7 {
Ok(None)
} else {
Ok(Some(val))
2017-09-23 20:16:02 +08:00
}
}
pub(crate) struct ClusterIterator<'a, 'b: 'a> {
rdr: DiskSlice<'a, 'b>,
fat_type: FatType,
cluster: Option<u32>,
err: bool,
2017-09-23 20:16:02 +08:00
}
impl <'a, 'b> ClusterIterator<'a, 'b> {
pub(crate) fn new(rdr: DiskSlice<'a, 'b>, fat_type: FatType, cluster: u32)
-> iter::Chain<iter::Once<io::Result<u32>>, ClusterIterator<'a, 'b>> {
let iter = ClusterIterator {
rdr: rdr,
fat_type: fat_type,
cluster: Some(cluster),
err: false,
};
iter::once(Ok(cluster)).chain(iter)
2017-09-23 20:16:02 +08:00
}
}
2017-10-02 03:31:44 +08:00
impl <'a, 'b> Iterator for ClusterIterator<'a, 'b> {
type Item = io::Result<u32>;
2017-10-02 03:31:44 +08:00
fn next(&mut self) -> Option<Self::Item> {
if self.err {
return None;
}
match self.cluster {
Some(current_cluster) => {
self.cluster = match get_next_cluster(&mut self.rdr, self.fat_type, current_cluster) {
Ok(next_cluster) => next_cluster,
Err(err) => {
self.err = true;
return Some(Err(err));
},
}
},
None => {},
};
match self.cluster {
Some(n) => Some(Ok(n)),
None => None,
}
2017-10-02 03:31:44 +08:00
}
}