use lib::fmt;
#[cfg(feature = "std")]
use std::error::Error as StdError;
use self::FastResult::*;
use ErrorOffset;
use stream::StreamOnce;
#[macro_export]
#[doc(hidden)]
macro_rules! ctry {
($result:expr) => {
match $result {
$crate::error::FastResult::ConsumedOk(x) => (x, $crate::error::Consumed::Consumed(())),
$crate::error::FastResult::EmptyOk(x) => (x, $crate::error::Consumed::Empty(())),
$crate::error::FastResult::ConsumedErr(err) => {
return $crate::error::FastResult::ConsumedErr(err.into())
}
$crate::error::FastResult::EmptyErr(err) => {
return $crate::error::FastResult::EmptyErr(err.into())
}
}
};
}
#[derive(Clone, Debug)]
pub enum Info<T, R> {
Token(T),
Range(R),
Borrowed(&'static str),
}
impl<R> From<char> for Info<char, R> {
fn from(s: char) -> Info<char, R> {
Info::Token(s)
}
}
impl<T, R> From<&'static str> for Info<T, R> {
fn from(s: &'static str) -> Info<T, R> {
Info::Borrowed(s)
}
}
impl<R> From<u8> for Info<u8, R> {
fn from(s: u8) -> Info<u8, R> {
Info::Token(s)
}
}
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum Consumed<T> {
Consumed(T),
Empty(T),
}
impl<T> AsMut<T> for Consumed<T> {
fn as_mut(&mut self) -> &mut T {
match *self {
Consumed::Empty(ref mut t) | Consumed::Consumed(ref mut t) => t,
}
}
}
impl<T> AsRef<T> for Consumed<T> {
fn as_ref(&self) -> &T {
match *self {
Consumed::Empty(ref t) | Consumed::Consumed(ref t) => t,
}
}
}
impl<T> Consumed<T> {
pub fn is_empty(&self) -> bool {
match *self {
Consumed::Empty(_) => true,
Consumed::Consumed(_) => false,
}
}
pub fn into_inner(self) -> T {
match self {
Consumed::Empty(x) | Consumed::Consumed(x) => x,
}
}
pub fn into_consumed(self) -> Consumed<T> {
Consumed::Consumed(self.into_inner())
}
pub fn into_empty(self) -> Consumed<T> {
Consumed::Empty(self.into_inner())
}
pub fn map<F, U>(self, f: F) -> Consumed<U>
where
F: FnOnce(T) -> U,
{
match self {
Consumed::Empty(x) => Consumed::Empty(f(x)),
Consumed::Consumed(x) => Consumed::Consumed(f(x)),
}
}
pub fn merge(&self, current: Consumed<T>) -> Consumed<T> {
match *self {
Consumed::Empty(_) => current,
Consumed::Consumed(_) => current.into_consumed(),
}
}
pub fn combine<F, U, E>(self, f: F) -> ParseResult2<U, E>
where
F: FnOnce(T) -> ParseResult2<U, E>,
{
match self {
Consumed::Consumed(x) => match f(x) {
Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
y => y,
},
Consumed::Empty(x) => f(x),
}
}
pub fn combine_consumed<F, U, E>(self, f: F) -> FastResult<U, E>
where
F: FnOnce(T) -> FastResult<U, E>,
{
use self::FastResult::*;
match self {
Consumed::Consumed(x) => match f(x) {
EmptyOk(v) => ConsumedOk(v),
EmptyErr(err) => ConsumedErr(err.error),
y => y,
},
Consumed::Empty(x) => f(x),
}
}
}
pub type ParseResult<O, I> = Result<(O, Consumed<()>), Consumed<Tracked<<I as StreamOnce>::Error>>>;
pub type ParseResult2<O, E> = Result<(O, Consumed<()>), Consumed<Tracked<E>>>;
pub trait StreamError<Item, Range>: Sized + PartialEq {
fn unexpected_token(token: Item) -> Self;
fn unexpected_range(token: Range) -> Self;
fn unexpected_message<T>(msg: T) -> Self
where
T: fmt::Display;
fn unexpected(info: Info<Item, Range>) -> Self {
match info {
Info::Token(b) => Self::unexpected_token(b),
Info::Range(b) => Self::unexpected_range(b),
Info::Borrowed(b) => Self::unexpected_static_message(b),
}
}
fn unexpected_static_message(msg: &'static str) -> Self {
Self::unexpected_message(msg)
}
fn expected_token(token: Item) -> Self;
fn expected_range(token: Range) -> Self;
fn expected_message<T>(msg: T) -> Self
where
T: fmt::Display;
fn expected(info: Info<Item, Range>) -> Self {
match info {
Info::Token(b) => Self::expected_token(b),
Info::Range(b) => Self::expected_range(b),
Info::Borrowed(b) => Self::expected_static_message(b),
}
}
fn expected_static_message(msg: &'static str) -> Self {
Self::expected_message(msg)
}
fn message_token(token: Item) -> Self;
fn message_range(token: Range) -> Self;
fn message_message<T>(msg: T) -> Self
where
T: fmt::Display;
fn message_static_message(msg: &'static str) -> Self {
Self::message_message(msg)
}
fn message(info: Info<Item, Range>) -> Self {
match info {
Info::Token(b) => Self::message_token(b),
Info::Range(b) => Self::message_range(b),
Info::Borrowed(b) => Self::message_static_message(b),
}
}
#[cfg(feature = "std")]
fn other<E>(err: E) -> Self
where
E: StdError + Send + Sync + 'static,
{
Self::message_message(err)
}
fn end_of_input() -> Self {
Self::unexpected_static_message("end of input")
}
fn into_other<T>(self) -> T
where
T: StreamError<Item, Range>;
}
pub trait ParseError<Item, Range, Position>: Sized + PartialEq {
type StreamError: StreamError<Item, Range>;
fn empty(position: Position) -> Self;
fn from_error(position: Position, err: Self::StreamError) -> Self;
fn set_position(&mut self, position: Position);
fn merge(self, other: Self) -> Self {
other
}
fn add(&mut self, err: Self::StreamError);
fn add_expected(&mut self, info: Info<Item, Range>) {
self.add(Self::StreamError::expected(info))
}
fn add_unexpected(&mut self, info: Info<Item, Range>) {
self.add(Self::StreamError::unexpected(info))
}
fn add_message(&mut self, info: Info<Item, Range>) {
self.add(Self::StreamError::message(info))
}
fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
where
F: FnOnce(&mut Tracked<Self>);
fn clear_expected(&mut self) {}
fn is_unexpected_end_of_input(&self) -> bool;
fn into_other<T>(self) -> T
where
T: ParseError<Item, Range, Position>;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum UnexpectedParse {
Eoi,
Unexpected,
}
impl fmt::Display for UnexpectedParse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::UnexpectedParse::*;
write!(
f,
"{}",
match *self {
Unexpected => "unexpected parse",
Eoi => "unexpected end of input",
}
)
}
}
impl<Item, Range> StreamError<Item, Range> for UnexpectedParse {
#[inline]
fn unexpected_token(_: Item) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn unexpected_range(_: Range) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn unexpected_message<T>(_: T) -> Self
where
T: fmt::Display,
{
UnexpectedParse::Unexpected
}
#[inline]
fn expected_token(_: Item) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn expected_range(_: Range) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn expected_message<T>(_: T) -> Self
where
T: fmt::Display,
{
UnexpectedParse::Unexpected
}
#[inline]
fn message_message<T>(_: T) -> Self
where
T: fmt::Display,
{
UnexpectedParse::Unexpected
}
#[inline]
fn message_token(_: Item) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn message_range(_: Range) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn end_of_input() -> Self {
UnexpectedParse::Eoi
}
#[inline]
fn into_other<T>(self) -> T
where
T: StreamError<Item, Range>,
{
match self {
UnexpectedParse::Unexpected => T::unexpected_static_message("parse"),
UnexpectedParse::Eoi => T::end_of_input(),
}
}
}
impl<Item, Range, Position> ParseError<Item, Range, Position> for UnexpectedParse
where
Position: Default,
{
type StreamError = Self;
#[inline]
fn empty(_position: Position) -> Self {
UnexpectedParse::Unexpected
}
#[inline]
fn from_error(_: Position, err: Self::StreamError) -> Self {
err
}
#[inline]
fn set_position(&mut self, _position: Position) {}
#[inline]
fn add(&mut self, err: Self::StreamError) {
*self = match (*self, err) {
(UnexpectedParse::Eoi, _) => UnexpectedParse::Eoi,
(_, err) => err,
};
}
#[inline]
fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
where
F: FnOnce(&mut Tracked<Self>),
{
f(self_);
self_.error = info;
}
fn is_unexpected_end_of_input(&self) -> bool {
*self == UnexpectedParse::Eoi
}
#[inline]
fn into_other<T>(self) -> T
where
T: ParseError<Item, Range, Position>,
{
T::from_error(Position::default(), StreamError::into_other(self))
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StringStreamError {
UnexpectedParse,
Eoi,
CharacterBoundary,
}
pub(crate) const CHAR_BOUNDARY_ERROR_MESSAGE: &str = "unexpected slice on character boundary";
impl fmt::Display for StringStreamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::StringStreamError::*;
write!(
f,
"{}",
match *self {
UnexpectedParse => "unexpected parse",
Eoi => "unexpected end of input",
CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
}
)
}
}
impl<Item, Range> StreamError<Item, Range> for StringStreamError {
#[inline]
fn unexpected_token(_: Item) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn unexpected_range(_: Range) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn unexpected_message<T>(_msg: T) -> Self
where
T: fmt::Display,
{
StringStreamError::UnexpectedParse
}
#[inline]
fn expected_token(_: Item) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn expected_range(_: Range) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn expected_message<T>(_: T) -> Self
where
T: fmt::Display,
{
StringStreamError::UnexpectedParse
}
#[inline]
fn message_message<T>(_: T) -> Self
where
T: fmt::Display,
{
StringStreamError::UnexpectedParse
}
#[inline]
fn message_token(_: Item) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn message_range(_: Range) -> Self {
StringStreamError::UnexpectedParse
}
fn message_static_message(msg: &'static str) -> Self {
if msg == CHAR_BOUNDARY_ERROR_MESSAGE {
StringStreamError::CharacterBoundary
} else {
StringStreamError::UnexpectedParse
}
}
#[inline]
fn end_of_input() -> Self {
StringStreamError::Eoi
}
#[inline]
fn into_other<T>(self) -> T
where
T: StreamError<Item, Range>,
{
let msg = match self {
StringStreamError::CharacterBoundary => CHAR_BOUNDARY_ERROR_MESSAGE,
StringStreamError::UnexpectedParse => "parse",
StringStreamError::Eoi => return T::end_of_input(),
};
T::unexpected_static_message(msg)
}
}
impl<Item, Range, Position> ParseError<Item, Range, Position> for StringStreamError
where
Position: Default,
{
type StreamError = Self;
#[inline]
fn empty(_position: Position) -> Self {
StringStreamError::UnexpectedParse
}
#[inline]
fn from_error(_: Position, err: Self::StreamError) -> Self {
err
}
#[inline]
fn set_position(&mut self, _position: Position) {}
#[inline]
fn add(&mut self, err: Self::StreamError) {
*self = match (*self, err) {
(StringStreamError::Eoi, _) => StringStreamError::Eoi,
(_, err) => err,
};
}
#[inline]
fn set_expected<F>(self_: &mut Tracked<Self>, info: Self::StreamError, f: F)
where
F: FnOnce(&mut Tracked<Self>),
{
f(self_);
self_.error = info;
}
fn is_unexpected_end_of_input(&self) -> bool {
*self == StringStreamError::Eoi
}
#[inline]
fn into_other<T>(self) -> T
where
T: ParseError<Item, Range, Position>,
{
T::from_error(Position::default(), StreamError::into_other(self))
}
}
#[derive(Clone, PartialEq, Debug, Copy)]
pub struct Tracked<E> {
pub error: E,
#[doc(hidden)]
pub offset: ErrorOffset,
}
impl<E> From<E> for Tracked<E> {
fn from(error: E) -> Self {
Tracked {
error: error,
offset: ErrorOffset(1),
}
}
}
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum FastResult<T, E> {
ConsumedOk(T),
EmptyOk(T),
ConsumedErr(E),
EmptyErr(Tracked<E>),
}
impl<T, E> FastResult<T, E> {
#[inline]
pub fn is_ok(&self) -> bool {
match *self {
ConsumedOk(_) | EmptyOk(_) => true,
ConsumedErr(_) | EmptyErr(_) => false,
}
}
pub fn as_ref(&self) -> FastResult<&T, &E> {
match *self {
ConsumedOk(ref t) => ConsumedOk(t),
EmptyOk(ref t) => EmptyOk(t),
ConsumedErr(ref e) => ConsumedErr(e),
EmptyErr(ref e) => EmptyErr(Tracked {
error: &e.error,
offset: e.offset,
}),
}
}
pub fn and_then<F, T2>(self, f: F) -> F::Output
where
F: FnOnce(T) -> FastResult<T2, E>,
{
match self {
ConsumedOk(t) => match f(t) {
ConsumedOk(t2) | EmptyOk(t2) => ConsumedOk(t2),
EmptyErr(e) => ConsumedErr(e.error),
ConsumedErr(e) => ConsumedErr(e),
},
EmptyOk(t) => f(t),
ConsumedErr(e) => ConsumedErr(e),
EmptyErr(e) => EmptyErr(e),
}
}
pub fn map_err<F, E2>(self, f: F) -> FastResult<T, F::Output>
where
F: FnOnce(E) -> E2,
{
match self {
ConsumedOk(t) => ConsumedOk(t),
EmptyOk(t) => EmptyOk(t),
ConsumedErr(e) => ConsumedErr(f(e)),
EmptyErr(e) => EmptyErr(Tracked {
error: f(e.error),
offset: e.offset,
}),
}
}
}
impl<T, E> FastResult<T, E> {
pub fn map<F, T2>(self, f: F) -> FastResult<F::Output, E>
where
F: FnOnce(T) -> T2,
{
match self {
ConsumedOk(t) => ConsumedOk(f(t)),
EmptyOk(t) => EmptyOk(f(t)),
ConsumedErr(e) => ConsumedErr(e),
EmptyErr(e) => EmptyErr(e),
}
}
}
pub type ConsumedResult<O, I> = FastResult<O, <I as StreamOnce>::Error>;
impl<T, E> Into<Result<Consumed<T>, Consumed<Tracked<E>>>> for FastResult<T, E> {
#[inline(always)]
fn into(self) -> Result<Consumed<T>, Consumed<Tracked<E>>> {
match self {
ConsumedOk(t) => Ok(Consumed::Consumed(t)),
EmptyOk(t) => Ok(Consumed::Empty(t)),
ConsumedErr(e) => Err(Consumed::Consumed(e.into())),
EmptyErr(e) => Err(Consumed::Empty(e)),
}
}
}
impl<O, E> Into<ParseResult2<O, E>> for FastResult<O, E> {
#[inline(always)]
fn into(self) -> ParseResult2<O, E> {
use self::FastResult::*;
match self {
ConsumedOk(t) => Ok((t, Consumed::Consumed(()))),
EmptyOk(t) => Ok((t, Consumed::Empty(()))),
ConsumedErr(e) => Err(Consumed::Consumed(e.into())),
EmptyErr(e) => Err(Consumed::Empty(e)),
}
}
}
impl<O, E> From<ParseResult2<O, E>> for FastResult<O, E> {
#[inline(always)]
fn from(result: ParseResult2<O, E>) -> FastResult<O, E> {
use self::FastResult::*;
match result {
Ok((t, Consumed::Consumed(()))) => ConsumedOk(t),
Ok((t, Consumed::Empty(()))) => EmptyOk(t),
Err(Consumed::Consumed(e)) => ConsumedErr(e.error),
Err(Consumed::Empty(e)) => EmptyErr(e),
}
}
}
#[cfg(all(feature = "std", test))]
mod tests_std {
use Parser;
#[derive(Clone, PartialEq, Debug)]
struct CloneOnly {
s: String,
}
#[test]
fn parse_clone_but_not_copy() {
let input = &[
CloneOnly { s: "x".to_string() },
CloneOnly { s: "y".to_string() },
][..];
let result =
::parser::range::take_while(|c: CloneOnly| c.s == "x".to_string()).parse(input);
assert_eq!(
result,
Ok((
&[CloneOnly { s: "x".to_string() }][..],
&[CloneOnly { s: "y".to_string() }][..]
))
);
}
}