aboutsummaryrefslogtreecommitdiff
path: root/src/ascii/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ascii/mod.rs')
-rw-r--r--src/ascii/mod.rs90
1 files changed, 71 insertions, 19 deletions
diff --git a/src/ascii/mod.rs b/src/ascii/mod.rs
index 8b3119f..8e6a480 100644
--- a/src/ascii/mod.rs
+++ b/src/ascii/mod.rs
@@ -10,17 +10,46 @@ use crate::lib::std::ops::{Add, Shl};
use crate::combinator::alt;
use crate::combinator::cut_err;
use crate::combinator::opt;
+use crate::combinator::trace;
use crate::error::ParserError;
use crate::error::{ErrMode, ErrorKind, Needed};
use crate::stream::{AsBStr, AsChar, ParseSlice, Stream, StreamIsPartial};
use crate::stream::{Compare, CompareResult};
use crate::token::one_of;
-use crate::token::take_till0;
+use crate::token::take_till;
use crate::token::take_while;
-use crate::trace::trace;
use crate::PResult;
use crate::Parser;
+/// Mark a value as case-insensitive for ASCII characters
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}};
+/// # use winnow::ascii::Caseless;
+///
+/// fn parser<'s>(s: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
+/// Caseless("hello").parse_next(s)
+/// }
+///
+/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser.parse_peek("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser.parse_peek("HeLlo, World!"), Ok((", World!", "HeLlo")));
+/// assert_eq!(parser.parse_peek("Some"), Err(ErrMode::Backtrack(InputError::new("Some", ErrorKind::Tag))));
+/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
+/// ```
+#[derive(Copy, Clone, Debug)]
+pub struct Caseless<T>(pub T);
+
+impl Caseless<&str> {
+ /// Get the byte-representation of this case-insensitive value
+ #[inline(always)]
+ pub fn as_bytes(&self) -> Caseless<&[u8]> {
+ Caseless(self.0.as_bytes())
+ }
+}
+
/// Recognizes the string `"\r\n"`.
///
/// *Complete version*: Will return an error if there's not enough input data.
@@ -72,9 +101,9 @@ where
/// ```
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
-/// # use winnow::ascii::not_line_ending;
+/// # use winnow::ascii::till_line_ending;
/// fn parser<'s>(input: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
-/// not_line_ending.parse_next(input)
+/// till_line_ending.parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("ab\r\nc"), Ok(("\r\nc", "ab")));
@@ -89,32 +118,45 @@ where
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
/// # use winnow::Partial;
-/// # use winnow::ascii::not_line_ending;
-/// assert_eq!(not_line_ending::<_, InputError<_>>.parse_peek(Partial::new("ab\r\nc")), Ok((Partial::new("\r\nc"), "ab")));
-/// assert_eq!(not_line_ending::<_, InputError<_>>.parse_peek(Partial::new("abc")), Err(ErrMode::Incomplete(Needed::new(1))));
-/// assert_eq!(not_line_ending::<_, InputError<_>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
-/// assert_eq!(not_line_ending::<_, InputError<_>>.parse_peek(Partial::new("a\rb\nc")), Err(ErrMode::Backtrack(InputError::new(Partial::new("\rb\nc"), ErrorKind::Tag ))));
-/// assert_eq!(not_line_ending::<_, InputError<_>>.parse_peek(Partial::new("a\rbc")), Err(ErrMode::Backtrack(InputError::new(Partial::new("\rbc"), ErrorKind::Tag ))));
+/// # use winnow::ascii::till_line_ending;
+/// assert_eq!(till_line_ending::<_, InputError<_>>.parse_peek(Partial::new("ab\r\nc")), Ok((Partial::new("\r\nc"), "ab")));
+/// assert_eq!(till_line_ending::<_, InputError<_>>.parse_peek(Partial::new("abc")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(till_line_ending::<_, InputError<_>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(till_line_ending::<_, InputError<_>>.parse_peek(Partial::new("a\rb\nc")), Err(ErrMode::Backtrack(InputError::new(Partial::new("\rb\nc"), ErrorKind::Tag ))));
+/// assert_eq!(till_line_ending::<_, InputError<_>>.parse_peek(Partial::new("a\rbc")), Err(ErrMode::Backtrack(InputError::new(Partial::new("\rbc"), ErrorKind::Tag ))));
/// ```
#[inline(always)]
-pub fn not_line_ending<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E>
+pub fn till_line_ending<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E>
where
I: StreamIsPartial,
I: Stream,
I: Compare<&'static str>,
<I as Stream>::Token: AsChar + Clone,
{
- trace("not_line_ending", move |input: &mut I| {
+ trace("till_line_ending", move |input: &mut I| {
if <I as StreamIsPartial>::is_partial_supported() {
- not_line_ending_::<_, _, true>(input)
+ till_line_ending_::<_, _, true>(input)
} else {
- not_line_ending_::<_, _, false>(input)
+ till_line_ending_::<_, _, false>(input)
}
})
.parse_next(input)
}
-fn not_line_ending_<I, E: ParserError<I>, const PARTIAL: bool>(
+/// Deprecated, replaced with [`till_line_ending`]
+#[deprecated(since = "0.5.35", note = "Replaced with `till_line_ending`")]
+#[inline(always)]
+pub fn not_line_ending<I, E: ParserError<I>>(input: &mut I) -> PResult<<I as Stream>::Slice, E>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ I: Compare<&'static str>,
+ <I as Stream>::Token: AsChar + Clone,
+{
+ till_line_ending(input)
+}
+
+fn till_line_ending_<I, E: ParserError<I>, const PARTIAL: bool>(
input: &mut I,
) -> PResult<<I as Stream>::Slice, E>
where
@@ -123,7 +165,7 @@ where
I: Compare<&'static str>,
<I as Stream>::Token: AsChar + Clone,
{
- let res = take_till0(('\r', '\n')).parse_next(input)?;
+ let res = take_till(0.., ('\r', '\n')).parse_next(input)?;
if input.compare("\r") == CompareResult::Ok {
let comp = input.compare("\r\n");
match comp {
@@ -423,7 +465,7 @@ where
///
/// ## Parsing an integer
///
-/// You can use `digit1` in combination with [`Parser::try_map`][crate::Parser::try_map] to parse an integer:
+/// You can use `digit1` in combination with [`Parser::try_map`] to parse an integer:
///
/// ```
/// # use winnow::prelude::*;
@@ -965,6 +1007,7 @@ impl Uint for u128 {
}
}
+/// Deprecated since v0.5.17
impl Uint for i8 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -974,6 +1017,7 @@ impl Uint for i8 {
}
}
+/// Deprecated since v0.5.17
impl Uint for i16 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -983,6 +1027,7 @@ impl Uint for i16 {
}
}
+/// Deprecated since v0.5.17
impl Uint for i32 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -992,6 +1037,7 @@ impl Uint for i32 {
}
}
+/// Deprecated since v0.5.17
impl Uint for i64 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -1001,6 +1047,7 @@ impl Uint for i64 {
}
}
+/// Deprecated since v0.5.17
impl Uint for i128 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -1318,6 +1365,7 @@ where
}
#[allow(clippy::trait_duplication_in_bounds)] // HACK: clippy 1.64.0 bug
+#[allow(deprecated)]
fn recognize_float_or_exceptions<I, E: ParserError<I>>(
input: &mut I,
) -> PResult<<I as Stream>::Slice, E>
@@ -1332,8 +1380,12 @@ where
alt((
recognize_float,
crate::token::tag_no_case("nan"),
- crate::token::tag_no_case("infinity"),
- crate::token::tag_no_case("inf"),
+ (
+ opt(one_of(['+', '-'])),
+ crate::token::tag_no_case("infinity"),
+ )
+ .recognize(),
+ (opt(one_of(['+', '-'])), crate::token::tag_no_case("inf")).recognize(),
))
.parse_next(input)
}