use std::io;
use crate::{
DecodeOptions, Format, IoResult, Result, Value,
io::{HexReader, HexSliceReader, PeekReader, SliceReader},
parse::Parser,
};
pub struct SequenceDecoder<'a> {
inner: SequenceDecoderInner<'a>,
}
enum SequenceDecoderInner<'a> {
Binary {
reader: SliceReader<'a>,
opts: DecodeOptions,
},
Hex {
reader: HexSliceReader<'a>,
opts: DecodeOptions,
},
Diagnostic {
parser: Parser<SliceReader<'a>>,
},
}
impl<'a> SequenceDecoder<'a> {
pub fn new<B: AsRef<[u8]> + ?Sized>(input: &'a B) -> Self {
Self::with_options(DecodeOptions::new(), input.as_ref())
}
pub(crate) fn with_options(opts: DecodeOptions, input: &'a [u8]) -> Self {
let inner = match opts.format_value() {
Format::Binary => SequenceDecoderInner::Binary {
reader: SliceReader(input),
opts,
},
Format::Hex => SequenceDecoderInner::Hex {
reader: HexSliceReader(input),
opts,
},
Format::Diagnostic => SequenceDecoderInner::Diagnostic {
parser: Parser::new(SliceReader(input), opts.recursion_limit_value()),
},
};
Self { inner }
}
}
impl<'a> Iterator for SequenceDecoder<'a> {
type Item = Result<Value>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
SequenceDecoderInner::Binary { reader, opts } => {
if reader.0.is_empty() {
None
} else {
Some(opts.decode_one(reader))
}
}
SequenceDecoderInner::Hex { reader, opts } => {
if reader.0.is_empty() {
None
} else {
Some(opts.decode_one(reader))
}
}
SequenceDecoderInner::Diagnostic { parser } => parser.parse_seq_item().transpose(),
}
}
}
pub struct SequenceReader<R: io::Read> {
inner: SequenceReaderInner<R>,
}
enum SequenceReaderInner<R: io::Read> {
Binary {
reader: PeekReader<R>,
opts: DecodeOptions,
},
Hex {
reader: HexReader<PeekReader<R>>,
opts: DecodeOptions,
},
Diagnostic {
parser: Parser<R>,
},
}
impl<R: io::Read> SequenceReader<R> {
pub fn new(reader: R) -> Self {
Self::with_options(DecodeOptions::new(), reader)
}
pub(crate) fn with_options(opts: DecodeOptions, reader: R) -> Self {
let inner = match opts.format_value() {
Format::Binary => SequenceReaderInner::Binary {
reader: PeekReader::new(reader),
opts,
},
Format::Hex => SequenceReaderInner::Hex {
reader: HexReader(PeekReader::new(reader)),
opts,
},
Format::Diagnostic => SequenceReaderInner::Diagnostic {
parser: Parser::new(reader, opts.recursion_limit_value()),
},
};
Self { inner }
}
}
impl<R: io::Read> Iterator for SequenceReader<R> {
type Item = IoResult<Value>;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
SequenceReaderInner::Binary { reader, opts } => match reader.at_eof() {
Ok(true) => None,
Ok(false) => Some(opts.decode_one(reader)),
Err(error) => Some(Err(error)),
},
SequenceReaderInner::Hex { reader, opts } => match reader.0.at_eof() {
Ok(true) => None,
Ok(false) => Some(opts.decode_one(reader)),
Err(error) => Some(Err(error)),
},
SequenceReaderInner::Diagnostic { parser } => parser.parse_seq_item().transpose(),
}
}
}