use super::Leaf;
use crate::parser::{Parser, ParserError, ParserMut};
use crate::utils::iter::{HasRestLen, IteratorWithRangesExt};
use std::mem::take;
#[derive(Clone)]
pub struct TypesIter<'a> {
buffer: &'a [u8],
}
impl<'a> TypesIter<'a> {
pub fn new(buffer: &'a [u8]) -> Self {
Self { buffer }
}
pub fn rest(&self) -> &'a [u8] {
self.buffer
}
}
impl<'a> HasRestLen for TypesIter<'a> {
fn rest_len(&self) -> usize {
self.buffer.len()
}
}
impl<'a> Iterator for TypesIter<'a> {
type Item = TypeRecord<'a>;
fn next(&mut self) -> Option<TypeRecord<'a>> {
if self.buffer.is_empty() {
return None;
}
let mut p = Parser::new(self.buffer);
let record_len = p.u16().ok()?;
if record_len < 2 {
return None;
}
let type_kind = p.u16().ok()?;
let Ok(record_data) = p.bytes(record_len as usize - 2) else {
return None;
};
self.buffer = p.into_rest();
Some(TypeRecord {
data: record_data,
kind: Leaf(type_kind),
})
}
}
#[derive(Clone)]
pub struct TypeRecord<'a> {
pub kind: Leaf,
pub data: &'a [u8],
}
impl<'a> TypeRecord<'a> {
pub fn parse(&self) -> Result<crate::types::TypeData<'a>, ParserError> {
crate::types::TypeData::parse(self.kind, &mut Parser::new(self.data))
}
}
pub fn build_types_starts(num_records_expected: usize, type_records: &[u8]) -> Vec<u32> {
let mut starts: Vec<u32> = Vec::with_capacity(num_records_expected + 1);
let mut iter = TypesIter::new(type_records).with_ranges();
loop {
let pos = iter.pos();
starts.push(pos as u32);
if iter.next().is_none() {
break;
}
}
starts.shrink_to_fit();
starts
}
pub struct TypesIterMut<'a> {
buffer: &'a mut [u8],
}
impl<'a> TypesIterMut<'a> {
pub fn new(buffer: &'a mut [u8]) -> Self {
Self { buffer }
}
}
impl<'a> HasRestLen for TypesIterMut<'a> {
fn rest_len(&self) -> usize {
self.buffer.len()
}
}
impl<'a> Iterator for TypesIterMut<'a> {
type Item = TypeRecordMut<'a>;
fn next(&mut self) -> Option<TypeRecordMut<'a>> {
if self.buffer.is_empty() {
return None;
}
let mut parser = ParserMut::new(take(&mut self.buffer));
let record_len = parser.u16().ok()?;
if record_len < 2 {
return None;
}
let type_kind = parser.u16().ok()?;
let Ok(record_data) = parser.bytes_mut(record_len as usize - 2) else {
return None;
};
self.buffer = parser.into_rest();
Some(TypeRecordMut {
data: record_data,
kind: Leaf(type_kind),
})
}
}
pub struct TypeRecordMut<'a> {
pub kind: Leaf,
pub data: &'a mut [u8],
}