1
use crate::parser::Error;
2
use nom::bytes::streaming::{tag, take_until};
3
use nom::character::streaming::one_of;
4
use nom::combinator::opt;
5
use nom::error::ParseError;
6
use nom::sequence::tuple;
7
use nom::IResult;
8

            
9
/// Recognize a content line, collapsing folded lines.
10
///
11
/// The Aetolia parser does not recognize folded lines, so if the icalendar input may contain them
12
/// then this function should be used to preprocess the input.
13
7
pub fn content_line_first_pass<'a, E>(mut input: &'a [u8]) -> IResult<&'a [u8], Vec<u8>, E>
14
7
where
15
7
    E: ParseError<&'a [u8]> + From<Error<'a>>,
16
7
{
17
7
    let mut out = Vec::new();
18

            
19
    loop {
20
500
        let (i, o) = take_until("\r\n")(input)?;
21
500
        out.extend_from_slice(o);
22
500
        input = i;
23
500

            
24
500
        if input.len() == 2 {
25
7
            break;
26
493
        }
27
493

            
28
493
        match tuple((tag("\r\n"), opt(one_of(" \t"))))(input) {
29
493
            Ok((i, (lb, sp))) => {
30
493
                if sp.is_none() {
31
476
                    out.extend_from_slice(lb);
32
490
                }
33
493
                input = i;
34
            }
35
            Err(e) => {
36
                if e.is_incomplete() {
37
                    return Err(e);
38
                }
39

            
40
                break;
41
            }
42
        }
43
    }
44

            
45
7
    let (input, v) = tag("\r\n")(input)?;
46
7
    out.extend_from_slice(v);
47
7

            
48
7
    Ok((input, out))
49
7
}
50

            
51
#[cfg(test)]
52
mod tests {
53
    use super::*;
54
    use crate::test_utils::check_rem;
55

            
56
    #[test]
57
2
    fn general_line() {
58
2
        let (rem, line) = content_line_first_pass::<Error>(
59
2
            b"DESCRIP\r\n TION;BRE\r\n NT\r\n =\r\n sent\r\n :\r\n Meeting \"\r\n A\"\r\n",
60
2
        )
61
2
        .unwrap();
62
2
        check_rem(rem, 0);
63
2
        assert_eq!(line, b"DESCRIPTION;BRENT=sent:Meeting \"A\"\r\n");
64
2
    }
65
}