use alloc::vec;
use alloc::vec::Vec;
use crate::Position;
use crate::de::{Deserialize, DeserializeDriver, Frame, Progress, StreamDeserializer};
use crate::error::{Error, ErrorKind};
const READ_SIZE: usize = 8 * 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Status {
Ready,
NeedInput,
End,
}
pub struct InputBuffer<D: StreamDeserializer> {
deserializer: D,
data: Vec<u8>,
start: usize,
end: usize,
eof: bool,
position: Position,
ready: Option<(usize, usize, usize)>,
done: bool,
failed: bool,
feeding: bool,
}
impl<D: StreamDeserializer> InputBuffer<D> {
pub fn new(deserializer: D) -> InputBuffer<D> {
InputBuffer {
deserializer,
data: Vec::new(),
start: 0,
end: 0,
eof: false,
position: Position::start(),
ready: None,
done: false,
failed: false,
feeding: false,
}
}
pub fn deserializer(&self) -> &D {
&self.deserializer
}
pub fn into_parts(mut self) -> (D, Vec<u8>) {
self.data.truncate(self.end);
self.data.drain(..self.start);
(self.deserializer, self.data)
}
pub fn offset(&self) -> usize {
self.position.offset
}
pub fn buffered(&self) -> usize {
self.end - self.start
}
pub fn is_eof(&self) -> bool {
self.eof
}
fn consume(&mut self, len: usize) {
self.position
.advance(&self.data[self.start..self.start + len]);
self.start += len;
}
pub fn poll(&mut self) -> Result<Status, Error> {
if self.ready.is_some() {
return Ok(Status::Ready);
}
if self.failed {
return Err(failed_error());
}
if self.feeding {
return Err(Error::new(ErrorKind::Unexpected, "a value is being fed"));
}
if self.done {
return Ok(Status::End);
}
loop {
let input = &self.data[self.start..self.end];
let frame = match self.deserializer.frame(input, self.eof) {
Ok(frame) => frame,
Err(err) => {
self.failed = true;
let base = self.position;
let err = if self.deserializer.is_text() {
err.resolve_position(input)
} else {
err
};
return Err(err.shift_position(base));
}
};
match frame {
Frame::Value {
start,
end,
consumed,
} => {
assert!(
start <= end && end <= consumed && consumed <= input.len(),
"invalid frame"
);
self.ready = Some((start, end, consumed));
return Ok(Status::Ready);
}
Frame::Incomplete { consumed } => {
assert!(consumed <= input.len(), "invalid frame");
if consumed > 0 {
self.consume(consumed);
continue;
}
if self.eof {
self.failed = true;
return Err(Error::new(ErrorKind::EndOfFile, "unexpected end of input")
.shift_position(self.position));
}
return Ok(Status::NeedInput);
}
Frame::End => {
assert!(self.eof, "end of values before the end of the input");
self.done = true;
return Ok(Status::End);
}
}
}
}
pub fn peek(&mut self) -> Result<Status, Error> {
if self.ready.is_some() || self.feeding {
return Ok(Status::Ready);
}
if self.failed {
return Err(failed_error());
}
if self.done {
return Ok(Status::End);
}
loop {
let input = &self.data[self.start..self.end];
let progress = match self.deserializer.peek(input, self.eof) {
Ok(Some(progress)) => progress,
Ok(None) => return self.poll(),
Err(err) => {
self.failed = true;
let err = if self.deserializer.is_text() {
err.resolve_position(input)
} else {
err
};
return Err(err.shift_position(self.position));
}
};
match progress {
Progress::Done { consumed } => {
assert!(consumed <= input.len(), "invalid progress");
self.consume(consumed);
return Ok(Status::Ready);
}
Progress::NeedMore { consumed } => {
assert!(consumed <= input.len(), "invalid progress");
if consumed > 0 {
self.consume(consumed);
continue;
}
if self.eof {
self.failed = true;
return Err(Error::new(ErrorKind::EndOfFile, "unexpected end of input")
.shift_position(self.position));
}
return Ok(Status::NeedInput);
}
Progress::End => {
assert!(self.eof, "end of values before the end of the input");
self.done = true;
return Ok(Status::End);
}
}
}
}
pub fn supports_feed(&self) -> bool {
self.deserializer.supports_feed()
}
pub fn feed(&mut self, driver: &mut DeserializeDriver<'_, '_>) -> Result<Status, Error> {
assert!(
self.deserializer.supports_feed(),
"the stream deserializer does not support feeding"
);
if self.ready.is_some() {
return self.drive_transient(driver).map(|()| Status::Ready);
}
if self.failed {
return Err(failed_error());
}
if self.done {
return Ok(Status::End);
}
let input = &self.data[self.start..self.end];
let rv = self
.deserializer
.feed(input, self.position.offset, self.eof, driver);
match rv {
Ok(Progress::Done { consumed }) => {
assert!(consumed <= input.len(), "invalid progress");
self.consume(consumed);
self.feeding = false;
Ok(Status::Ready)
}
Ok(Progress::NeedMore { consumed }) => {
assert!(consumed <= input.len(), "invalid progress");
self.consume(consumed);
self.feeding = true;
if self.eof {
self.failed = true;
return Err(self.locate(
Error::new(ErrorKind::EndOfFile, "unexpected end of input")
.with_offset(self.position.offset),
));
}
Ok(Status::NeedInput)
}
Ok(Progress::End) => {
assert!(self.eof, "end of values before the end of the input");
self.done = true;
self.feeding = false;
Ok(Status::End)
}
Err(err) => {
self.feeding = false;
Err(self.locate(err))
}
}
}
fn locate(&self, err: Error) -> Error {
err.map_each(|err| match err.offset() {
Some(offset)
if self.deserializer.is_text()
&& err.line().is_none()
&& offset >= self.position.offset
&& offset - self.position.offset <= self.end - self.start =>
{
let mut position = self.position;
position
.advance(&self.data[self.start..self.start + offset - self.position.offset]);
err.with_position(offset, position.line, position.column)
}
_ => err,
})
}
pub fn read_buf(&mut self) -> &mut [u8] {
if self.data.len() - self.end < READ_SIZE {
if self.start > 0 {
self.data.copy_within(self.start..self.end, 0);
self.end -= self.start;
self.start = 0;
}
if self.data.len() - self.end < READ_SIZE {
let len = (self.end + READ_SIZE).max(self.data.len() * 2);
let mut data = vec![0; len];
data[..self.end].copy_from_slice(&self.data[..self.end]);
self.data = data;
}
}
&mut self.data[self.end..]
}
pub fn filled(&mut self, len: usize) {
assert!(!self.eof, "data after the end of the stream");
assert!(
len <= self.data.len() - self.end,
"more data than read into"
);
self.end += len;
}
pub fn set_eof(&mut self) {
self.eof = true;
}
pub fn extend_from_slice(&mut self, mut input: &[u8]) {
while !input.is_empty() {
let buf = self.read_buf();
let len = buf.len().min(input.len());
buf[..len].copy_from_slice(&input[..len]);
self.filled(len);
input = &input[len..];
}
}
fn take_ready(&mut self) -> (core::ops::Range<usize>, Position) {
let (start, end, consumed) = self
.ready
.take()
.expect("no value is ready, poll the buffer first");
let mut position = self.position;
position.advance(&self.data[self.start..self.start + start]);
let range = self.start + start..self.start + end;
self.consume(consumed);
(range, position)
}
pub fn deserialize<'a, T: Deserialize<'a>>(&'a mut self) -> Result<T, Error> {
self.deserialize_with(|_| {})
}
pub fn deserialize_with<'a, T, F>(&'a mut self, setup: F) -> Result<T, Error>
where
T: Deserialize<'a>,
F: FnOnce(&mut DeserializeDriver<'_, 'a>),
{
let mut out = None;
{
let mut driver = DeserializeDriver::new(&mut out);
setup(&mut driver);
self.drive(&mut driver)?;
}
out.ok_or_else(|| Error::new(ErrorKind::EndOfFile, "empty input"))
}
pub fn drive<'a>(&'a mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
let (range, position) = self.take_ready();
let frame = &self.data[range];
self.deserializer
.drive_frame(frame, driver)
.map_err(|err| err.shift_position(position))
}
pub fn drive_transient(&mut self, driver: &mut DeserializeDriver<'_, '_>) -> Result<(), Error> {
let (range, position) = self.take_ready();
let frame = &self.data[range];
let deserializer = &mut self.deserializer;
driver
.transient(|driver| deserializer.drive_frame(frame, driver))
.map_err(|err| err.shift_position(position))
}
pub fn trailing_error(&self) -> Error {
let (start, _, _) = self.ready.expect("no value is ready");
let mut position = self.position;
position.advance(&self.data[self.start..self.start + start]);
Error::new(ErrorKind::Unexpected, "unexpected value after the end")
.with_position(0, 1, 1)
.shift_position(position)
}
}
#[cold]
fn failed_error() -> Error {
Error::new(ErrorKind::Unexpected, "cannot continue after an error")
}