use crate::parse::{parse_uleb128_at, ParseAt, ParseErrorContext as _, ParseResult};
use crate::xo65::Xo65Bytes;
#[derive(Debug)]
pub struct ImportTable<'data> {
bytes: Xo65Bytes<'data>,
imports: Box<[Import]>,
}
impl<'data> ImportTable<'data> {
pub fn as_bytes(&self) -> &'data [u8] {
self.bytes.as_inner()
}
pub fn count(&self) -> usize {
self.imports.len()
}
pub fn get(&self, idx: usize) -> Option<&Import> {
self.imports.get(idx)
}
pub fn iter(
&self,
) -> impl DoubleEndedIterator<Item = &Import> + ExactSizeIterator + std::iter::FusedIterator + Clone
{
self.imports.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 imports = Vec::<Import>::with_capacity(count);
for i in 0..count {
let import = Import::parse_at(&bytes, &mut off)
.with_context(|| format!("import {i} parse error"))?;
imports.push(import);
}
Ok(Self {
bytes,
imports: imports.into(),
})
}
}
#[derive(Debug)]
pub struct Import {
addr_size: u8,
name: u32,
def_lines: Box<[u32]>,
ref_lines: Box<[u32]>,
}
impl Import {
pub fn addr_size(&self) -> u8 {
self.addr_size
}
pub fn name(&self) -> u32 {
self.name
}
pub fn def_lines(&self) -> &[u32] {
&self.def_lines
}
pub fn ref_lines(&self) -> &[u32] {
&self.ref_lines
}
}
impl ParseAt<'_> for Import {
fn parse_at(bytes: &Xo65Bytes<'_>, off: &mut usize) -> ParseResult<Self> {
let addr_size = u8::parse_at(bytes, off)?;
let name = parse_uleb128_at(bytes, off)?;
let def_lines = parse_lines_at(bytes, off)?;
let ref_lines = parse_lines_at(bytes, off)?;
Ok(Self {
addr_size,
name,
def_lines,
ref_lines,
})
}
}
fn parse_lines_at(bytes: &Xo65Bytes<'_>, off: &mut usize) -> ParseResult<Box<[u32]>> {
let count = parse_uleb128_at(bytes, off)? as usize;
let mut lines = Vec::<u32>::with_capacity(count);
for _ in 0..count {
let line = parse_uleb128_at(bytes, off)?;
lines.push(line);
}
Ok(lines.into())
}