use zerocopy::byteorder::little_endian::{U16, U32};
use zerocopy::*;
use crate::error::Error;
#[derive(Debug)]
pub enum FatType {
Type16,
Type32,
}
#[derive(Debug)]
pub enum FatEntry {
Available,
Reserved,
Bad,
Media,
End,
Data(u32),
Invalid,
}
pub type FatEntryId = u32;
pub type ClusterId = u32;
impl From<u16> for FatEntry {
fn from(value: u16) -> Self {
match value {
0x0000 => FatEntry::Available,
0x0001..0xfff0 => FatEntry::Data(value as u32),
0xfff0 => FatEntry::Reserved,
0xfff7 => FatEntry::Bad,
0xfff8 => FatEntry::Media,
0xffff => FatEntry::End,
_ => FatEntry::Invalid,
}
}
}
impl From<u32> for FatEntry {
fn from(value: u32) -> Self {
match value {
0x00000000 => FatEntry::Available,
0x00000001..0xfffffff0 => FatEntry::Data(value),
0xfffffff0 => FatEntry::Reserved,
0xfffffff7 => FatEntry::Bad,
0xfffffff8 => FatEntry::Media,
0xffffffff => FatEntry::End,
_ => FatEntry::Invalid,
}
}
}
#[derive(Debug)]
pub struct Fat {
pub fat_type: FatType,
pub fat_size_bytes: u64,
pub fat_data: Vec<u8>, }
impl Fat {
pub fn new(num_fat_entries: u32) -> Self {
let (fat_type, fat_size_bytes) = if num_fat_entries < 0xfff0 {
(
FatType::Type16,
(num_fat_entries as u64 * 2).next_multiple_of(4096),
)
} else {
(
FatType::Type32,
(num_fat_entries as u64 * 4).next_multiple_of(4096),
)
};
let fat_data = vec![0u8; fat_size_bytes as usize];
Self {
fat_type,
fat_size_bytes,
fat_data,
}
}
pub fn entry(&mut self, index: FatEntryId) -> Result<FatEntry, Error> {
match self.fat_type {
FatType::Type16 => {
let fat = <[U16]>::ref_from_bytes_with_elems(
&self.fat_data[..],
(self.fat_size_bytes / 2) as usize,
)
.unwrap();
let value: u16 = fat[index as usize].into();
Ok(value.into())
}
FatType::Type32 => {
let fat = <[U32]>::ref_from_bytes_with_elems(
&self.fat_data[..],
(self.fat_size_bytes / 4) as usize,
)
.unwrap();
let value: u32 = fat[index as usize].into();
Ok(value.into())
}
}
}
}