ics: implement support for multiple values per key

This commit is contained in:
Astro 2021-05-31 19:04:16 +02:00
parent 553ccc6ad7
commit 7453b01191
2 changed files with 43 additions and 11 deletions

View File

@ -15,21 +15,21 @@ pub type Props = Vec<(String, String)>;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Object { pub struct Object {
pub name: String, pub name: String,
pub content: HashMap<String, (Props, String)>, pub content: HashMap<String, Vec<(Props, String)>>,
pub children: Vec<Box<Object>>, pub children: Vec<Box<Object>>,
} }
impl<'a> GetValue<'a, &'a str> for Object { impl<'a> GetValue<'a, &'a str> for Object {
fn get(&'a self, key: &'_ str) -> Option<&'a str> { fn get(&'a self, key: &'_ str) -> Option<&'a str> {
self.content.get(key) 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 { impl<'a> GetValue<'a, String> for Object {
fn get(&self, key: &'_ str) -> Option<String> { fn get(&self, key: &'_ str) -> Option<String> {
self.content.get(key) self.content.get(key)
.map(|(_props, value)| value.clone()) .and_then(|pairs| pairs.first().map(|(_props, value)| value.clone()))
} }
} }

View File

@ -68,7 +68,10 @@ impl Parser {
let key = replace(current_key, None); let key = replace(current_key, None);
let objects_len = objects.len(); let objects_len = objects.len();
let content = &mut objects[objects_len - 1].content; 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 p.feed(b"BEGIN:VEVENT
SUMMARY:Test event SUMMARY:Test event
DTSTART:19700101 DTSTART:19700101
RRULE:FREQ=YEARLY
END:VEVENT END:VEVENT
", |o| { ", |o| {
@ -97,11 +99,41 @@ END:VEVENT
assert_eq!(obj, Some(Object { assert_eq!(obj, Some(Object {
name: "VEVENT".to_owned(), name: "VEVENT".to_owned(),
content: [("SUMMARY", "Test event"), content: [("SUMMARY", "Test event"),
("RRULE", "FREQ=YEARLY"),
("DTSTART", "19700101")] ("DTSTART", "19700101")]
.iter() .iter()
.cloned() .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(), .collect(),
children: vec![], children: vec![],
})); }));
@ -123,8 +155,8 @@ END:VEVENT
assert_eq!(obj, Some(Object { assert_eq!(obj, Some(Object {
name: "VEVENT".to_owned(), name: "VEVENT".to_owned(),
content: [ content: [
("SUMMARY".to_owned(), (vec![], "Test event".to_owned())), ("SUMMARY".to_owned(), vec![(vec![], "Test event".to_owned())]),
("DTSTART".to_owned(), (vec![("TZID".to_owned(), "Europe/Berlin".to_owned())], "19700101".to_owned())) ("DTSTART".to_owned(), vec![(vec![("TZID".to_owned(), "Europe/Berlin".to_owned())], "19700101".to_owned())])
].iter().cloned().collect(), ].iter().cloned().collect(),
children: vec![], children: vec![],
})); }));
@ -152,14 +184,14 @@ END:VEVENT
("DTSTART", "19700101")] ("DTSTART", "19700101")]
.iter() .iter()
.cloned() .cloned()
.map(|(k, v)| (k.to_owned(), (vec![], v.to_owned()))) .map(|(k, v)| (k.to_owned(), vec![(vec![], v.to_owned())]))
.collect(), .collect(),
children: vec![Box::new(Object { children: vec![Box::new(Object {
name: "VALARM".to_owned(), name: "VALARM".to_owned(),
content: [("ACTION", "NONE")] content: [("ACTION", "NONE")]
.iter() .iter()
.cloned() .cloned()
.map(|(k, v)| (k.to_owned(), (vec![], v.to_owned()))) .map(|(k, v)| (k.to_owned(), vec![(vec![], v.to_owned())]))
.collect(), .collect(),
children: vec![], children: vec![],
})], })],