use crate::IsoError;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PathTableEntry {
pub lba: u32,
pub parent_dir_num: u16,
pub dir_id: Vec<u8>,
}
fn parse_table(data: &[u8], big_endian: bool) -> Result<Vec<PathTableEntry>, IsoError> {
let mut entries = Vec::new();
let mut offset = 0;
while offset < data.len() {
if offset + 8 > data.len() {
break;
}
let id_len = data[offset] as usize;
if id_len == 0 {
break;
}
let record_len = 8 + id_len + (id_len % 2); if offset + record_len > data.len() {
break;
}
let lba = if big_endian {
u32::from_be_bytes(data[offset + 2..offset + 6].try_into().unwrap())
} else {
u32::from_le_bytes(data[offset + 2..offset + 6].try_into().unwrap())
};
let parent = if big_endian {
u16::from_be_bytes(data[offset + 6..offset + 8].try_into().unwrap())
} else {
u16::from_le_bytes(data[offset + 6..offset + 8].try_into().unwrap())
};
let dir_id = data[offset + 8..offset + 8 + id_len].to_vec();
entries.push(PathTableEntry { lba, parent_dir_num: parent, dir_id });
offset += record_len;
}
Ok(entries)
}
pub fn parse_l_path_table(data: &[u8]) -> Result<Vec<PathTableEntry>, IsoError> {
parse_table(data, false)
}
pub fn parse_m_path_table(data: &[u8]) -> Result<Vec<PathTableEntry>, IsoError> {
parse_table(data, true)
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PathTableMismatch {
pub index: usize,
pub description: String,
}
pub fn validate_path_tables(l: &[PathTableEntry], m: &[PathTableEntry]) -> Vec<PathTableMismatch> {
let mut out = Vec::new();
if l.len() != m.len() {
out.push(PathTableMismatch {
index: 0,
description: format!("entry count mismatch: L={} M={}", l.len(), m.len()),
});
}
for (i, (le, me)) in l.iter().zip(m.iter()).enumerate() {
if le.lba != me.lba {
out.push(PathTableMismatch {
index: i,
description: format!("LBA mismatch: L={} M={}", le.lba, me.lba),
});
}
if le.parent_dir_num != me.parent_dir_num {
out.push(PathTableMismatch {
index: i,
description: format!(
"parent mismatch: L={} M={}",
le.parent_dir_num, me.parent_dir_num
),
});
}
if le.dir_id != me.dir_id {
out.push(PathTableMismatch {
index: i,
description: format!("dir_id mismatch: L={:?} M={:?}", le.dir_id, me.dir_id),
});
}
}
out
}