use alloc::{borrow::Cow, collections::BTreeMap, vec::Vec};
use crate::{parse::Reader, seal::Seal};
pub trait Read<'a>: Seal {
fn integer(&mut self) -> Option<u32>;
fn name(&mut self) -> Option<Cow<'a, str>>;
fn name_vector(&mut self) -> Option<Vec<Cow<'a, str>>>;
fn name_map(&mut self) -> Option<BTreeMap<u32, Cow<'a, str>>>;
fn indirect_name_map(
&mut self,
) -> Option<BTreeMap<u32, BTreeMap<u32, Cow<'a, str>>>>;
fn subsection(&mut self) -> Option<(u8, Reader<'a>)>;
}
impl<'a> Read<'a> for Reader<'a> {
fn integer(&mut self) -> Option<u32> {
let mut value = 0;
let mut shift = 0;
while {
let byte = self.u8()?;
value |= u32::from(byte & 0x7f) << shift;
shift += 7;
let more = shift < u32::BITS;
let fits_u32 = more || byte < 16;
if byte & 0x80 == 0 && fits_u32 {
return Some(value);
}
more
} {}
None
}
fn name(&mut self) -> Option<Cow<'a, str>> {
let len = self.integer()?.try_into().ok()?;
self.str(len).map(From::from)
}
fn name_vector(&mut self) -> Option<Vec<Cow<'a, str>>> {
(0..self.integer()?).map(|_| self.name()).collect()
}
fn name_map(&mut self) -> Option<BTreeMap<u32, Cow<'a, str>>> {
let mut name_map = BTreeMap::new();
for _ in 0..self.integer()? {
name_map.insert(self.integer()?, self.name()?);
}
Some(name_map)
}
fn indirect_name_map(
&mut self,
) -> Option<BTreeMap<u32, BTreeMap<u32, Cow<'a, str>>>> {
let mut indirect_name_map = BTreeMap::new();
for _ in 0..self.integer()? {
indirect_name_map.insert(self.integer()?, self.name_map()?);
}
Some(indirect_name_map)
}
fn subsection(&mut self) -> Option<(u8, Reader<'a>)> {
let subsection = self.u8()?;
let len = self.integer()?.try_into().ok()?;
Some((subsection, self.reader(len)?))
}
}