From 6ccb5a67e493f945f224432dbde62f22e80635ce Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Wed, 31 Dec 2025 17:55:58 +0100 Subject: [PATCH] ical: Respect that calendar do not have to contain a main event --- crates/ical/src/icalendar/object.rs | 39 ++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/crates/ical/src/icalendar/object.rs b/crates/ical/src/icalendar/object.rs index 7aecfce..fa99059 100644 --- a/crates/ical/src/icalendar/object.rs +++ b/crates/ical/src/icalendar/object.rs @@ -89,10 +89,19 @@ impl From<&CalendarObjectComponent> for CalendarObjectType { impl CalendarObjectComponent { fn from_events(mut events: Vec) -> Result { - let main_event = events + // A calendar object does not necessarily have to contain a main VOBJECT + if events.is_empty() { + return Err(Error::MissingCalendar); + } + #[allow(clippy::option_if_let_else)] + let main_event = if let Some(main) = events .extract_if(.., |event| event.event.get_recurrence_id().is_none()) .next() - .expect("there must be one main event"); + { + main + } else { + events.remove(0) + }; let overrides = events; for event in &overrides { if event.get_uid() != main_event.get_uid() { @@ -109,10 +118,19 @@ impl CalendarObjectComponent { Ok(Self::Event(main_event, overrides)) } fn from_todos(mut todos: Vec) -> Result { - let main_todo = todos + // A calendar object does not necessarily have to contain a main VOBJECT + if todos.is_empty() { + return Err(Error::MissingCalendar); + } + #[allow(clippy::option_if_let_else)] + let main_todo = if let Some(main) = todos .extract_if(.., |todo| todo.get_recurrence_id().is_none()) .next() - .expect("there must be one main event"); + { + main + } else { + todos.remove(0) + }; let overrides = todos; for todo in &overrides { if todo.get_uid() != main_todo.get_uid() { @@ -129,10 +147,19 @@ impl CalendarObjectComponent { Ok(Self::Todo(main_todo, overrides)) } fn from_journals(mut journals: Vec) -> Result { - let main_journal = journals + // A calendar object does not necessarily have to contain a main VOBJECT + if journals.is_empty() { + return Err(Error::MissingCalendar); + } + #[allow(clippy::option_if_let_else)] + let main_journal = if let Some(main) = journals .extract_if(.., |journal| journal.get_recurrence_id().is_none()) .next() - .expect("there must be one main event"); + { + main + } else { + journals.remove(0) + }; let overrides = journals; for journal in &overrides { if journal.get_uid() != main_journal.get_uid() {