use crate::parse::{parse_uleb128_at, ParseAt, ParseErrorContext as _, ParseResult};
use crate::xo65::Xo65Bytes;
#[derive(Debug)]
pub struct SpanTable<'data> {
bytes: Xo65Bytes<'data>,
spans: Box<[Span]>,
}
impl<'data> SpanTable<'data> {
pub fn as_bytes(&self) -> &'data [u8] {
self.bytes.as_inner()
}
pub fn count(&self) -> usize {
self.spans.len()
}
pub fn get(&self, idx: usize) -> Option<&Span> {
self.spans.get(idx)
}
pub fn iter(
&self,
) -> impl DoubleEndedIterator<Item = &Span> + ExactSizeIterator + std::iter::FusedIterator + Clone
{
self.spans.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 spans = Vec::<Span>::with_capacity(count);
for i in 0..count {
let span = Span::parse_at(&bytes, &mut off)
.with_context(|| format!("span {i} parse error"))?;
spans.push(span);
}
Ok(Self {
bytes,
spans: spans.into(),
})
}
}
#[derive(Debug)]
pub struct Span {
section: u32,
off: u32,
len: u32,
ty: u32,
}
impl Span {
pub fn section(&self) -> u32 {
self.section
}
pub fn offset(&self) -> u32 {
self.off
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> u32 {
self.len
}
pub fn ty(&self) -> u32 {
self.ty
}
}
impl ParseAt<'_> for Span {
fn parse_at(bytes: &Xo65Bytes<'_>, off: &mut usize) -> ParseResult<Self> {
let section = parse_uleb128_at(bytes, off)?;
let span_off = parse_uleb128_at(bytes, off)?;
let span_len = parse_uleb128_at(bytes, off)?;
let ty = parse_uleb128_at(bytes, off)?;
Ok(Self {
section,
off: span_off,
len: span_len,
ty,
})
}
}