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))
}
}