use std::io;
use std::marker::PhantomData;
use crate::beve::traits::Read;
use crate::options::{Options, Standard};
use crate::stream::{DEFAULT_BUFFER, Split};
use super::split::{Mode, Splitter};
use super::window::{self, Window};
use super::{StreamError, StreamResult};
pub struct Documents<R, O: Options = Standard> {
reader: R,
win: Window,
chunk: usize,
options: PhantomData<fn() -> O>,
}
impl<R: io::Read> Documents<R> {
pub fn array(reader: R) -> Self {
Self::new(reader, Mode::Array)
}
pub fn values(reader: R) -> Self {
Self::new(reader, Mode::Values)
}
pub fn new(reader: R, mode: Mode) -> Self {
Documents {
reader,
win: Window::new(Splitter::new(mode), DEFAULT_BUFFER),
chunk: DEFAULT_BUFFER,
options: PhantomData,
}
}
}
impl<R: io::Read, O: Options> Documents<R, O> {
#[must_use = "with_options returns a configured reader and consumes the old one"]
pub fn with_options<P: Options>(self) -> Documents<R, P> {
Documents {
reader: self.reader,
win: self.win,
chunk: self.chunk,
options: PhantomData,
}
}
#[must_use = "max_value returns a configured reader and consumes the old one"]
pub fn max_value(mut self, bytes: usize) -> Self {
self.win.set_limit(bytes);
self
}
#[must_use = "read_size returns a configured reader and consumes the old one"]
pub fn read_size(mut self, bytes: usize) -> Self {
self.chunk = bytes.max(1);
self
}
pub fn buffered(&self) -> usize {
self.win.buffered()
}
pub fn offset(&self) -> usize {
self.win.offset()
}
pub fn into_inner(self) -> R {
self.reader
}
pub fn into_parts(self) -> (R, Vec<u8>) {
(self.reader, self.win.into_unread())
}
pub fn next_value<'a, T: Read<'a> + Default>(&'a mut self) -> Option<StreamResult<T>> {
match self.locate() {
Ok(Some(span)) => Some(window::read::<O, T>(&self.win, span)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
pub fn next_value_into<T: for<'de> Read<'de>>(
&mut self,
value: &mut T,
) -> Option<StreamResult<()>> {
match self.locate() {
Ok(Some(span)) => Some(window::read_into::<O, T>(&self.win, span, value)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
pub fn iter<T: for<'de> Read<'de> + Default>(&mut self) -> Iter<'_, R, T, O> {
Iter {
docs: self,
marker: PhantomData,
}
}
fn locate(&mut self) -> StreamResult<Option<(usize, usize)>> {
loop {
match self.win.try_next()? {
Split::Item { start, end } => return Ok(Some((start, end))),
Split::End => return Ok(None),
Split::Need => {
if self.win.is_eof() {
return Err(StreamError::Parse(crate::Error::new(
crate::ErrorCode::UnexpectedEnd,
self.win.offset(),
)));
}
self.win.fill(&mut self.reader, self.chunk)?;
}
}
}
}
}
pub struct Iter<'d, R, T, O: Options = Standard> {
docs: &'d mut Documents<R, O>,
marker: PhantomData<fn() -> T>,
}
impl<R: io::Read, T: for<'de> Read<'de> + Default, O: Options> Iterator for Iter<'_, R, T, O> {
type Item = StreamResult<T>;
fn next(&mut self) -> Option<Self::Item> {
self.docs.next_value::<T>()
}
}