use a2kit_macro::{DiskStructError,DiskStruct};
use a2kit_macro_derive::DiskStruct;
use super::types::ENTRY_SIZE;
#[derive(DiskStruct)]
pub struct VolDirHeader {
pub begin_block: [u8;2],
pub end_block: [u8;2],
pub file_type: [u8;2], pub name_len: u8, pub name: [u8;7],
pub total_blocks: [u8;2],
pub num_files: [u8;2],
pub last_access_date: [u8;2],
pub last_set_date: [u8;2],
pub pad: [u8;4]
}
#[derive(DiskStruct,Copy,Clone)]
pub struct DirectoryEntry {
pub begin_block: [u8;2],
pub end_block: [u8;2],
pub file_type: [u8;2],
pub name_len: u8, pub name: [u8;15],
pub bytes_remaining: [u8;2],
pub mod_date: [u8;2]
}
pub struct Directory {
pub header: VolDirHeader,
pub entries: Vec<DirectoryEntry>
}
impl Directory {
pub fn total_blocks(&self) -> usize {
u16::from_le_bytes(self.header.total_blocks) as usize
}
}
impl DiskStruct for Directory {
fn new() -> Self {
Self {
header: VolDirHeader::new(),
entries: Vec::new()
}
}
fn to_bytes(&self) -> Vec<u8> {
let mut ans: Vec<u8> = Vec::new();
ans.append(&mut self.header.to_bytes());
for i in 0..self.entries.len() {
ans.append(&mut self.entries[i].to_bytes());
}
return ans;
}
fn update_from_bytes(&mut self,bytes: &[u8]) -> Result<(),DiskStructError> {
let num_entries = bytes.len()/ENTRY_SIZE - 1;
self.header.update_from_bytes(&bytes[0..ENTRY_SIZE])?;
self.entries = Vec::new();
for i in 0..num_entries {
if (i+1)*ENTRY_SIZE > bytes.len() {
return Err(DiskStructError::OutOfData);
}
let entry_buf = DirectoryEntry::from_bytes(&bytes[i*ENTRY_SIZE..(i+1)*ENTRY_SIZE])?;
self.entries.push(entry_buf);
}
Ok(())
}
fn from_bytes(bytes: &[u8]) -> Result<Self,DiskStructError> {
let mut ans = Self::new();
ans.update_from_bytes(bytes)?;
Ok(ans)
}
fn len(&self) -> usize {
return self.header.len()*(1 + self.entries.len());
}
}