1
#![doc = include_str!("../README.md")]
2

            
3
use crate::parser::Error;
4
use nom::branch::alt;
5
use nom::combinator::recognize;
6
use nom::error::ParseError;
7
use nom::sequence::tuple;
8
use nom::{IResult, InputIter, InputLength, InputTake};
9
use std::num::NonZeroUsize;
10

            
11
/// Common types.
12
pub mod common;
13
/// Conversion from the parser model to the core representation.
14
pub mod convert;
15
/// The core representation that is used for everything except the parser.
16
pub mod model;
17
/// Common operations.
18
pub mod ops;
19
/// The iCalendar parser.
20
pub mod parser;
21
/// The serializer for the core representation back to the iCalendar text format.
22
pub mod serialize;
23
#[cfg(test)]
24
mod test_utils;
25
/// Validation of iCalendar rules against the core representation.
26
pub mod validate;
27

            
28
/// Prelude which contains everything that's needed for most use-cases to consume this library.
29
pub mod prelude {
30
    pub use crate::common::PropertyKind;
31
    pub use crate::common::*;
32
    pub use crate::model::access::*;
33
    pub use crate::model::component::*;
34
    pub use crate::model::object::*;
35
    pub use crate::model::param::*;
36
    pub use crate::model::property::*;
37
    pub use crate::ops::load_ical;
38
    pub use crate::parser::{content_line_first_pass, ical_object, ical_stream};
39
    pub use crate::serialize::WriteModel;
40
    pub use crate::validate::{validate_model, ICalendarErrorSeverity};
41
}
42

            
43
/// Streaming, single character matching the predicate
44
84900
pub(crate) fn single<F, Input, Output, Error: ParseError<Input>>(
45
84900
    cond: F,
46
84900
) -> impl Fn(Input) -> IResult<Input, Output, Error>
47
84900
where
48
84900
    Input: InputIter<Item = Output> + InputLength + InputTake,
49
84900
    F: Fn(<Input as InputIter>::Item) -> bool,
50
84900
    Output: Copy,
51
84900
{
52
37872
    move |i: Input| {
53
37872
        match i.iter_elements().next() {
54
37872
            Some(c) if cond(c) => {
55
15116
                let (input, v) = i.take_split(1);
56
15116
                Ok((input, v.iter_elements().next().unwrap()))
57
            }
58
            // Closest error I can get, can't add to the Nom enum!
59
22756
            Some(_) => Err(nom::Err::Error(Error::from_error_kind(
60
22756
                i,
61
22756
                nom::error::ErrorKind::OneOf,
62
22756
            ))),
63
            None => Err(nom::Err::Incomplete(nom::Needed::Size(
64
                NonZeroUsize::new(1).unwrap(),
65
            ))),
66
        }
67
37872
    }
68
84900
}
69

            
70
2478
fn utf8_seq<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E>
71
2478
where
72
2478
    E: ParseError<&'a [u8]> + From<Error<'a>>,
73
2478
{
74
2478
    let (input, seq) = alt((
75
2478
        // Utf-8 2-byte sequence
76
2478
        recognize(tuple((
77
2478
            single(|b| matches!(b, b'\xC2'..=b'\xDF')),
78
2478
            single(|b| matches!(b, b'\x80'..=b'\xBF')),
79
2478
        ))),
80
2478
        // Utf-8 3-byte sequence
81
2478
        alt((
82
2478
            recognize(tuple((
83
2478
                single(|b| b == b'\xE0'),
84
2478
                single(|b| matches!(b, b'\xA0'..=b'\xBF')),
85
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
86
2478
            ))),
87
2478
            recognize(tuple((
88
2478
                single(|b| matches!(b, b'\xE1'..=b'\xEC')),
89
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
90
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
91
2478
            ))),
92
2478
            recognize(tuple((
93
2478
                single(|b| b == b'\xED'),
94
2478
                single(|b| matches!(b, b'\x80'..=b'\x9F')),
95
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
96
2478
            ))),
97
2478
            recognize(tuple((
98
2478
                single(|b| matches!(b, b'\xEE'..=b'\xEF')),
99
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
100
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
101
2478
            ))),
102
2478
        )),
103
2478
        // Utf-8 4-byte sequence
104
2478
        alt((
105
2478
            recognize(tuple((
106
2478
                single(|b| b == b'\xF0'),
107
2478
                single(|b| matches!(b, b'\x90'..=b'\xBF')),
108
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
109
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
110
2478
            ))),
111
2478
            recognize(tuple((
112
2478
                single(|b| matches!(b, b'\xF1'..=b'\xF3')),
113
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
114
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
115
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
116
2478
            ))),
117
2478
            recognize(tuple((
118
2478
                single(|b| b == b'\xF4'),
119
2478
                single(|b| matches!(b, b'\x80'..=b'\x8F')),
120
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
121
2478
                single(|b| matches!(b, b'\x80'..=b'\xBF')),
122
2478
            ))),
123
2478
        )),
124
2478
    ))(input)?;
125

            
126
8
    Ok((input, seq))
127
2478
}
128

            
129
#[cfg(test)]
130
mod tests {
131
    use super::*;
132
    use nom::multi::many1;
133

            
134
    #[test]
135
2
    fn valid_utf8() {
136
2
        let (rem, seq) = utf8_seq::<Error>("👍".as_bytes()).unwrap();
137
2
        test_utils::check_rem(rem, 0);
138
2
        assert_eq!(seq, "👍".as_bytes());
139
2
    }
140

            
141
    #[test]
142
2
    fn invalid_utf8() {
143
2
        let mut input = "👍👌".as_bytes().to_vec();
144
2
        input.extend_from_slice(&[1, 3, 4, 5, 2, 1]);
145
2
        let (rem, seq) = many1(utf8_seq::<Error>)(input.as_slice()).unwrap();
146
2
        test_utils::check_rem(rem, 6);
147
2
        assert_eq!(
148
2
            seq.into_iter().flatten().cloned().collect::<Vec<_>>(),
149
2
            "👍👌".as_bytes().to_vec()
150
2
        );
151
2
    }
152
}