File size: 3,295 Bytes
d90101d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | use nom::branch::alt;
use nom::bytes::complete::take_while_m_n as take_while_m_n_complete;
use nom::bytes::streaming::{tag, take_while, take_while_m_n, take_while1};
use nom::combinator::opt;
use nom::sequence::{preceded, terminated};
use nom::{IResult, Parser};
/// ; ABNF definition from HTML spec
///
/// stream = [ bom ] *event
/// event = *( comment / field ) end-of-line
/// comment = colon *any-char end-of-line
/// field = 1*name-char [ colon [ space ] *any-char ] end-of-line
/// end-of-line = ( cr lf / cr / lf )
///
/// ; characters
/// lf = %x000A ; U+000A LINE FEED (LF)
/// cr = %x000D ; U+000D CARRIAGE RETURN (CR)
/// space = %x0020 ; U+0020 SPACE
/// colon = %x003A ; U+003A COLON (:)
/// bom = %xFEFF ; U+FEFF BYTE ORDER MARK
/// name-char = %x0000-0009 / %x000B-000C / %x000E-0039 / %x003B-10FFFF
/// ; a scalar value other than U+000A LINE FEED (LF), U+000D
/// CARRIAGE RETURN (CR), or U+003A COLON (:) any-char = %x0000-0009 /
/// %x000B-000C / %x000E-10FFFF ; a scalar value other than
/// U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)
#[derive(Debug)]
#[allow(dead_code)]
pub enum RawEventLine<'a> {
Comment(&'a str),
Field(&'a str, Option<&'a str>),
Empty,
}
#[inline]
pub fn is_lf(c: char) -> bool {
c == '\u{000A}'
}
#[inline]
pub fn is_cr(c: char) -> bool {
c == '\u{000D}'
}
#[inline]
pub fn is_space(c: char) -> bool {
c == '\u{0020}'
}
#[inline]
pub fn is_colon(c: char) -> bool {
c == '\u{003A}'
}
#[inline]
pub fn is_bom(c: char) -> bool {
c == '\u{feff}'
}
#[inline]
pub fn is_name_char(c: char) -> bool {
matches!(c, '\u{0000}'..='\u{0009}'
| '\u{000B}'..='\u{000C}'
| '\u{000E}'..='\u{0039}'
| '\u{003B}'..='\u{10FFFF}')
}
#[inline]
pub fn is_any_char(c: char) -> bool {
matches!(c, '\u{0000}'..='\u{0009}'
| '\u{000B}'..='\u{000C}'
| '\u{000E}'..='\u{10FFFF}')
}
#[inline]
fn crlf(input: &str) -> IResult<&str, &str> {
tag("\u{000D}\u{000A}").parse(input)
}
#[inline]
fn end_of_line(input: &str) -> IResult<&str, &str> {
alt((
crlf,
take_while_m_n_complete(1, 1, is_cr),
take_while_m_n_complete(1, 1, is_lf),
))
.parse(input)
}
#[inline]
fn comment(input: &str) -> IResult<&str, RawEventLine<'_>> {
preceded(
take_while_m_n(1, 1, is_colon),
terminated(take_while(is_any_char), end_of_line),
)
.parse(input)
.map(|(input, comment)| (input, RawEventLine::Comment(comment)))
}
#[inline]
fn field(input: &str) -> IResult<&str, RawEventLine<'_>> {
terminated(
(
take_while1(is_name_char),
opt(preceded(
take_while_m_n(1, 1, is_colon),
preceded(opt(take_while_m_n(1, 1, is_space)), take_while(is_any_char)),
)),
),
end_of_line,
)
.parse(input)
.map(|(input, (field, data))| (input, RawEventLine::Field(field, data)))
}
#[inline]
fn empty(input: &str) -> IResult<&str, RawEventLine<'_>> {
end_of_line(input).map(|(i, _)| (i, RawEventLine::Empty))
}
pub fn line(input: &str) -> IResult<&str, RawEventLine<'_>> {
alt((comment, field, empty)).parse(input)
}
|