diff --git a/libticker/src/ics/mod.rs b/libticker/src/ics/mod.rs index d84e0a9..c73c745 100644 --- a/libticker/src/ics/mod.rs +++ b/libticker/src/ics/mod.rs @@ -15,21 +15,21 @@ pub type Props = Vec<(String, String)>; #[derive(Debug, PartialEq)] pub struct Object { pub name: String, - pub content: HashMap, + pub content: HashMap>, pub children: Vec>, } impl<'a> GetValue<'a, &'a str> for Object { fn get(&'a self, key: &'_ str) -> Option<&'a str> { self.content.get(key) - .map(|(_props, value)| value.as_ref()) + .and_then(|pairs| pairs.first().map(|(_props, ref value)| value.as_str())) } } impl<'a> GetValue<'a, String> for Object { fn get(&self, key: &'_ str) -> Option { self.content.get(key) - .map(|(_props, value)| value.clone()) + .and_then(|pairs| pairs.first().map(|(_props, value)| value.clone())) } } diff --git a/libticker/src/ics/parser.rs b/libticker/src/ics/parser.rs index ebf1df3..a5b4286 100644 --- a/libticker/src/ics/parser.rs +++ b/libticker/src/ics/parser.rs @@ -68,7 +68,10 @@ impl Parser { let key = replace(current_key, None); let objects_len = objects.len(); let content = &mut objects[objects_len - 1].content; - key.map(|key| content.insert(key, (props, value))); + key.map(|key| content.entry(key) + .or_insert_with(|| vec![]) + .push((props, value)) + ); } } } @@ -87,7 +90,6 @@ mod test { p.feed(b"BEGIN:VEVENT SUMMARY:Test event DTSTART:19700101 -RRULE:FREQ=YEARLY END:VEVENT ", |o| { @@ -97,11 +99,41 @@ END:VEVENT assert_eq!(obj, Some(Object { name: "VEVENT".to_owned(), content: [("SUMMARY", "Test event"), - ("RRULE", "FREQ=YEARLY"), ("DTSTART", "19700101")] .iter() .cloned() - .map(|(k, v)| (k.to_owned(), (vec![], v.to_owned()))) + .map(|(k, v)| (k.to_owned(), vec![(vec![], v.to_owned())])) + .collect(), + children: vec![], + })); + } + + #[test] + fn parse_recurring_event() { + let mut p = Parser::new(); + let mut obj = None; + p.feed(b"BEGIN:VEVENT +SUMMARY:Test event +DTSTART:19700101 +RRULE:FREQ=YEARLY +EXDATE:19710101 +EXDATE:19730101 +EXDATE:19770101 +END:VEVENT + +", |o| { + assert!(obj.is_none()); + obj = Some(o); +}); + assert_eq!(obj, Some(Object { + name: "VEVENT".to_owned(), + content: [("SUMMARY", vec!["Test event"]), + ("RRULE", vec!["FREQ=YEARLY"]), + ("EXDATE", vec!["19710101", "19730101", "19770101"]), + ("DTSTART", vec!["19700101"])] + .iter() + .cloned() + .map(|(k, v)| (k.to_owned(), v.into_iter().map(|v| (vec![], v.to_owned())).collect())) .collect(), children: vec![], })); @@ -123,8 +155,8 @@ END:VEVENT assert_eq!(obj, Some(Object { name: "VEVENT".to_owned(), content: [ - ("SUMMARY".to_owned(), (vec![], "Test event".to_owned())), - ("DTSTART".to_owned(), (vec![("TZID".to_owned(), "Europe/Berlin".to_owned())], "19700101".to_owned())) + ("SUMMARY".to_owned(), vec![(vec![], "Test event".to_owned())]), + ("DTSTART".to_owned(), vec![(vec![("TZID".to_owned(), "Europe/Berlin".to_owned())], "19700101".to_owned())]) ].iter().cloned().collect(), children: vec![], })); @@ -152,14 +184,14 @@ END:VEVENT ("DTSTART", "19700101")] .iter() .cloned() - .map(|(k, v)| (k.to_owned(), (vec![], v.to_owned()))) + .map(|(k, v)| (k.to_owned(), vec![(vec![], v.to_owned())])) .collect(), children: vec![Box::new(Object { name: "VALARM".to_owned(), content: [("ACTION", "NONE")] .iter() .cloned() - .map(|(k, v)| (k.to_owned(), (vec![], v.to_owned()))) + .map(|(k, v)| (k.to_owned(), vec![(vec![], v.to_owned())])) .collect(), children: vec![], })],