diff options
-rw-r--r-- | src/errors.rs | 21 | ||||
-rw-r--r-- | src/event.rs | 14 | ||||
-rw-r--r-- | src/events.rs | 56 | ||||
-rw-r--r-- | src/ics.rs | 73 | ||||
-rw-r--r-- | src/main.rs | 17 |
5 files changed, 95 insertions, 86 deletions
diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..d526bae --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,21 @@ +use std::num::ParseIntError; +use ical::parser; + +#[derive(Debug)] +pub enum EventError { + IcalError(parser::errors::Error), + IntError(ParseIntError), + StatusError, +} + +impl From<parser::errors::Error> for EventError { + fn from(err: parser::errors::Error) -> EventError { + EventError::IcalError(err) + } +} + +impl From<ParseIntError> for EventError { + fn from(err: ParseIntError) -> EventError { + EventError::IntError(err) + } +} diff --git a/src/event.rs b/src/event.rs index 904e550..92b91ed 100644 --- a/src/event.rs +++ b/src/event.rs @@ -3,10 +3,10 @@ use std::fmt; use std::str::FromStr; use chrono; -use chrono::prelude::{DateTime, TimeZone}; +use chrono::TimeZone; use chrono_tz::{Tz, UTC}; -use ics::IcsError; +use errors::EventError; #[derive(Debug)] @@ -21,7 +21,7 @@ pub struct Event { #[derive(Debug)] pub enum Date { - Time(DateTime<Tz>), + Time(chrono::DateTime<Tz>), AllDay(chrono::Date<Tz>), } @@ -77,7 +77,7 @@ impl Date { } } - pub fn parse(date: String, time_zone: String) -> Result<Self, IcsError> { + pub fn parse(date: &String, time_zone: &String) -> Result<Self, EventError> { let tz: Tz = time_zone.parse().unwrap_or(UTC); let date = match date.find("T") { Some(_) => { @@ -102,19 +102,19 @@ impl Date { } impl FromStr for Status { - type Err = IcsError; + type Err = EventError; fn from_str(s: &str) -> Result<Self, Self::Err> { match s { "CONFIRMED" => Ok(Status::Confirmed), "TENTATIVE" => Ok(Status::Tentative), "CANCELED" => Ok(Status::Canceled), - _ => Err(IcsError::StatusError), + _ => Err(EventError::StatusError), } } } -fn cmp_date_time<T: TimeZone>(date: &chrono::Date<T>, time: &DateTime<T>) -> Ordering { +fn cmp_date_time<T: TimeZone>(date: &chrono::Date<T>, time: &chrono::DateTime<T>) -> Ordering { let d2 = time.date(); if date.eq(&d2) { return Ordering::Less; diff --git a/src/events.rs b/src/events.rs new file mode 100644 index 0000000..a78a286 --- /dev/null +++ b/src/events.rs @@ -0,0 +1,56 @@ +use std::io::BufRead; +use std::fmt; +use ical::IcalParser; + +use event::{Event, Date}; +use errors::EventError; + +pub struct Events { + single: Vec<Event>, +} + +impl Events { + pub fn parse<B: BufRead>(buf: B) -> Result<Self, EventError> { + let reader = IcalParser::new(buf); + let mut single = 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)?, + _ => (), + }; + } + single.push(event); + } + } + + single.sort_by(|a, b| a.start.cmp(&b.start)); + Ok(Events { single }) + } +} + +impl fmt::Display for Events { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for event in &self.single { + writeln!(f, "{}", event)?; + } + Ok(()) + } +} diff --git a/src/ics.rs b/src/ics.rs deleted file mode 100644 index 0726ba1..0000000 --- a/src/ics.rs +++ /dev/null @@ -1,73 +0,0 @@ -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) - } -} diff --git a/src/main.rs b/src/main.rs index f51f763..c923232 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,19 @@ extern crate ical; extern crate chrono; extern crate chrono_tz; -use std::env; -mod ics; mod event; +mod events; +mod errors; + +use std::env; +use std::io::BufReader; +use std::fs::File; +use events::Events; fn main() { let args: Vec<_> = env::args().collect(); - let events = ics::parse(&args[1]).unwrap(); - for event in events { - println!("{}", event); - } + let file = File::open(&args[1]).unwrap(); + let buf = BufReader::new(file); + let events = Events::parse(buf).unwrap(); + println!("{}", events); } |