2023-07-20 14:26:59 +00:00
|
|
|
use nom::{
|
2023-07-22 11:51:19 +00:00
|
|
|
branch::alt,
|
2023-08-30 17:00:08 +00:00
|
|
|
bytes::complete::{tag, take_while1},
|
2023-07-20 14:26:59 +00:00
|
|
|
character::complete::space0,
|
2023-08-30 17:00:08 +00:00
|
|
|
combinator::{into, recognize},
|
|
|
|
multi::many0,
|
2023-07-23 07:46:57 +00:00
|
|
|
sequence::{pair, terminated, tuple},
|
2023-07-23 14:37:47 +00:00
|
|
|
IResult,
|
2023-07-20 14:26:59 +00:00
|
|
|
};
|
|
|
|
|
2023-08-30 17:00:08 +00:00
|
|
|
use crate::text::whitespace::{foldable_line, obs_crlf};
|
|
|
|
use crate::text::misc_token::unstructured;
|
2023-07-20 14:26:59 +00:00
|
|
|
|
2023-07-24 20:08:13 +00:00
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
2023-08-30 17:00:08 +00:00
|
|
|
pub struct Kv2<'a>(pub &'a [u8], pub &'a [u8]);
|
|
|
|
impl<'a> From<(&'a [u8], &'a [u8])> for Kv2<'a> {
|
|
|
|
fn from(pair: (&'a [u8], &'a [u8])) -> Self {
|
2023-08-30 09:35:29 +00:00
|
|
|
Self(pair.0, pair.1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
pub enum Field<'a> {
|
2023-08-30 17:00:08 +00:00
|
|
|
Good(Kv2<'a>),
|
2023-08-30 09:35:29 +00:00
|
|
|
Bad(&'a [u8]),
|
|
|
|
}
|
2023-08-30 17:00:08 +00:00
|
|
|
impl<'a> From<Kv2<'a>> for Field<'a> {
|
|
|
|
fn from(kv: Kv2<'a>) -> Self {
|
2023-08-30 09:35:29 +00:00
|
|
|
Self::Good(kv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a> From<&'a [u8]> for Field<'a> {
|
|
|
|
fn from(bad: &'a [u8]) -> Self {
|
|
|
|
Self::Bad(bad)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse headers as key/values
|
|
|
|
pub fn header_kv(input: &[u8]) -> IResult<&[u8], Vec<Field>> {
|
|
|
|
terminated(
|
|
|
|
many0(
|
|
|
|
alt((
|
2023-08-30 17:00:08 +00:00
|
|
|
into(correct_field),
|
2023-08-30 09:35:29 +00:00
|
|
|
into(foldable_line),
|
|
|
|
))
|
|
|
|
),
|
|
|
|
obs_crlf
|
|
|
|
)(input)
|
|
|
|
}
|
2023-07-24 17:19:49 +00:00
|
|
|
|
2023-08-30 09:35:29 +00:00
|
|
|
pub fn field_any(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
|
|
|
terminated(
|
|
|
|
take_while1(|c| (0x21..=0x7E).contains(&c) && c != 0x3A),
|
|
|
|
tuple((space0, tag(b":"), space0)),
|
|
|
|
)(input)
|
|
|
|
}
|
|
|
|
|
2023-07-20 14:26:59 +00:00
|
|
|
/// Optional field
|
|
|
|
///
|
|
|
|
/// ```abnf
|
|
|
|
/// field = field-name ":" unstructured CRLF
|
|
|
|
/// field-name = 1*ftext
|
|
|
|
/// ftext = %d33-57 / ; Printable US-ASCII
|
|
|
|
/// %d59-126 ; characters not including
|
|
|
|
/// ; ":".
|
|
|
|
/// ```
|
2023-08-30 17:00:08 +00:00
|
|
|
pub fn correct_field(input: &[u8]) -> IResult<&[u8], Kv2> {
|
2023-07-22 11:51:19 +00:00
|
|
|
terminated(
|
2023-08-30 09:35:29 +00:00
|
|
|
into(pair(
|
|
|
|
field_any,
|
2023-08-30 17:00:08 +00:00
|
|
|
recognize(unstructured),
|
2023-08-30 09:35:29 +00:00
|
|
|
)),
|
2023-07-23 14:37:47 +00:00
|
|
|
obs_crlf,
|
|
|
|
)(input)
|
2023-07-20 14:26:59 +00:00
|
|
|
}
|