use crate::parse::{parse_uleb128_at, ParseAt, ParseErrorContext as _, ParseResult};
use crate::xo65::Xo65Bytes;
#[derive(Debug)]
pub struct FileTable<'data> {
bytes: Xo65Bytes<'data>,
files: Box<[File]>,
}
impl<'data> FileTable<'data> {
pub fn as_bytes(&self) -> &'data [u8] {
self.bytes.as_inner()
}
pub fn count(&self) -> usize {
self.files.len()
}
pub fn get(&self, idx: usize) -> Option<&File> {
self.files.get(idx)
}
pub fn iter(
&self,
) -> impl DoubleEndedIterator<Item = &File> + ExactSizeIterator + std::iter::FusedIterator + Clone
{
self.files.iter()
}
pub(crate) fn parse(bytes: Xo65Bytes<'data>) -> ParseResult<Self> {
let mut off = 0;
let count = parse_uleb128_at(&bytes, &mut off)? as usize;
let mut files = Vec::<File>::with_capacity(count);
for i in 0..count {
let file = File::parse_at(&bytes, &mut off)
.with_context(|| format!("file {i} parse error"))?;
files.push(file);
}
Ok(Self {
bytes,
files: files.into(),
})
}
}
#[derive(Debug)]
pub struct File {
name: u32,
size: u32,
mtime: i32,
}
impl File {
pub fn name(&self) -> u32 {
self.name
}
pub fn size(&self) -> u32 {
self.size
}
pub fn mtime(&self) -> i32 {
self.mtime
}
}
impl ParseAt<'_> for File {
fn parse_at(bytes: &Xo65Bytes<'_>, off: &mut usize) -> ParseResult<Self> {
let name = parse_uleb128_at(bytes, off)?;
let mtime = i32::parse_at(bytes, off)?;
let size = parse_uleb128_at(bytes, off)?;
Ok(Self { name, size, mtime })
}
}