1
use crate::convert::ToModel;
2
use crate::error::{AetoliaError, AetoliaResult};
3
use crate::model::object::ICalObject;
4
use crate::parser::{content_line_first_pass, ical_stream, Error};
5
use std::io::Read;
6

            
7
/// Load iCalendar data from a byte source.
8
///
9
/// If the input cannot be parsed or represented using the core model, an error is returned.
10
/// The content is expected to be a list of iCalendar objects. In most cases, this it is a single
11
/// iCalendar object, containing multiple components.
12
///
13
/// Note that this function does NOT validate the iCalendar data. You should use the validator if
14
/// you want to ensure that the data is reasonably correct. If you plan to ingest the data into
15
/// another system, you should validate the result of this function because the parser
16
/// and model permit a lot of inputs that could confuse other systems.
17
5
pub fn load_ical(input: impl AsRef<[u8]>) -> AetoliaResult<Vec<ICalObject>> {
18
5
    let (rem, content) = content_line_first_pass::<Error>(input.as_ref())
19
5
        .map_err(|e| AetoliaError::other(format!("First pass failed: {e}")))?;
20
5
    if !rem.is_empty() {
21
        return Err(AetoliaError::other("Trailing data after first pass"));
22
5
    }
23

            
24
5
    let (rem, stream) = ical_stream::<Error>(&content)
25
5
        .map_err(|e| AetoliaError::other(format!("Stream parsing failed: {e}")))?;
26
5
    if !rem.is_empty() {
27
        return Err(AetoliaError::other("Trailing data after stream"));
28
5
    }
29

            
30
5
    let model = stream.to_model()?;
31

            
32
5
    Ok(model)
33
5
}
34

            
35
/// Convenience function to load iCalendar data from a readable source.
36
///
37
/// The data is read to the end and then passed to [load_ical].
38
3
pub fn read_ical<R: Read>(mut input: R) -> AetoliaResult<Vec<ICalObject>> {
39
3
    let mut buffer = Vec::new();
40
3
    input.read_to_end(&mut buffer)?;
41

            
42
3
    load_ical(buffer)
43
3
}