ezk_sip_types/
parse.rs

1//! Parsing utilities for SIP message components
2
3use 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
27/// Parsable type using nom
28pub trait Parse: Sized + FromStr {
29    /// Create a parser which references the given buffer
30    fn parse(src: &Bytes) -> impl Fn(&str) -> IResult<&str, Self> + '_;
31
32    /// Parse from str
33    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}