xo65 0.1.0

Library for parsing cc65 object files (xo65 format)
Documentation
use crate::parse::{
    parse_bytes_at, parse_uleb128_at, ParseAt, ParseErrorContext as _, ParseResult,
};
use crate::xo65::Xo65Bytes;

#[derive(Debug)]
pub struct StringTable<'data> {
    bytes: Xo65Bytes<'data>,

    strs: Box<[&'data [u8]]>,
}

impl<'data> StringTable<'data> {
    pub fn as_bytes(&self) -> &'data [u8] {
        self.bytes.as_inner()
    }

    pub fn count(&self) -> usize {
        self.strs.len()
    }

    pub fn get(&self, idx: usize) -> Option<&'data [u8]> {
        self.strs.get(idx).copied()
    }

    pub fn iter(
        &self,
    ) -> impl DoubleEndedIterator<Item = &'data [u8]>
           + ExactSizeIterator
           + std::iter::FusedIterator
           + Clone {
        self.strs.iter().copied()
    }

    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 strs = Vec::<&'data [u8]>::with_capacity(count);

        for i in 0..count {
            let s = Xo65String::parse_at(&bytes, &mut off)
                .with_context(|| format!("string {i} parse error"))?
                .0;
            strs.push(s);
        }

        Ok(Self {
            bytes,
            strs: strs.into(),
        })
    }
}

#[derive(Debug)]
struct Xo65String<'data>(&'data [u8]);

impl<'data> ParseAt<'data> for Xo65String<'data> {
    fn parse_at(bytes: &Xo65Bytes<'data>, off: &mut usize) -> ParseResult<Self> {
        let len = parse_uleb128_at(bytes, off)? as usize;
        let s = parse_bytes_at(bytes, off, len)?;

        Ok(Self(s))
    }
}