aboutsummaryrefslogtreecommitdiff
path: root/src/ics.rs
blob: 0726ba1b810b69ba2b88d2d7d2c6cfa460fbd9e2 (plain)
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
use std::io;
use std::io::BufReader;
use std::fs::File;
use std::path::Path;
use std::num::ParseIntError;

use ical::parser;
use ical::IcalParser;

use event::{Event, Date};


pub fn parse<P: AsRef<Path>>(ics: P) -> Result<Vec<Event>, IcsError> {
    let buf = BufReader::new(File::open(ics)?);
    let reader = IcalParser::new(buf);
    let mut events = Vec::new();

    for line in reader {
        for ev in line?.events {
            let mut event = Event::new();
            for property in ev.properties {
                let value = property.value.unwrap_or("".to_string());
                let mut time_zone = "".to_string();

                for (param, value) in property.params.unwrap_or(vec![]) {
                    if param == "TZID" && value.len() > 0 {
                        time_zone = value[0].clone();
                    }
                }

                match property.name.as_ref() {
                    "SUMMARY" => event.summary = value,
                    "LOCATION" => event.location = value,
                    "DESCRIPTION" => event.description = value,
                    "STATUS" => event.status = value.parse()?,
                    "DTSTART" => event.start = Date::parse(value, time_zone)?,
                    "DTEND" => event.end = Date::parse(value, time_zone)?,
                    _ => (),
                };
            }
            events.push(event);
        }
    }

    events.sort_by(|a, b| a.start.cmp(&b.start));
    Ok(events)
}

#[derive(Debug)]
pub enum IcsError {
    IoError(io::Error),
    IcalError(parser::errors::Error),
    IntError(ParseIntError),
    StatusError,
}

impl From<io::Error> for IcsError {
    fn from(err: io::Error) -> IcsError {
        IcsError::IoError(err)
    }
}

impl From<parser::errors::Error> for IcsError {
    fn from(err: parser::errors::Error) -> IcsError {
        IcsError::IcalError(err)
    }
}

impl From<ParseIntError> for IcsError {
    fn from(err: ParseIntError) -> IcsError {
        IcsError::IntError(err)
    }
}