pub struct IsoDirEntry<'a> {
pub lba: u32,
pub size: u32,
pub flags: u8,
pub name: &'a str,
}
impl<'a> IsoDirEntry<'a> {
pub fn to_bytes(&self) -> Vec<u8> {
let (file_id, file_id_len) = match self.name {
"." => (vec![0x00], 1),
".." => (vec![0x01], 1),
_ => {
let name_str = if self.flags & 0x02 != 0 {
self.name.to_uppercase()
} else {
format!("{};1", self.name.to_uppercase())
};
let bytes = name_str.into_bytes();
let len = bytes.len();
(bytes, len)
}
};
let mut record_len = 33 + file_id_len;
if record_len % 2 != 0 {
record_len += 1;
}
assert!(
record_len <= u8::MAX as usize,
"Directory record length exceeds 255 bytes"
);
let mut record = vec![0u8; record_len];
record[0] = record_len as u8;
record[2..6].copy_from_slice(&self.lba.to_le_bytes());
record[6..10].copy_from_slice(&self.lba.to_be_bytes());
record[10..14].copy_from_slice(&self.size.to_le_bytes());
record[14..18].copy_from_slice(&self.size.to_be_bytes());
record[25] = self.flags;
record[28..30].copy_from_slice(&1u16.to_le_bytes()); record[30..32].copy_from_slice(&1u16.to_be_bytes()); record[32] = file_id_len as u8;
record[33..33 + file_id_len].copy_from_slice(&file_id);
record
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_file_record() {
let entry = IsoDirEntry {
lba: 123,
size: 456,
flags: 0,
name: "file.txt",
};
let bytes = entry.to_bytes();
assert_eq!(bytes.len(), 44);
assert_eq!(bytes[0], 44); assert_eq!(bytes[2..6], 123u32.to_le_bytes());
assert_eq!(bytes[6..10], 123u32.to_be_bytes());
assert_eq!(bytes[10..14], 456u32.to_le_bytes());
assert_eq!(bytes[14..18], 456u32.to_be_bytes());
assert_eq!(bytes[25], 0); assert_eq!(bytes[32], 10); assert_eq!(&bytes[33..43], b"FILE.TXT;1");
assert_eq!(bytes[43], 0); }
#[test]
fn test_directory_record() {
let entry = IsoDirEntry {
lba: 200,
size: 2048,
flags: 0x02, name: "mydir",
};
let bytes = entry.to_bytes();
assert_eq!(bytes.len(), 38);
assert_eq!(bytes[0], 38);
assert_eq!(bytes[25], 0x02);
assert_eq!(bytes[32], 5); assert_eq!(&bytes[33..38], b"MYDIR");
}
#[test]
fn test_current_dir_record() {
let entry = IsoDirEntry {
lba: 300,
size: 2048,
flags: 0x02,
name: ".",
};
let bytes = entry.to_bytes();
assert_eq!(bytes.len(), 34);
assert_eq!(bytes[0], 34);
assert_eq!(bytes[32], 1);
assert_eq!(bytes[33], 0x00);
}
#[test]
fn test_parent_dir_record() {
let entry = IsoDirEntry {
lba: 400,
size: 2048,
flags: 0x02,
name: "..",
};
let bytes = entry.to_bytes();
assert_eq!(bytes.len(), 34);
assert_eq!(bytes[0], 34);
assert_eq!(bytes[32], 1);
assert_eq!(bytes[33], 0x01);
}
}