use std::marker::PhantomData;
use crate::json::traits::Read;
use crate::options::{Options, Standard};
use crate::stream::{DEFAULT_BUFFER, Split};
use super::StreamResult;
use super::split::{Mode, Splitter};
use super::window::{self, Window};
pub struct Feed<O: Options = Standard> {
win: Window,
options: PhantomData<fn() -> O>,
}
impl Default for Feed {
fn default() -> Self {
Self::values()
}
}
impl Feed {
pub fn values() -> Self {
Self::new(Mode::Values)
}
pub fn lines() -> Self {
Self::new(Mode::Lines)
}
pub fn array() -> Self {
Self::new(Mode::Array)
}
pub fn new(mode: Mode) -> Self {
Feed {
win: Window::new(Splitter::new(mode), DEFAULT_BUFFER),
options: PhantomData,
}
}
}
impl<O: Options> Feed<O> {
#[must_use = "with_options returns a configured feed and consumes the old one"]
pub fn with_options<P: Options>(mut self) -> Feed<P> {
self.win.framer_mut().set_comments(P::ALLOW_COMMENTS);
Feed {
win: self.win,
options: PhantomData,
}
}
#[must_use = "max_value returns a configured feed and consumes the old one"]
pub fn max_value(mut self, bytes: usize) -> Self {
self.win.set_limit(bytes);
self
}
pub fn push(&mut self, bytes: &[u8]) {
self.win.extend(bytes);
}
pub fn end(&mut self) {
self.win.set_eof();
}
pub fn buffered(&self) -> usize {
self.win.buffered()
}
pub fn offset(&self) -> usize {
self.win.offset()
}
pub fn next_value<'a, T: Read<'a> + Default>(&'a mut self) -> Option<StreamResult<T>> {
match self.locate() {
Ok(Some(span)) => Some(window::parse::<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::parse_into::<O, T>(&self.win, span, value)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
fn locate(&mut self) -> StreamResult<Option<(usize, usize)>> {
match self.win.try_next()? {
Split::Item { start, end } => Ok(Some((start, end))),
Split::Need | Split::End => Ok(None),
}
}
}
impl<O: Options> core::fmt::Debug for Feed<O> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Feed")
.field("buffered", &self.buffered())
.field("offset", &self.offset())
.finish_non_exhaustive()
}
}