use crate::lib::{cmp::Ordering, fmt, marker::PhantomData, str::Chars};
use crate::{
error::{
ParseError,
ParseResult::{self, *},
StreamError, StringStreamError, Tracked, UnexpectedParse,
},
Parser,
};
#[cfg(feature = "std")]
pub use self::decoder::Decoder;
#[doc(hidden)]
#[macro_export]
macro_rules! clone_resetable {
(( $($params: tt)* ) $ty: ty) => {
impl<$($params)*> ResetStream for $ty
where Self: StreamOnce
{
type Checkpoint = Self;
fn checkpoint(&self) -> Self {
self.clone()
}
#[inline]
fn reset(&mut self, checkpoint: Self) -> Result<(), Self::Error> {
*self = checkpoint;
Ok(())
}
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod buf_reader;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod buffered;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod easy;
pub mod position;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod read;
pub mod span;
pub mod state;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod decoder;
pub trait Positioned: StreamOnce {
fn position(&self) -> Self::Position;
}
pub type StreamErrorFor<Input> = <<Input as StreamOnce>::Error as ParseError<
<Input as StreamOnce>::Token,
<Input as StreamOnce>::Range,
<Input as StreamOnce>::Position,
>>::StreamError;
pub trait StreamOnce {
type Token: Clone;
type Range: Clone;
type Position: Clone + Ord;
type Error: ParseError<Self::Token, Self::Range, Self::Position>;
fn uncons(&mut self) -> Result<Self::Token, StreamErrorFor<Self>>;
fn is_partial(&self) -> bool {
false
}
}
pub trait ResetStream: StreamOnce {
type Checkpoint: Clone;
fn checkpoint(&self) -> Self::Checkpoint;
fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error>;
}
clone_resetable! {('a) &'a str}
clone_resetable! {('a, T) &'a [T]}
clone_resetable! {('a, T) SliceStream<'a, T> }
clone_resetable! {(T: Clone) IteratorStream<T>}
pub trait Stream: StreamOnce + ResetStream + Positioned {}
impl<Input> Stream for Input
where
Input: StreamOnce + Positioned + ResetStream,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
}
#[inline]
pub fn uncons<Input>(input: &mut Input) -> ParseResult<Input::Token, Input::Error>
where
Input: ?Sized + Stream,
{
match input.uncons() {
Ok(x) => CommitOk(x),
Err(err) => wrap_stream_error(input, err),
}
}
pub trait RangeStreamOnce: StreamOnce + ResetStream {
fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>>;
fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool;
#[inline]
fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
let mut committed = false;
let result = self.uncons_while(|c| {
let ok = f(c);
committed |= ok;
ok
});
if committed {
match result {
Ok(x) => CommitOk(x),
Err(x) => CommitErr(x),
}
} else {
PeekErr(Tracked::from(
StreamErrorFor::<Self>::unexpected_static_message(""),
))
}
}
fn distance(&self, end: &Self::Checkpoint) -> usize;
fn range(&self) -> Self::Range;
}
pub trait RangeStream: Stream + RangeStreamOnce {}
impl<Input> RangeStream for Input where Input: RangeStreamOnce + Stream {}
#[doc(hidden)]
pub fn wrap_stream_error<T, Input>(
input: &Input,
err: <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
) -> ParseResult<T, <Input as StreamOnce>::Error>
where
Input: ?Sized + StreamOnce + Positioned,
{
let err = Input::Error::from_error(input.position(), err);
if input.is_partial() {
CommitErr(err)
} else {
PeekErr(err.into())
}
}
#[inline]
pub fn uncons_range<Input>(
input: &mut Input,
size: usize,
) -> ParseResult<Input::Range, <Input as StreamOnce>::Error>
where
Input: ?Sized + RangeStream,
{
match input.uncons_range(size) {
Err(err) => wrap_stream_error(input, err),
Ok(x) => {
if size == 0 {
PeekOk(x)
} else {
CommitOk(x)
}
}
}
}
#[doc(hidden)]
pub fn input_at_eof<Input>(input: &mut Input) -> bool
where
Input: ?Sized + Stream,
{
let before = input.checkpoint();
let x = input
.uncons()
.err()
.map_or(false, |err| err.is_unexpected_end_of_input());
input.reset(before).is_ok() && x
}
#[inline]
pub fn uncons_while<Input, F>(
input: &mut Input,
predicate: F,
) -> ParseResult<Input::Range, Input::Error>
where
F: FnMut(Input::Token) -> bool,
Input: ?Sized + RangeStream,
Input::Range: Range,
{
match input.uncons_while(predicate) {
Err(err) => wrap_stream_error(input, err),
Ok(x) => {
if input.is_partial() && input_at_eof(input) {
CommitErr(Input::Error::from_error(
input.position(),
StreamError::end_of_input(),
))
} else if x.len() == 0 {
PeekOk(x)
} else {
CommitOk(x)
}
}
}
}
#[inline]
pub fn uncons_while1<Input, F>(
input: &mut Input,
predicate: F,
) -> ParseResult<Input::Range, Input::Error>
where
F: FnMut(Input::Token) -> bool,
Input: ?Sized + RangeStream,
{
match input.uncons_while1(predicate) {
CommitOk(x) => {
if input.is_partial() && input_at_eof(input) {
CommitErr(Input::Error::from_error(
input.position(),
StreamError::end_of_input(),
))
} else {
CommitOk(x)
}
}
PeekErr(_) => {
if input.is_partial() && input_at_eof(input) {
CommitErr(Input::Error::from_error(
input.position(),
StreamError::end_of_input(),
))
} else {
PeekErr(Input::Error::empty(input.position()).into())
}
}
CommitErr(err) => {
if input.is_partial() && input_at_eof(input) {
CommitErr(Input::Error::from_error(
input.position(),
StreamError::end_of_input(),
))
} else {
wrap_stream_error(input, err)
}
}
PeekOk(_) => unreachable!(),
}
}
pub trait Range {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<'a, I> StreamOnce for &'a mut I
where
I: StreamOnce + ?Sized,
{
type Token = I::Token;
type Range = I::Range;
type Position = I::Position;
type Error = I::Error;
fn uncons(&mut self) -> Result<Self::Token, StreamErrorFor<Self>> {
(**self).uncons()
}
fn is_partial(&self) -> bool {
(**self).is_partial()
}
}
impl<'a, I> Positioned for &'a mut I
where
I: Positioned + ?Sized,
{
#[inline]
fn position(&self) -> Self::Position {
(**self).position()
}
}
impl<'a, I> ResetStream for &'a mut I
where
I: ResetStream + ?Sized,
{
type Checkpoint = I::Checkpoint;
fn checkpoint(&self) -> Self::Checkpoint {
(**self).checkpoint()
}
fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
(**self).reset(checkpoint)
}
}
impl<'a, I> RangeStreamOnce for &'a mut I
where
I: RangeStreamOnce + ?Sized,
{
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
(**self).uncons_while(f)
}
#[inline]
fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
(**self).uncons_while1(f)
}
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
(**self).uncons_range(size)
}
#[inline]
fn distance(&self, end: &Self::Checkpoint) -> usize {
(**self).distance(end)
}
fn range(&self) -> Self::Range {
(**self).range()
}
}
impl<'a, I> Range for &'a mut I
where
I: Range + ?Sized,
{
fn len(&self) -> usize {
(**self).len()
}
}
impl<'a> StreamOnce for &'a str {
type Token = char;
type Range = &'a str;
type Position = PointerOffset<str>;
type Error = StringStreamError;
#[inline]
fn uncons(&mut self) -> Result<char, StreamErrorFor<Self>> {
let mut chars = self.chars();
match chars.next() {
Some(c) => {
*self = chars.as_str();
Ok(c)
}
None => Err(StringStreamError::Eoi),
}
}
}
impl<'a> Positioned for &'a str {
#[inline]
fn position(&self) -> Self::Position {
PointerOffset::new(self.as_bytes().position().0)
}
}
#[allow(clippy::while_let_loop)]
fn str_uncons_while<'a, F>(slice: &mut &'a str, mut chars: Chars<'a>, mut f: F) -> &'a str
where
F: FnMut(char) -> bool,
{
let mut last_char_size = 0;
macro_rules! test_next {
() => {
match chars.next() {
Some(c) => {
if !f(c) {
last_char_size = c.len_utf8();
break;
}
}
None => break,
}
};
}
loop {
test_next!();
test_next!();
test_next!();
test_next!();
test_next!();
test_next!();
test_next!();
test_next!();
}
let len = slice.len() - chars.as_str().len() - last_char_size;
let (result, rest) = slice.split_at(len);
*slice = rest;
result
}
impl<'a> RangeStreamOnce for &'a str {
fn uncons_while<F>(&mut self, f: F) -> Result<&'a str, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
Ok(str_uncons_while(self, self.chars(), f))
}
#[inline]
fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
let mut chars = self.chars();
match chars.next() {
Some(c) => {
if !f(c) {
return PeekErr(Tracked::from(StringStreamError::UnexpectedParse));
}
}
None => return PeekErr(Tracked::from(StringStreamError::UnexpectedParse)),
}
CommitOk(str_uncons_while(self, chars, f))
}
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<&'a str, StreamErrorFor<Self>> {
fn is_char_boundary(s: &str, index: usize) -> bool {
if index == s.len() {
return true;
}
match s.as_bytes().get(index) {
None => false,
Some(&b) => b < 128 || b >= 192,
}
}
if size <= self.len() {
if is_char_boundary(self, size) {
let (result, remaining) = self.split_at(size);
*self = remaining;
Ok(result)
} else {
Err(StringStreamError::CharacterBoundary)
}
} else {
Err(StringStreamError::Eoi)
}
}
#[inline]
fn distance(&self, end: &Self) -> usize {
self.position().0 - end.position().0
}
fn range(&self) -> Self::Range {
self
}
}
impl<'a> Range for &'a str {
#[inline]
fn len(&self) -> usize {
str::len(self)
}
}
impl<'a, T> Range for &'a [T] {
#[inline]
fn len(&self) -> usize {
<[T]>::len(self)
}
}
fn slice_uncons_while<'a, T, F>(slice: &mut &'a [T], mut i: usize, mut f: F) -> &'a [T]
where
F: FnMut(T) -> bool,
T: Clone,
{
let len = slice.len();
let mut found = false;
macro_rules! check {
() => {
if !f(unsafe { slice.get_unchecked(i).clone() }) {
found = true;
break;
}
i += 1;
};
}
while len - i >= 8 {
check!();
check!();
check!();
check!();
check!();
check!();
check!();
check!();
}
if !found {
while let Some(c) = slice.get(i) {
if !f(c.clone()) {
break;
}
i += 1;
}
}
let (result, remaining) = slice.split_at(i);
*slice = remaining;
result
}
impl<'a, T> RangeStreamOnce for &'a [T]
where
T: Clone + PartialEq,
{
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<&'a [T], StreamErrorFor<Self>> {
if size <= self.len() {
let (result, remaining) = self.split_at(size);
*self = remaining;
Ok(result)
} else {
Err(UnexpectedParse::Eoi)
}
}
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<&'a [T], StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
Ok(slice_uncons_while(self, 0, f))
}
#[inline]
fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
if !self.first().cloned().map_or(false, &mut f) {
return PeekErr(Tracked::from(UnexpectedParse::Unexpected));
}
CommitOk(slice_uncons_while(self, 1, f))
}
#[inline]
fn distance(&self, end: &Self) -> usize {
end.len() - self.len()
}
fn range(&self) -> Self::Range {
self
}
}
impl<'a, T> Positioned for &'a [T]
where
T: Clone + PartialEq,
{
#[inline]
fn position(&self) -> Self::Position {
PointerOffset::new(self.as_ptr() as usize)
}
}
impl<'a, T> StreamOnce for &'a [T]
where
T: Clone + PartialEq,
{
type Token = T;
type Range = &'a [T];
type Position = PointerOffset<[T]>;
type Error = UnexpectedParse;
#[inline]
fn uncons(&mut self) -> Result<T, StreamErrorFor<Self>> {
match self.split_first() {
Some((first, rest)) => {
*self = rest;
Ok(first.clone())
}
None => Err(UnexpectedParse::Eoi),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct PartialStream<S>(pub S);
impl<S> From<S> for PartialStream<S> {
fn from(t: S) -> Self {
PartialStream(t)
}
}
impl<S> Positioned for PartialStream<S>
where
S: Positioned,
{
#[inline]
fn position(&self) -> Self::Position {
self.0.position()
}
}
impl<S> ResetStream for PartialStream<S>
where
S: ResetStream,
{
type Checkpoint = S::Checkpoint;
#[inline]
fn checkpoint(&self) -> Self::Checkpoint {
self.0.checkpoint()
}
#[inline]
fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), S::Error> {
self.0.reset(checkpoint)
}
}
impl<S> StreamOnce for PartialStream<S>
where
S: StreamOnce,
{
type Token = S::Token;
type Range = S::Range;
type Position = S::Position;
type Error = S::Error;
#[inline]
fn uncons(&mut self) -> Result<S::Token, StreamErrorFor<Self>> {
self.0.uncons()
}
fn is_partial(&self) -> bool {
true
}
}
impl<S> RangeStreamOnce for PartialStream<S>
where
S: RangeStreamOnce,
{
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
self.0.uncons_range(size)
}
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while(f)
}
fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while1(f)
}
#[inline]
fn distance(&self, end: &Self::Checkpoint) -> usize {
self.0.distance(end)
}
#[inline]
fn range(&self) -> Self::Range {
self.0.range()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
#[repr(transparent)]
pub struct CompleteStream<S>(pub S);
impl<S> From<S> for CompleteStream<S> {
fn from(t: S) -> Self {
CompleteStream(t)
}
}
impl<'s, S> From<&'s mut S> for &'s mut CompleteStream<S> {
fn from(t: &'s mut S) -> Self {
unsafe { &mut *(t as *mut S as *mut CompleteStream<S>) }
}
}
impl<S> Positioned for CompleteStream<S>
where
S: Positioned,
{
#[inline]
fn position(&self) -> Self::Position {
self.0.position()
}
}
impl<S> ResetStream for CompleteStream<S>
where
S: ResetStream,
{
type Checkpoint = S::Checkpoint;
#[inline]
fn checkpoint(&self) -> Self::Checkpoint {
self.0.checkpoint()
}
#[inline]
fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), S::Error> {
self.0.reset(checkpoint)
}
}
impl<S> StreamOnce for CompleteStream<S>
where
S: StreamOnce,
{
type Token = S::Token;
type Range = S::Range;
type Position = S::Position;
type Error = S::Error;
#[inline]
fn uncons(&mut self) -> Result<S::Token, StreamErrorFor<Self>> {
self.0.uncons()
}
fn is_partial(&self) -> bool {
false
}
}
impl<S> RangeStreamOnce for CompleteStream<S>
where
S: RangeStreamOnce,
{
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
self.0.uncons_range(size)
}
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while(f)
}
fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while1(f)
}
#[inline]
fn distance(&self, end: &Self::Checkpoint) -> usize {
self.0.distance(end)
}
#[inline]
fn range(&self) -> Self::Range {
self.0.range()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct MaybePartialStream<S>(pub S, pub bool);
impl<S> Positioned for MaybePartialStream<S>
where
S: Positioned,
{
#[inline]
fn position(&self) -> Self::Position {
self.0.position()
}
}
impl<S> ResetStream for MaybePartialStream<S>
where
S: ResetStream,
{
type Checkpoint = S::Checkpoint;
#[inline]
fn checkpoint(&self) -> Self::Checkpoint {
self.0.checkpoint()
}
#[inline]
fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), S::Error> {
self.0.reset(checkpoint)
}
}
impl<S> StreamOnce for MaybePartialStream<S>
where
S: StreamOnce,
{
type Token = S::Token;
type Range = S::Range;
type Position = S::Position;
type Error = S::Error;
#[inline]
fn uncons(&mut self) -> Result<S::Token, StreamErrorFor<Self>> {
self.0.uncons()
}
fn is_partial(&self) -> bool {
self.1
}
}
impl<S> RangeStreamOnce for MaybePartialStream<S>
where
S: RangeStreamOnce,
{
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
self.0.uncons_range(size)
}
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while(f)
}
fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
self.0.uncons_while1(f)
}
#[inline]
fn distance(&self, end: &Self::Checkpoint) -> usize {
self.0.distance(end)
}
#[inline]
fn range(&self) -> Self::Range {
self.0.range()
}
}
#[derive(Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct SliceStream<'a, T>(pub &'a [T]);
impl<'a, T> Clone for SliceStream<'a, T> {
fn clone(&self) -> SliceStream<'a, T> {
SliceStream(self.0)
}
}
impl<'a, T> Positioned for SliceStream<'a, T>
where
T: PartialEq + 'a,
{
#[inline]
fn position(&self) -> Self::Position {
PointerOffset::new(self.0.as_ptr() as usize)
}
}
impl<'a, T> StreamOnce for SliceStream<'a, T>
where
T: PartialEq + 'a,
{
type Token = &'a T;
type Range = &'a [T];
type Position = PointerOffset<[T]>;
type Error = UnexpectedParse;
#[inline]
fn uncons(&mut self) -> Result<&'a T, StreamErrorFor<Self>> {
match self.0.split_first() {
Some((first, rest)) => {
self.0 = rest;
Ok(first)
}
None => Err(UnexpectedParse::Eoi),
}
}
}
fn slice_uncons_while_ref<'a, T, F>(slice: &mut &'a [T], mut i: usize, mut f: F) -> &'a [T]
where
F: FnMut(&'a T) -> bool,
{
let len = slice.len();
let mut found = false;
macro_rules! check {
() => {
if !f(unsafe { slice.get_unchecked(i) }) {
found = true;
break;
}
i += 1;
};
}
while len - i >= 8 {
check!();
check!();
check!();
check!();
check!();
check!();
check!();
check!();
}
if !found {
while let Some(c) = slice.get(i) {
if !f(c) {
break;
}
i += 1;
}
}
let (result, remaining) = slice.split_at(i);
*slice = remaining;
result
}
impl<'a, T> RangeStreamOnce for SliceStream<'a, T>
where
T: PartialEq + 'a,
{
#[inline]
fn uncons_range(&mut self, size: usize) -> Result<&'a [T], StreamErrorFor<Self>> {
if size <= self.0.len() {
let (range, rest) = self.0.split_at(size);
self.0 = rest;
Ok(range)
} else {
Err(UnexpectedParse::Eoi)
}
}
#[inline]
fn uncons_while<F>(&mut self, f: F) -> Result<&'a [T], StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
Ok(slice_uncons_while_ref(&mut self.0, 0, f))
}
#[inline]
fn uncons_while1<F>(&mut self, mut f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
where
F: FnMut(Self::Token) -> bool,
{
if !self.0.first().map_or(false, &mut f) {
return PeekErr(Tracked::from(UnexpectedParse::Unexpected));
}
CommitOk(slice_uncons_while_ref(&mut self.0, 1, f))
}
#[inline]
fn distance(&self, end: &Self) -> usize {
end.0.len() - self.0.len()
}
fn range(&self) -> Self::Range {
self.0
}
}
#[derive(Copy, Clone, Debug)]
pub struct IteratorStream<Input>(Input);
impl<Input> IteratorStream<Input>
where
Input: Iterator,
{
pub fn new<T>(iter: T) -> IteratorStream<Input>
where
T: IntoIterator<IntoIter = Input, Item = Input::Item>,
{
IteratorStream(iter.into_iter())
}
}
impl<Input> Iterator for IteratorStream<Input>
where
Input: Iterator,
{
type Item = Input::Item;
fn next(&mut self) -> Option<Input::Item> {
self.0.next()
}
}
impl<Input: Iterator> StreamOnce for IteratorStream<Input>
where
Input::Item: Clone + PartialEq,
{
type Token = Input::Item;
type Range = Input::Item;
type Position = ();
type Error = UnexpectedParse;
#[inline]
fn uncons(&mut self) -> Result<Self::Token, StreamErrorFor<Self>> {
match self.next() {
Some(x) => Ok(x),
None => Err(UnexpectedParse::Eoi),
}
}
}
pub struct PointerOffset<T: ?Sized>(pub usize, PhantomData<T>);
impl<T: ?Sized> Clone for PointerOffset<T> {
fn clone(&self) -> Self {
PointerOffset::new(self.0)
}
}
impl<T: ?Sized> Copy for PointerOffset<T> {}
impl<T: ?Sized> Default for PointerOffset<T> {
fn default() -> Self {
PointerOffset::new(0)
}
}
impl<T: ?Sized> PartialEq for PointerOffset<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T: ?Sized> Eq for PointerOffset<T> {}
impl<T: ?Sized> PartialOrd for PointerOffset<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T: ?Sized> Ord for PointerOffset<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<T> fmt::Debug for PointerOffset<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<T> fmt::Display for PointerOffset<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PointerOffset({:?})", self.0 as *const ())
}
}
impl<T> PointerOffset<T>
where
T: ?Sized,
{
pub fn new(offset: usize) -> Self {
PointerOffset(offset, PhantomData)
}
pub fn translate_position(mut self, initial_slice: &T) -> usize {
self.0 -= initial_slice as *const T as *const () as usize;
self.0
}
}
pub fn decode<Input, P>(
mut parser: P,
mut input: &mut Input,
partial_state: &mut P::PartialState,
) -> Result<(Option<P::Output>, usize), <Input as StreamOnce>::Error>
where
P: Parser<Input>,
Input: RangeStream,
{
let start = input.checkpoint();
match parser.parse_with_state(&mut input, partial_state) {
Ok(message) => Ok((Some(message), input.distance(&start))),
Err(err) => {
if input.is_partial() && err.is_unexpected_end_of_input() {
Ok((None, input.distance(&start)))
} else {
Err(err)
}
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[macro_export]
macro_rules! decode {
($decoder: expr, $read: expr, $parser: expr $(,)?) => {
$crate::decode!($decoder, $read, $parser, |input, _position| input, |x| x)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr $(,)?) => {
$crate::decode!($decoder, $read, $parser, $input_stream, |x| x)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr, $post_decode: expr $(,)?) => {
match $decoder {
ref mut decoder => match $read {
ref mut read => 'outer: loop {
let (opt, removed) = {
let (state, position, buffer, end_of_input) = decoder.__inner();
let buffer =
$crate::stream::buf_reader::CombineBuffer::buffer(buffer, read);
let mut stream = $crate::stream::call_with2(
$crate::stream::MaybePartialStream(buffer, !end_of_input),
*position,
$input_stream,
);
let result = $crate::stream::decode($parser, &mut stream, state);
*position = $crate::stream::Positioned::position(&stream);
$crate::stream::call_with(stream, $post_decode);
match result {
Ok(x) => x,
Err(err) => {
break 'outer Err($crate::stream::decoder::Error::Parse(err))
}
}
};
decoder.advance(&mut *read, removed);
if let Some(v) = opt {
break 'outer Ok(v);
}
match decoder.__before_parse(&mut *read) {
Ok(x) => x,
Err(error) => {
break 'outer Err($crate::stream::decoder::Error::Io {
error,
position: Clone::clone(decoder.position()),
})
}
};
},
},
}
};
}
#[cfg(feature = "futures-io-03")]
#[cfg_attr(docsrs, doc(cfg(feature = "futures-io-03")))]
#[macro_export]
macro_rules! decode_futures_03 {
($decoder: expr, $read: expr, $parser: expr) => {
$crate::decode_futures_03!($decoder, $read, $parser, |x| x $(,)?)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr $(,)?) => {
$crate::decode_futures_03!($decoder, $read, $parser, $input_stream, |x| x)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr, $post_decode: expr $(,)?) => {
match $decoder {
ref mut decoder => match $read {
ref mut read => 'outer: loop {
let (opt, removed) = {
let (state, position, buffer, end_of_input) = decoder.__inner();
let buffer =
$crate::stream::buf_reader::CombineBuffer::buffer(buffer, &*read);
let mut stream = $crate::stream::call_with2(
$crate::stream::MaybePartialStream(buffer, !end_of_input),
*position,
$input_stream,
);
let result = $crate::stream::decode($parser, &mut stream, state);
*position = $crate::stream::Positioned::position(&stream);
$crate::stream::call_with(stream, $post_decode);
match result {
Ok(x) => x,
Err(err) => break 'outer Err($crate::stream::decoder::Error::Parse(err)),
}
};
decoder.advance_pin(std::pin::Pin::new(&mut *read), removed);
if let Some(v) = opt {
break 'outer Ok(v);
}
match decoder.__before_parse_async(std::pin::Pin::new(&mut *read)).await {
Ok(_) => (),
Err(error) => {
break 'outer Err($crate::stream::decoder::Error::Io {
error,
position: Clone::clone(decoder.position()),
})
}
};
}
}
}
};
}
#[cfg(feature = "tokio-02")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio-02")))]
#[macro_export]
macro_rules! decode_tokio_02 {
($decoder: expr, $read: expr, $parser: expr $(,)?) => {
$crate::decode_tokio_02!($decoder, $read, $parser, |input, _position| input)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr $(,)?) => {
$crate::decode_tokio_02!($decoder, $read, $parser, $input_stream, |x| x)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr, $post_decode: expr $(,)?) => {
match $decoder {
ref mut decoder => match $read {
ref mut read => 'outer: loop {
let (opt, removed) = {
let (state, position, buffer, end_of_input) = decoder.__inner();
let buffer =
$crate::stream::buf_reader::CombineBuffer::buffer(buffer, &*read);
let mut stream = $crate::stream::call_with2(
$crate::stream::MaybePartialStream(buffer, !end_of_input),
*position,
$input_stream,
);
let result = $crate::stream::decode($parser, &mut stream, state);
*position = $crate::stream::Positioned::position(&stream);
$crate::stream::call_with(stream, $post_decode);
match result {
Ok(x) => x,
Err(err) => {
break 'outer Err($crate::stream::decoder::Error::Parse(err))
}
}
};
decoder.advance_pin(std::pin::Pin::new(read), removed);
if let Some(v) = opt {
break 'outer Ok(v);
}
match decoder
.__before_parse_tokio_02(std::pin::Pin::new(&mut *read))
.await
{
Ok(x) => x,
Err(error) => {
break 'outer Err($crate::stream::decoder::Error::Io {
error,
position: Clone::clone(decoder.position()),
})
}
};
},
},
}
};
}
#[cfg(feature = "tokio-03")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio-03")))]
#[macro_export]
macro_rules! decode_tokio_03 {
($decoder: expr, $read: expr, $parser: expr $(,)?) => {
$crate::decode_tokio_03!($decoder, $read, $parser, |input, _position| input)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr $(,)?) => {
$crate::decode_tokio_03!($decoder, $read, $parser, $input_stream, |x| x)
};
($decoder: expr, $read: expr, $parser: expr, $input_stream: expr, $post_decode: expr $(,)?) => {
match $decoder {
ref mut decoder => match $read {
ref mut read => 'outer: loop {
let (opt, removed) = {
let (state, position, buffer, end_of_input) = decoder.__inner();
let buffer =
$crate::stream::buf_reader::CombineBuffer::buffer(buffer, &*read);
let mut stream = $crate::stream::call_with2(
$crate::stream::MaybePartialStream(buffer, !end_of_input),
*position,
$input_stream,
);
let result = $crate::stream::decode($parser, &mut stream, state);
*position = $crate::stream::Positioned::position(&stream);
$crate::stream::call_with(stream, $post_decode);
match result {
Ok(x) => x,
Err(err) => {
break 'outer Err($crate::stream::decoder::Error::Parse(err))
}
}
};
decoder.advance_pin(std::pin::Pin::new(read), removed);
if let Some(v) = opt {
break 'outer Ok(v);
}
match decoder
.__before_parse_tokio_03(std::pin::Pin::new(&mut *read))
.await
{
Ok(x) => x,
Err(error) => {
break 'outer Err($crate::stream::decoder::Error::Io {
error,
position: Clone::clone(decoder.position()),
})
}
};
},
},
}
};
}
#[doc(hidden)]
pub fn call_with2<F, A, B, R>(a: A, b: B, f: F) -> R
where
F: FnOnce(A, B) -> R,
{
f(a, b)
}
#[doc(hidden)]
pub fn call_with<F, A, R>(a: A, f: F) -> R
where
F: FnOnce(A) -> R,
{
f(a)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[inline]
fn uncons_range_at_end() {
assert_eq!("".uncons_range(0), Ok(""));
assert_eq!("123".uncons_range(3), Ok("123"));
assert_eq!((&[1][..]).uncons_range(1), Ok(&[1][..]));
let s: &[u8] = &[];
assert_eq!(SliceStream(s).uncons_range(0), Ok(&[][..]));
}
#[test]
fn larger_than_1_byte_items_return_correct_distance() {
let mut input = &[123i32, 0i32][..];
let before = input.checkpoint();
assert_eq!(input.distance(&before), 0);
input.uncons().unwrap();
assert_eq!(input.distance(&before), 1);
input.uncons().unwrap();
assert_eq!(input.distance(&before), 2);
input.reset(before.clone()).unwrap();
assert_eq!(input.distance(&before), 0);
}
}