diff --git a/src/error.rs b/src/error.rs index 18473ae5..066a5f1f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -752,22 +752,47 @@ impl crate::lib::std::fmt::Display for StrContextValue { } } +/// Used by [`LongestMatch`] to compare checkpoint positions +pub trait AsOrd { + /// The type used to compare checkpoint positions + type Ord: Ord + Clone + crate::lib::std::fmt::Debug; + + /// Get comparable value + fn as_ord(&self) -> Self::Ord; +} + +impl<'a, T> AsOrd for &'a [T] { + type Ord = *const T; + + fn as_ord(&self) -> Self::Ord { + self.as_ptr() + } +} + +impl<'a> AsOrd for &'a str { + type Ord = *const u8; + + fn as_ord(&self) -> Self::Ord { + self.as_ptr() + } +} + /// Collect context of the longest matching parser while backtracking on errors #[derive(Clone, Debug)] pub struct LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: MergeContext, { - checkpoint: I::Checkpoint, + ord: <::Checkpoint as AsOrd>::Ord, inner: E, } impl LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: MergeContext, { /// Extract the error for the longest matching parser @@ -780,24 +805,24 @@ where impl ParserError for LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: ParserError + MergeContext, { #[inline] fn from_error_kind(input: &I, kind: ErrorKind) -> Self { Self { - checkpoint: input.checkpoint(), + ord: input.checkpoint().as_ord(), inner: E::from_error_kind(input, kind), } } #[inline] fn append(mut self, input: &I, kind: ErrorKind) -> Self { - let checkpoint = input.checkpoint(); - match checkpoint.cmp(&self.checkpoint) { + let checkpoint = input.checkpoint().as_ord(); + match checkpoint.cmp(&self.ord) { core::cmp::Ordering::Less => self, core::cmp::Ordering::Greater => { - self.checkpoint = checkpoint; + self.ord = checkpoint; self.clear_context(); self.inner = self.inner.append(input, kind); self @@ -818,19 +843,19 @@ where impl AddContext for LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: AddContext + MergeContext, { #[inline] fn add_context(mut self, input: &I, ctx: C) -> Self { - let checkpoint = input.checkpoint(); - match checkpoint.cmp(&self.checkpoint) { + let ord = input.checkpoint().as_ord(); + match ord.cmp(&self.ord) { core::cmp::Ordering::Less => {} core::cmp::Ordering::Equal => { self.inner = self.inner.add_context(input, ctx); } core::cmp::Ordering::Greater => { - self.checkpoint = checkpoint; + self.ord = ord; self.inner.clear_context(); self.inner = self.inner.add_context(input, ctx); } @@ -842,11 +867,11 @@ where impl MergeContext for LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, { #[inline] fn merge_context(mut self, other: Self) -> Self { - match other.checkpoint.cmp(&self.checkpoint) { + match other.ord.cmp(&self.ord) { core::cmp::Ordering::Less => self, core::cmp::Ordering::Greater => other, core::cmp::Ordering::Equal => { @@ -860,13 +885,13 @@ where impl FromExternalError for LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: FromExternalError + MergeContext, { #[inline] fn from_external_error(input: &I, kind: ErrorKind, e: EX) -> Self { Self { - checkpoint: input.checkpoint(), + ord: input.checkpoint().as_ord(), inner: E::from_external_error(input, kind, e), } } @@ -875,7 +900,7 @@ where impl crate::lib::std::fmt::Display for LongestMatch where I: Stream, - ::Checkpoint: Ord, + ::Checkpoint: AsOrd, E: crate::lib::std::fmt::Display + MergeContext, { fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result { diff --git a/src/error/tests.rs b/src/error/tests.rs index 5c9fccc8..11b73cbb 100644 --- a/src/error/tests.rs +++ b/src/error/tests.rs @@ -2,12 +2,9 @@ use super::*; mod longest_match { use super::*; - use crate::{ - combinator::{alt, eof, terminated}, - Located, - }; + use crate::combinator::{alt, eof, terminated}; - type Input<'a> = Located<&'a str>; + type Input<'a> = &'a str; type Error<'a> = LongestMatch, ContextError<&'static str>>; type PResult<'a, O> = crate::error::PResult>; @@ -37,7 +34,7 @@ mod longest_match { fn parser<'a>(input: &mut Input<'a>) -> PResult<'a, &'a str> { alt((syms("abcd"), syms("abc"), syms("ab"))).parse_next(input) } - let ctx = expect_err(parser(&mut Input::new("abcde"))); + let ctx = expect_err(parser(&mut "abcde")); assert_eq!(ctx, vec!["abcd"]); } @@ -47,24 +44,23 @@ mod longest_match { alt((syms("abcd"), syms("abc"), syms("def"), syms("defg"))).parse_next(input) } - let ctx = expect_err(parser(&mut Input::new("abd"))); + let ctx = expect_err(parser(&mut "abd")); assert_eq!(ctx, vec!["abcd", "abc"]); - let ctx = expect_err(parser(&mut Input::new("deg"))); + let ctx = expect_err(parser(&mut "deg")); assert_eq!(ctx, vec!["def", "defg"]); } #[test] - #[ignore] fn multi_longest_match_eof() { fn parser<'a>(input: &mut Input<'a>) -> PResult<'a, &'a str> { alt((syms("abcd"), syms("abc"), syms("def"), syms("defg"))).parse_next(input) } - let ctx = expect_err(parser(&mut Input::new("ab"))); + let ctx = expect_err(parser(&mut "ab")); assert_eq!(ctx, vec!["abcd", "abc"]); - let ctx = expect_err(parser(&mut Input::new("de"))); + let ctx = expect_err(parser(&mut "de")); assert_eq!(ctx, vec!["def", "defg"]); } } diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 2b219f20..18063664 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -13,7 +13,7 @@ use core::hash::BuildHasher; use core::num::NonZeroUsize; use crate::ascii::Caseless as AsciiCaseless; -use crate::error::Needed; +use crate::error::{AsOrd, Needed}; use crate::lib::std::iter::{Cloned, Enumerate}; use crate::lib::std::slice::Iter; use crate::lib::std::str::from_utf8; @@ -2200,6 +2200,14 @@ where #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Checkpoint(T); +impl AsOrd for Checkpoint { + type Ord = T::Ord; + + fn as_ord(&self) -> Self::Ord { + self.0.as_ord() + } +} + /// A range bounded inclusively for counting parses performed #[derive(PartialEq, Eq)] pub struct Range {