use crate::{BinaryReader, BinaryReaderError, Result};
use std::fmt;
use std::marker;
use std::ops::Range;
mod component;
mod core;
pub use self::component::*;
pub use self::core::*;
pub trait FromReader<'a>: Sized {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self>;
}
impl<'a> FromReader<'a> for u32 {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
reader.read_var_u32()
}
}
impl<'a> FromReader<'a> for &'a str {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
reader.read_string()
}
}
impl<'a, T, U> FromReader<'a> for (T, U)
where
T: FromReader<'a>,
U: FromReader<'a>,
{
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
Ok((reader.read()?, reader.read()?))
}
}
pub struct SectionLimited<'a, T> {
reader: BinaryReader<'a>,
count: u32,
_marker: marker::PhantomData<T>,
}
impl<'a, T> SectionLimited<'a, T> {
pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
let mut reader = BinaryReader::new_with_offset(data, offset);
let count = reader.read_var_u32()?;
Ok(SectionLimited {
reader,
count,
_marker: marker::PhantomData,
})
}
pub fn count(&self) -> u32 {
self.count
}
pub fn original_position(&self) -> usize {
self.reader.original_position()
}
pub fn range(&self) -> Range<usize> {
self.reader.range()
}
pub fn into_iter_with_offsets(self) -> SectionLimitedIntoIterWithOffsets<'a, T>
where
T: FromReader<'a>,
{
SectionLimitedIntoIterWithOffsets {
iter: self.into_iter(),
}
}
}
impl<T> Clone for SectionLimited<'_, T> {
fn clone(&self) -> Self {
SectionLimited {
reader: self.reader.clone(),
count: self.count,
_marker: self._marker,
}
}
}
impl<T> fmt::Debug for SectionLimited<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SectionLimited")
.field("count", &self.count)
.field("range", &self.range())
.finish()
}
}
impl<'a, T> IntoIterator for SectionLimited<'a, T>
where
T: FromReader<'a>,
{
type Item = Result<T>;
type IntoIter = SectionLimitedIntoIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
SectionLimitedIntoIter {
remaining: self.count,
section: self,
end: false,
}
}
}
pub struct SectionLimitedIntoIter<'a, T> {
section: SectionLimited<'a, T>,
remaining: u32,
end: bool,
}
impl<T> SectionLimitedIntoIter<'_, T> {
pub fn original_position(&self) -> usize {
self.section.reader.original_position()
}
}
impl<'a, T> Iterator for SectionLimitedIntoIter<'a, T>
where
T: FromReader<'a>,
{
type Item = Result<T>;
fn next(&mut self) -> Option<Result<T>> {
if self.end {
return None;
}
if self.remaining == 0 {
self.end = true;
if self.section.reader.eof() {
return None;
}
return Some(Err(BinaryReaderError::new(
"section size mismatch: unexpected data at the end of the section",
self.section.reader.original_position(),
)));
}
let result = self.section.reader.read();
self.end = result.is_err();
self.remaining -= 1;
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.remaining as usize;
(remaining, Some(remaining))
}
}
impl<'a, T> ExactSizeIterator for SectionLimitedIntoIter<'a, T> where T: FromReader<'a> {}
pub struct SectionLimitedIntoIterWithOffsets<'a, T> {
iter: SectionLimitedIntoIter<'a, T>,
}
impl<'a, T> Iterator for SectionLimitedIntoIterWithOffsets<'a, T>
where
T: FromReader<'a>,
{
type Item = Result<(usize, T)>;
fn next(&mut self) -> Option<Self::Item> {
let pos = self.iter.section.reader.original_position();
Some(self.iter.next()?.map(|item| (pos, item)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T> ExactSizeIterator for SectionLimitedIntoIterWithOffsets<'a, T> where T: FromReader<'a> {}
pub trait Subsection<'a>: Sized {
fn from_reader(id: u8, reader: BinaryReader<'a>) -> Result<Self>;
}
pub struct Subsections<'a, T> {
reader: BinaryReader<'a>,
_marker: marker::PhantomData<T>,
}
impl<'a, T> Subsections<'a, T> {
pub fn new(data: &'a [u8], offset: usize) -> Self {
Subsections {
reader: BinaryReader::new_with_offset(data, offset),
_marker: marker::PhantomData,
}
}
pub fn original_position(&self) -> usize {
self.reader.original_position()
}
pub fn range(&self) -> Range<usize> {
self.reader.range()
}
fn read(&mut self) -> Result<T>
where
T: Subsection<'a>,
{
let subsection_id = self.reader.read_u7()?;
let reader = self.reader.read_reader("unexpected end of section")?;
T::from_reader(subsection_id, reader)
}
}
impl<T> Clone for Subsections<'_, T> {
fn clone(&self) -> Self {
Subsections {
reader: self.reader.clone(),
_marker: self._marker,
}
}
}
impl<T> fmt::Debug for Subsections<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Subsections")
.field("range", &self.range())
.finish()
}
}
impl<'a, T> Iterator for Subsections<'a, T>
where
T: Subsection<'a>,
{
type Item = Result<T>;
fn next(&mut self) -> Option<Result<T>> {
if self.reader.eof() {
None
} else {
Some(self.read())
}
}
}