From a791f2e80d49e8ca0a36a9dbc38fdd1013935e8f Mon Sep 17 00:00:00 2001 From: ThetaSinner Date: Sat, 25 May 2024 20:40:17 +0100 Subject: [PATCH] Test a simple vevent property --- src/parser/component/event.rs | 163 ++++++++++++++++++++++++++++++- src/parser/object/types.rs | 42 +++++++- src/parser/property/component.rs | 18 ++-- 3 files changed, 208 insertions(+), 15 deletions(-) diff --git a/src/parser/component/event.rs b/src/parser/component/event.rs index dbe259d..00e88ee 100644 --- a/src/parser/component/event.rs +++ b/src/parser/component/event.rs @@ -1,5 +1,13 @@ use crate::parser::object::types::{CalendarComponent, ComponentProperty}; -use crate::parser::property::{prop_date_time_stamp, prop_date_time_start, prop_iana, prop_x}; +use crate::parser::property::{ + prop_attach, prop_attendee, prop_categories, prop_classification, prop_comment, prop_contact, + prop_created, prop_date_time_end, prop_date_time_stamp, prop_date_time_start, prop_description, + prop_duration, prop_exception_date_times, prop_geographic_position, prop_iana, + prop_last_modified, prop_location, prop_organizer, prop_priority, prop_recurrence_date_times, + prop_recurrence_id, prop_recurrence_rule, prop_related_to, prop_request_status, prop_resources, + prop_sequence, prop_status, prop_summary, prop_time_transparency, prop_unique_identifier, + prop_url, prop_x, +}; use crate::parser::Error; use nom::branch::alt; use nom::bytes::streaming::tag; @@ -11,8 +19,40 @@ pub fn component_event(input: &[u8]) -> IResult<&[u8], CalendarComponent, Error> let (input, (_, properties, _)) = tuple(( tag("BEGIN:VEVENT\r\n"), many0(alt(( - prop_date_time_start.map(ComponentProperty::DateTimeStart), - prop_date_time_stamp.map(ComponentProperty::DateTimeStamp), + alt(( + prop_date_time_stamp.map(ComponentProperty::DateTimeStamp), + prop_unique_identifier.map(ComponentProperty::UniqueIdentifier), + prop_date_time_start.map(ComponentProperty::DateTimeStart), + prop_classification.map(ComponentProperty::Classification), + prop_created.map(ComponentProperty::DateTimeCreated), + prop_description.map(ComponentProperty::Description), + prop_geographic_position.map(ComponentProperty::GeographicPosition), + prop_last_modified.map(ComponentProperty::LastModified), + prop_location.map(ComponentProperty::Location), + prop_organizer.map(ComponentProperty::Organizer), + prop_priority.map(ComponentProperty::Priority), + prop_sequence.map(ComponentProperty::Sequence), + prop_status.map(ComponentProperty::Status), + prop_summary.map(ComponentProperty::Summary), + prop_time_transparency.map(ComponentProperty::TimeTransparency), + )), + alt(( + prop_url.map(ComponentProperty::Url), + prop_recurrence_id.map(ComponentProperty::RecurrenceId), + prop_recurrence_rule.map(ComponentProperty::RecurrenceRule), + prop_date_time_end.map(ComponentProperty::DateTimeEnd), + prop_duration.map(ComponentProperty::Duration), + prop_attach.map(ComponentProperty::Attach), + prop_attendee.map(ComponentProperty::Attendee), + prop_categories.map(ComponentProperty::Categories), + prop_comment.map(ComponentProperty::Comment), + prop_contact.map(ComponentProperty::Contact), + prop_exception_date_times.map(ComponentProperty::ExceptionDateTimes), + prop_request_status.map(ComponentProperty::RequestStatus), + prop_related_to.map(ComponentProperty::RelatedTo), + prop_resources.map(ComponentProperty::Resources), + prop_recurrence_date_times.map(ComponentProperty::RecurrenceDateTimes), + )), prop_x.map(ComponentProperty::XProp), prop_iana.map(ComponentProperty::IanaProp), ))), @@ -21,3 +61,120 @@ pub fn component_event(input: &[u8]) -> IResult<&[u8], CalendarComponent, Error> Ok((input, CalendarComponent::Event { properties })) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::parser::property::{ + CategoriesProperty, Classification, ClassificationProperty, Date, DateOrDateTime, DateTime, + DateTimeEndProperty, DateTimeStamp, DateTimeStartProperty, SummaryProperty, Time, + UniqueIdentifierProperty, + }; + use crate::test_utils::check_rem; + + #[test] + fn test_component_event() { + let input = b"BEGIN:VEVENT\r\nUID:19970901T130000Z-123401@example.com\r\nDTSTAMP:19970901T130000Z\r\nDTSTART:19970903T163000Z\r\nDTEND:19970903T190000Z\r\nSUMMARY:Annual Employee Review\r\nCLASS:PRIVATE\r\nCATEGORIES:BUSINESS,HUMAN RESOURCES\r\nEND:VEVENT\r\n"; + let (rem, component) = component_event(input).unwrap(); + check_rem(rem, 0); + + match component { + CalendarComponent::Event { properties } => { + assert_eq!(properties.len(), 7); + + assert_eq!( + properties[0], + ComponentProperty::UniqueIdentifier(UniqueIdentifierProperty { + other_params: vec![], + value: b"19970901T130000Z-123401@example.com".to_vec(), + }) + ); + + assert_eq!( + properties[1], + ComponentProperty::DateTimeStamp(DateTimeStamp { + other_params: vec![], + value: DateTime { + date: Date { + year: 1997, + month: 9, + day: 1, + }, + time: Time { + hour: 13, + minute: 0, + second: 0, + is_utc: true, + }, + }, + }) + ); + + assert_eq!( + properties[2], + ComponentProperty::DateTimeStart(DateTimeStartProperty { + params: vec![], + value: DateOrDateTime::DateTime(DateTime { + date: Date { + year: 1997, + month: 9, + day: 3, + }, + time: Time { + hour: 16, + minute: 30, + second: 0, + is_utc: true, + }, + }), + }) + ); + + assert_eq!( + properties[3], + ComponentProperty::DateTimeEnd(DateTimeEndProperty { + params: vec![], + value: DateOrDateTime::DateTime(DateTime { + date: Date { + year: 1997, + month: 9, + day: 3, + }, + time: Time { + hour: 19, + minute: 0, + second: 0, + is_utc: true, + }, + }), + }) + ); + + assert_eq!( + properties[4], + ComponentProperty::Summary(SummaryProperty { + params: vec![], + value: b"Annual Employee Review".to_vec(), + }) + ); + + assert_eq!( + properties[5], + ComponentProperty::Classification(ClassificationProperty { + other_params: vec![], + value: Classification::Private, + }) + ); + + assert_eq!( + properties[6], + ComponentProperty::Categories(CategoriesProperty { + params: vec![], + value: vec![b"BUSINESS".to_vec(), b"HUMAN RESOURCES".to_vec()], + }) + ); + } + _ => panic!("Unexpected component type"), + } + } +} diff --git a/src/parser/object/types.rs b/src/parser/object/types.rs index 15d379b..198b672 100644 --- a/src/parser/object/types.rs +++ b/src/parser/object/types.rs @@ -1,7 +1,15 @@ use crate::parser::property::types::{ CalendarScaleProperty, IanaProperty, MethodProperty, ProductId, VersionProperty, XProperty, }; -use crate::parser::property::{DateTimeStamp, DateTimeStartProperty}; +use crate::parser::property::{ + AttachProperty, AttendeeProperty, CategoriesProperty, ClassificationProperty, CommentProperty, + ContactProperty, CreatedProperty, DateTimeEndProperty, DateTimeStamp, DateTimeStartProperty, + DescriptionProperty, DurationProperty, ExceptionDateTimesProperty, GeographicPositionProperty, + LastModifiedProperty, LocationProperty, OrganizerProperty, PriorityProperty, + RecurrenceDateTimesProperty, RecurrenceIdProperty, RecurrenceRuleProperty, RelatedToProperty, + RequestStatusProperty, ResourcesProperty, SequenceProperty, StatusProperty, SummaryProperty, + TimeTransparencyProperty, UniqueIdentifierProperty, UrlProperty, +}; use crate::parser::ContentLine; #[derive(Debug)] @@ -20,10 +28,38 @@ pub enum CalendarProperty<'a> { IanaProp(IanaProperty<'a>), } -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq)] pub enum ComponentProperty<'a> { - DateTimeStart(DateTimeStartProperty<'a>), DateTimeStamp(DateTimeStamp<'a>), + UniqueIdentifier(UniqueIdentifierProperty<'a>), + DateTimeStart(DateTimeStartProperty<'a>), + Classification(ClassificationProperty<'a>), + DateTimeCreated(CreatedProperty<'a>), + Description(DescriptionProperty<'a>), + GeographicPosition(GeographicPositionProperty<'a>), + LastModified(LastModifiedProperty<'a>), + Location(LocationProperty<'a>), + Organizer(OrganizerProperty<'a>), + Priority(PriorityProperty<'a>), + Sequence(SequenceProperty<'a>), + Status(StatusProperty<'a>), + Summary(SummaryProperty<'a>), + TimeTransparency(TimeTransparencyProperty<'a>), + Url(UrlProperty<'a>), + RecurrenceId(RecurrenceIdProperty<'a>), + RecurrenceRule(RecurrenceRuleProperty<'a>), + DateTimeEnd(DateTimeEndProperty<'a>), + Duration(DurationProperty<'a>), + Attach(AttachProperty<'a>), + Attendee(AttendeeProperty<'a>), + Categories(CategoriesProperty<'a>), + Comment(CommentProperty<'a>), + Contact(ContactProperty<'a>), + ExceptionDateTimes(ExceptionDateTimesProperty<'a>), + RequestStatus(RequestStatusProperty<'a>), + RelatedTo(RelatedToProperty<'a>), + Resources(ResourcesProperty<'a>), + RecurrenceDateTimes(RecurrenceDateTimesProperty<'a>), XProp(XProperty<'a>), IanaProp(IanaProperty<'a>), } diff --git a/src/parser/property/component.rs b/src/parser/property/component.rs index c451bce..560d34d 100644 --- a/src/parser/property/component.rs +++ b/src/parser/property/component.rs @@ -169,7 +169,7 @@ pub struct DescriptionProperty<'a> { /// Parse a DESCRIPTION property. /// /// RFC 5545, section 3.8.1.5 -fn prop_description(input: &[u8]) -> IResult<&[u8], DescriptionProperty, Error> { +pub fn prop_description(input: &[u8]) -> IResult<&[u8], DescriptionProperty, Error> { let (input, (_, params, _, value, _)) = tuple(( tag("DESCRIPTION"), params, @@ -191,7 +191,7 @@ pub struct GeographicPositionProperty<'a> { /// Parse a GEO property. /// /// RFC 5545, section 3.8.1.6 -fn prop_geographic_position(input: &[u8]) -> IResult<&[u8], GeographicPositionProperty, Error> { +pub fn prop_geographic_position(input: &[u8]) -> IResult<&[u8], GeographicPositionProperty, Error> { let (input, (_, other_params, _, (latitude, _, longitude), _)) = tuple(( tag("GEO"), other_params, @@ -595,7 +595,7 @@ pub fn prop_url(input: &[u8]) -> IResult<&[u8], UrlProperty, Error> { } #[derive(Debug, Eq, PartialEq)] -pub struct UniqueIdentifier<'a> { +pub struct UniqueIdentifierProperty<'a> { pub other_params: Vec>, pub value: Vec, } @@ -603,7 +603,7 @@ pub struct UniqueIdentifier<'a> { /// Parse a UID property. /// /// RFC 5545, section 3.8.4.7 -pub fn prop_unique_identifier(input: &[u8]) -> IResult<&[u8], UniqueIdentifier, Error> { +pub fn prop_unique_identifier(input: &[u8]) -> IResult<&[u8], UniqueIdentifierProperty, Error> { let (input, (_, other_params, _, value, _)) = tuple(( tag("UID"), other_params, @@ -614,7 +614,7 @@ pub fn prop_unique_identifier(input: &[u8]) -> IResult<&[u8], UniqueIdentifier, Ok(( input, - UniqueIdentifier { + UniqueIdentifierProperty { other_params, value, }, @@ -711,7 +711,7 @@ pub struct CreatedProperty<'a> { /// Parse a CREATED property. /// /// RFC 5545, section 3.8.7.1 -pub fn prop_date_time_created(input: &[u8]) -> IResult<&[u8], CreatedProperty, Error> { +pub fn prop_created(input: &[u8]) -> IResult<&[u8], CreatedProperty, Error> { let (input, (_, other_params, _, value, _)) = tuple(( tag("CREATED"), other_params, @@ -1451,7 +1451,7 @@ RSVP to team leader."# check_rem(rem, 1); assert_eq!( prop, - UniqueIdentifier { + UniqueIdentifierProperty { other_params: vec![], value: b"19960401T080045Z-4000F192713-0052@example.com".to_vec(), } @@ -1640,7 +1640,7 @@ RSVP to team leader."# #[test] fn created() { - let (rem, prop) = prop_date_time_created(b"CREATED:19980118T230000Z\r\n;").unwrap(); + let (rem, prop) = prop_created(b"CREATED:19980118T230000Z\r\n;").unwrap(); check_rem(rem, 1); assert_eq!( prop, @@ -1665,7 +1665,7 @@ RSVP to team leader."# #[test] fn date_time_stamp() { - let (rem, prop) = prop_date_time_created(b"CREATED:19960329T133000Z\r\n;").unwrap(); + let (rem, prop) = prop_created(b"CREATED:19960329T133000Z\r\n;").unwrap(); check_rem(rem, 1); assert_eq!( prop,