diff options
author | Markus Unterwaditzer <markus@unterwaditzer.net> | 2016-11-15 20:07:29 +0100 |
---|---|---|
committer | Markus Unterwaditzer <markus@unterwaditzer.net> | 2016-11-15 20:07:29 +0100 |
commit | ee10d38238f120c5fa85004b2b38431a34d47235 (patch) | |
tree | 1b4dc0df0c0d90c0d4904ba8b85105d4d5e91f0f | |
parent | cb041f208a5dc9abd74199d54cbaaa805db2d9a6 (diff) |
Refactor API
-rw-r--r-- | src/vobject/lib.rs | 49 | ||||
-rw-r--r-- | tests/lib.rs | 26 |
2 files changed, 42 insertions, 33 deletions
diff --git a/src/vobject/lib.rs b/src/vobject/lib.rs index b892fd9..999e865 100644 --- a/src/vobject/lib.rs +++ b/src/vobject/lib.rs @@ -66,36 +66,45 @@ impl Component { } } - /// Retrieve one property (from many) by key. Returns `None` if nothing is found. - pub fn single_prop(&self, key: &str) -> Option<&Property> { - match self.props.get(key) { - Some(x) => { - match x.len() { - 1 => Some(&x[0]), - _ => None - } - }, - None => None - } + /// Append the given property, preserve other same-named properties. + pub fn push(&mut self, prop: Property) { + self.props.entry(prop.name.clone()).or_insert_with(Vec::new).push(prop); + } + + /// Set the given property, remove other same-named properties. + pub fn set(&mut self, prop: Property) { + self.props.insert(prop.name.clone(), vec![prop]); } - /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the - /// component) if none exists. - pub fn all_props_mut<T: Into<String>>(&mut self, key: T) -> &mut Vec<Property> { - match self.props.entry(key.into()) { - Occupied(values) => values.into_mut(), - Vacant(values) => values.insert(vec![]) + /// Retrieve one property by key. Returns `None` if not exactly one property was found. + pub fn get_only<P: AsRef<str>>(&self, name: P) -> Option<&Property> { + match self.props.get(name.as_ref()) { + Some(x) if x.len() == 1 => Some(&x[0]), + _ => None } } /// Retrieve properties by key. Returns an empty slice if key doesn't exist. - pub fn all_props(&self, key: &str) -> &[Property] { + pub fn get_all<P: AsRef<str>>(&self, name: P) -> &[Property] { static EMPTY: &'static [Property] = &[]; - match self.props.get(key) { + match self.props.get(name.as_ref()) { Some(values) => &values[..], None => EMPTY } } + + /// Remove a single property. + pub fn pop<P: AsRef<str>>(&mut self, name: P) -> Option<Property> { + match self.props.get_mut(name.as_ref()) { + Some(values) => values.pop(), + None => None + } + } + + /// Remove all properties + pub fn remove<P: AsRef<str>>(&mut self, name: P) -> Option<Vec<Property>> { + self.props.remove(name.as_ref()) + } } impl FromStr for Component { @@ -388,7 +397,7 @@ impl<'s> Parser<'s> { break; } else { - component.all_props_mut(property.name.to_owned()).push(property); + component.push(property); } }; diff --git a/tests/lib.rs b/tests/lib.rs index d5e4f24..165de00 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -24,10 +24,10 @@ fn test_vcard_basic() { REV:20140301T221110Z\n\ END:VCARD\n\r\n\n").unwrap(); - assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Erika Mustermann")); - assert_eq!(item.single_prop("N").unwrap().raw_value, s!("Mustermann;Erika")); + assert_eq!(item.get_only("FN").unwrap().raw_value, s!("Erika Mustermann")); + assert_eq!(item.get_only("N").unwrap().raw_value, s!("Mustermann;Erika")); - let mut tel_values = item.all_props("TEL").iter().map(|x| &x.raw_value[..]); + let mut tel_values = item.get_all("TEL").iter().map(|x| &x.raw_value[..]); assert_eq!(tel_values.next().unwrap(), s!("(0221) 9999123")); assert_eq!(tel_values.next().unwrap(), s!("(0221) 1234567")); assert!(tel_values.next().is_none()); @@ -48,9 +48,9 @@ fn test_line_cont() { END:VCARD").unwrap(); assert_eq!(item.name, s!("VCARD")); - assert_eq!(item.single_prop("TEL").unwrap().raw_value, s!("55554444")); - assert_eq!(item.single_prop("N").unwrap().raw_value, s!("Nikdo;Nikdo=vic")); - assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Alice;Alice=vic")); + assert_eq!(item.get_only("TEL").unwrap().raw_value, s!("55554444")); + assert_eq!(item.get_only("N").unwrap().raw_value, s!("Nikdo;Nikdo=vic")); + assert_eq!(item.get_only("FN").unwrap().raw_value, s!("Alice;Alice=vic")); } #[test] @@ -74,13 +74,13 @@ fn test_icalendar_basic() { END:VCALENDAR\n").unwrap(); assert_eq!(item.name, s!("VCALENDAR")); - assert!(item.single_prop("LOCATION").is_none()); - assert!(item.single_prop("ORGANIZER").is_none()); + assert!(item.get_only("LOCATION").is_none()); + assert!(item.get_only("ORGANIZER").is_none()); let event = &item.subcomponents[0]; assert_eq!(event.name, s!("VEVENT")); - assert!(event.single_prop("ORGANIZER").is_some()); - assert_eq!(event.single_prop("LOCATION").unwrap().raw_value, s!("Somewhere")); + assert!(event.get_only("ORGANIZER").is_some()); + assert_eq!(event.get_only("LOCATION").unwrap().raw_value, s!("Somewhere")); } #[test] @@ -95,7 +95,7 @@ fn test_icalendar_multline() { END:VEVENT\n").unwrap(); assert_eq!(event.name, s!("VEVENT")); - assert_eq!(event.single_prop("SUMMARY").unwrap().raw_value, + assert_eq!(event.get_only("SUMMARY").unwrap().raw_value, s!("Important meeting")); } @@ -122,7 +122,7 @@ fn test_escaping() { ORGANIZER;CN=\"Cott:n Eye Joe\":mailto:joe@joe.com\n\ END:VCALENDAR\n").unwrap(); assert_eq!(item.name, s!("VCALENDAR")); - assert_eq!(item.single_prop("ORGANIZER").unwrap().raw_value, s!("mailto:joe@joe.com")); + assert_eq!(item.get_only("ORGANIZER").unwrap().raw_value, s!("mailto:joe@joe.com")); } #[test] @@ -132,6 +132,6 @@ fn test_property_groups() { foo.EMAIL;TYPE=INTERNET:foo@example.com\n\ foo.X-ACTUAL-TYPE:CUSTOM\n\ END:VCARD\n").unwrap(); - assert_eq!(item.single_prop("EMAIL").unwrap().prop_group, Some("foo".to_owned())); + assert_eq!(item.get_only("EMAIL").unwrap().prop_group, Some("foo".to_owned())); } |