Don't use dynamic allocation for FAT table wrapper.

FAT table still uses Box but its hardly avoidable when reading entire FAT into memory.
This commit is contained in:
Rafał Harabień 2017-09-28 00:11:24 +02:00
parent 5f6f5921c1
commit c8ccd7d86e
3 changed files with 78 additions and 57 deletions

View File

@ -4,6 +4,7 @@ use std::io::{SeekFrom, ErrorKind};
use std::io; use std::io;
use fs::FatSharedStateRef; use fs::FatSharedStateRef;
use table::FatNextCluster;
pub struct FatFile<'a, 'b: 'a> { pub struct FatFile<'a, 'b: 'a> {

View File

@ -8,7 +8,7 @@ use byteorder::{LittleEndian, ReadBytesExt};
use file::FatFile; use file::FatFile;
use dir::{FatDirReader, FatDir}; use dir::{FatDirReader, FatDir};
use table::{FatTable, FatTable12, FatTable16, FatTable32}; use table::FatTable;
// FAT implementation based on: // FAT implementation based on:
// http://wiki.osdev.org/FAT // http://wiki.osdev.org/FAT
@ -28,7 +28,7 @@ pub(crate) struct FatSharedState<'a> {
pub(crate) boot: FatBootRecord, pub(crate) boot: FatBootRecord,
pub(crate) first_data_sector: u32, pub(crate) first_data_sector: u32,
pub(crate) root_dir_sectors: u32, pub(crate) root_dir_sectors: u32,
pub(crate) table: Box<FatTable>, pub(crate) table: FatTable,
} }
impl <'a> FatSharedState<'a> { impl <'a> FatSharedState<'a> {
@ -128,12 +128,7 @@ impl <'a> FatFileSystem<'a> {
let fat_offset = boot.bpb.reserved_sector_count * boot.bpb.bytes_per_sector; let fat_offset = boot.bpb.reserved_sector_count * boot.bpb.bytes_per_sector;
rdr.seek(SeekFrom::Start(fat_offset as u64))?; rdr.seek(SeekFrom::Start(fat_offset as u64))?;
let table_size_bytes = table_size * boot.bpb.bytes_per_sector as u32; let table_size_bytes = table_size * boot.bpb.bytes_per_sector as u32;
let table: Box<FatTable> = match fat_type { let table = FatTable::from_read(rdr, fat_type, table_size_bytes as usize)?;
FatType::Fat12 => Box::new(FatTable12::read(rdr, table_size_bytes as usize)?),
FatType::Fat16 => Box::new(FatTable16::read(rdr, table_size_bytes as usize)?),
FatType::Fat32 => Box::new(FatTable32::read(rdr, table_size_bytes as usize)?),
_ => panic!("TODO: exfat")
};
let state = FatSharedState { let state = FatSharedState {
rdr, rdr,

View File

@ -1,78 +1,81 @@
use std::io::prelude::*; use std::io::prelude::*;
use std::io; use std::io;
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use fs::FatType;
pub(crate) struct FatTableData<T> { pub(crate) struct FatTableData<T> {
table: Box<[T]>, table: Box<[T]>,
} }
pub(crate) type FatTable32 = FatTableData<u32>;
pub(crate) type FatTable16 = FatTableData<u16>;
pub(crate) type FatTable12 = FatTableData<u8>;
impl <T> FatTableData<T> { impl <T> FatTableData<T> {
pub fn new(data: Box<[T]>) -> FatTableData<T> { pub fn new(data: Box<[T]>) -> Self {
FatTableData::<T> { Self {
table: data, table: data,
} }
} }
} }
pub(crate) type FatTable12 = FatTableData<u8>;
pub(crate) type FatTable16 = FatTableData<u16>;
pub(crate) type FatTable32 = FatTableData<u32>;
pub(crate) enum FatTable {
Fat12(FatTable12),
Fat16(FatTable16),
Fat32(FatTable32),
}
impl FatTable {
pub fn from_read(rdr: &mut Read, fat_type: FatType, size: usize) -> io::Result<FatTable> {
let table = match fat_type {
FatType::Fat12 => FatTable::Fat12(FatTable12::from_read(rdr, size)?),
FatType::Fat16 => FatTable::Fat16(FatTable16::from_read(rdr, size)?),
FatType::Fat32 => FatTable::Fat32(FatTable32::from_read(rdr, size)?),
_ => panic!("TODO: exfat")
};
Ok(table)
}
}
pub(crate) trait FatNextCluster {
fn get_next_cluster(&self, cluster: u32) -> Option<u32>;
}
impl FatNextCluster for FatTable {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
match *self {
FatTable::Fat12(ref fat) => fat.get_next_cluster(cluster),
FatTable::Fat16(ref fat) => fat.get_next_cluster(cluster),
FatTable::Fat32(ref fat) => fat.get_next_cluster(cluster),
}
}
}
impl FatTable12 { impl FatTable12 {
pub fn read(rdr: &mut Read, size: usize) -> io::Result<Self> { pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
let mut fat = vec![0;size as usize]; let mut fat = vec![0;size];
rdr.read_exact(fat.as_mut())?; rdr.read_exact(fat.as_mut())?;
Ok(FatTable12::new(fat.into_boxed_slice())) Ok(Self::new(fat.into_boxed_slice()))
} }
} }
impl FatTable16 { impl FatTable16 {
pub fn read(rdr: &mut Read, size: usize) -> io::Result<Self> { pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
let mut fat = Vec::with_capacity(size/2); let mut fat = vec![0;size/2];
for _ in 0..size/2 { rdr.read_u16_into::<LittleEndian>(fat.as_mut())?;
fat.push(rdr.read_u16::<LittleEndian>()?); Ok(Self::new(fat.into_boxed_slice()))
}
Ok(FatTable16::new(fat.into_boxed_slice()))
} }
} }
impl FatTable32 { impl FatTable32 {
pub fn read(rdr: &mut Read, size: usize) -> io::Result<Self> { pub fn from_read(rdr: &mut Read, size: usize) -> io::Result<Self> {
let mut fat = Vec::with_capacity(size/4); let mut fat = vec![0;size/4];
for _ in 0..size/4 { rdr.read_u32_into::<LittleEndian>(fat.as_mut())?;
fat.push(rdr.read_u32::<LittleEndian>()?); Ok(Self::new(fat.into_boxed_slice()))
}
Ok(FatTable32::new(fat.into_boxed_slice()))
} }
} }
pub trait FatTable { impl FatNextCluster for FatTable12 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32>;
}
impl FatTable for FatTable32 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
let val = self.table[cluster as usize] & 0x0FFFFFFF;
if val <= 1 || val >= 0x0FFFFFF7 {
None
} else {
Some(val)
}
}
}
impl FatTable for FatTable16 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
let val = self.table[cluster as usize];
if val <= 1 || val >= 0xFFF7 {
None
} else {
Some(val as u32)
}
}
}
impl FatTable for FatTable12 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> { fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
let fat_offset = cluster + (cluster / 2); let fat_offset = cluster + (cluster / 2);
let val1 = self.table[fat_offset as usize] as u16; let val1 = self.table[fat_offset as usize] as u16;
@ -90,3 +93,25 @@ impl FatTable for FatTable12 {
} }
} }
} }
impl FatNextCluster for FatTable16 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
let val = self.table[cluster as usize];
if val <= 1 || val >= 0xFFF7 {
None
} else {
Some(val as u32)
}
}
}
impl FatNextCluster for FatTable32 {
fn get_next_cluster(&self, cluster: u32) -> Option<u32> {
let val = self.table[cluster as usize] & 0x0FFFFFFF;
if val <= 1 || val >= 0x0FFFFFF7 {
None
} else {
Some(val)
}
}
}