1use std::str::FromStr;
4
5use bytes::Bytes;
6use bytesstr::BytesStr;
7use internal::IResult;
8use nom::Finish;
9use nom::bytes::complete::{escaped, is_not};
10use nom::character::complete::char;
11use nom::error::{VerboseError, VerboseErrorKind};
12use nom::sequence::delimited;
13
14pub(crate) fn parse_quoted(i: &str) -> IResult<&str, &str> {
15 delimited(char('"'), escaped(is_not("\""), '\\', char('"')), char('"'))(i)
16}
17
18pub(crate) fn whitespace(c: char) -> bool {
19 matches!(c, ' ' | '\t' | '\r' | '\n')
20}
21
22#[rustfmt::skip]
23pub(crate) fn token(c: char) -> bool {
24 c.is_alphanumeric() || matches!(c, '-' | '.' | '!' | '%' | '*' | '_' | '`' | '\'' | '~' | '+')
25}
26
27pub trait Parse: Sized + FromStr {
29 fn parse(src: &Bytes) -> impl Fn(&str) -> IResult<&str, Self> + '_;
31
32 fn parse_str(i: &str) -> Result<Self, VerboseError<String>> {
34 let src = BytesStr::from(i);
35
36 let (remaining, parsed) = Self::parse(src.as_ref())(&src)
37 .finish()
38 .map_err(internal::verbose_error_to_owned)?;
39
40 if remaining.is_empty() {
41 Ok(parsed)
42 } else {
43 Err(VerboseError {
44 errors: vec![(
45 remaining.into(),
46 VerboseErrorKind::Context("Input was not completely consumed"),
47 )],
48 })
49 }
50 }
51}
52
53macro_rules! impl_from_str {
54 ($ty:ty) => {
55 impl std::str::FromStr for $ty {
56 type Err = $crate::_private_reexport::nom::error::VerboseError<String>;
57
58 fn from_str(i: &str) -> Result<Self, Self::Err> {
59 <Self as Parse>::parse_str(i)
60 }
61 }
62 };
63}