From e47e2a0ce70ec2f8e398c2a80022f7e2b8299516 Mon Sep 17 00:00:00 2001 From: ThetaSinner Date: Tue, 11 Feb 2025 23:36:16 +0000 Subject: [PATCH] chore: Remove anyhow --- Cargo.lock | 7 -- Cargo.toml | 1 - src/common.rs | 7 +- src/convert.rs | 6 +- src/convert/component.rs | 5 +- src/convert/object.rs | 3 +- src/convert/param.rs | 3 +- src/convert/property.rs | 134 +++++++++++++-------------- src/convert/property/recur.rs | 8 +- src/error.rs | 38 ++++++++ src/lib.rs | 3 + src/model/property.rs | 3 +- src/ops.rs | 13 +-- src/serialize.rs | 3 +- src/serialize/component.rs | 3 +- src/serialize/object.rs | 5 +- src/serialize/param.rs | 3 +- src/serialize/property.rs | 5 +- src/serialize/value.rs | 63 ++++++------- src/validate.rs | 22 +++-- src/validate/component_properties.rs | 7 +- src/validate/recur.rs | 3 +- src/validate/value.rs | 34 +++---- 23 files changed, 216 insertions(+), 163 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.lock b/Cargo.lock index d470ede..a8c0ba8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,6 @@ version = 4 name = "aetolia" version = "0.2.0" dependencies = [ - "anyhow", "base64", "chrono", "hex", @@ -33,12 +32,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anyhow" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" - [[package]] name = "autocfg" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index cae83d8..3ca801e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ nom-language = "0.1.0" base64 = "0.22" hex = "0.4" lazy_static = "1.4" -anyhow = "1" # builder time = "0.3" diff --git a/src/common.rs b/src/common.rs index 740bad9..a43c4ae 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,3 +1,4 @@ +use crate::error::{AetoliaError, AetoliaResult}; use crate::model::property::Duration; use std::cmp::Ordering; use std::ops::{Add, Sub}; @@ -241,7 +242,7 @@ impl From<(time::Date, Option, bool)> for CalendarDateTime { } impl CalendarDateTime { - pub fn add(&self, duration: &Duration) -> anyhow::Result { + pub fn add(&self, duration: &Duration) -> AetoliaResult { match self.time { Some(time) => { // TODO otherwise you have to account for daylight changes. Not yet supported @@ -362,8 +363,8 @@ impl CalendarDateTime { utc: self.utc, }) } else { - Err(anyhow::anyhow!( - "Duration is a time, but the calendar date time is just a date" + Err(AetoliaError::other( + "Duration is a time, but the calendar date time is just a date", )) } } diff --git a/src/convert.rs b/src/convert.rs index 15bde51..80d2eb8 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,3 +1,5 @@ +use crate::error::AetoliaResult; + mod component; mod object; mod param; @@ -7,7 +9,7 @@ mod property; pub trait ToModel { type Model; - fn to_model(&self) -> anyhow::Result; + fn to_model(&self) -> AetoliaResult; } impl ToModel for Vec @@ -16,7 +18,7 @@ where { type Model = Vec; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { self.iter().map(ToModel::to_model).collect() } } diff --git a/src/convert/component.rs b/src/convert/component.rs index 7c7919e..a53ac5e 100644 --- a/src/convert/component.rs +++ b/src/convert/component.rs @@ -1,4 +1,5 @@ use crate::convert::{convert_string, ToModel}; +use crate::error::AetoliaResult; use crate::model::component::{ AlarmComponent, DaylightComponent, EventComponent, FreeBusyComponent, JournalComponent, StandardComponent, TimeZoneComponent, ToDoComponent, @@ -9,7 +10,7 @@ use crate::parser::types::ContentLine; impl ToModel for crate::parser::types::CalendarComponent<'_> { type Model = crate::model::component::CalendarComponent; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { match self { crate::parser::types::CalendarComponent::Event { properties, alarms } => { let mut component = EventComponent::new(); @@ -145,7 +146,7 @@ impl ToModel for crate::parser::types::CalendarComponent<'_> { fn map_unknown_lines( lines: &Vec, component_properties: &mut Vec, -) -> anyhow::Result<()> { +) -> AetoliaResult<()> { for line in lines { let m = line.to_model()?; if m.name.starts_with("X-") || m.name.starts_with("x-") { diff --git a/src/convert/object.rs b/src/convert/object.rs index 978b167..3b49a9f 100644 --- a/src/convert/object.rs +++ b/src/convert/object.rs @@ -1,9 +1,10 @@ use crate::convert::ToModel; +use crate::error::AetoliaResult; impl ToModel for crate::parser::types::ICalendar<'_> { type Model = crate::model::object::ICalObject; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let mut calendar = crate::model::object::ICalObject::new(); calendar.properties.reserve(self.properties.len()); diff --git a/src/convert/param.rs b/src/convert/param.rs index 1f2c2ef..55588a0 100644 --- a/src/convert/param.rs +++ b/src/convert/param.rs @@ -1,4 +1,5 @@ use crate::convert::{convert_string, ToModel}; +use crate::error::AetoliaResult; use crate::model::param::{ AlternateRepresentationParam, CalendarUserTypeParam, CommonNameParam, DelegatedFromParam, DelegatedToParam, DirectoryEntryReferenceParam, EncodingParam, FormatTypeParam, @@ -11,7 +12,7 @@ use crate::parser::types::ParamValue as ParserParam; impl ToModel for ParserParam<'_> { type Model = ModelParam; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(match self { ParserParam::AltRep { uri } => ModelParam::AltRep(AlternateRepresentationParam { uri: convert_string(uri), diff --git a/src/convert/property.rs b/src/convert/property.rs index 79f5e2b..ea3882a 100644 --- a/src/convert/property.rs +++ b/src/convert/property.rs @@ -1,32 +1,32 @@ use crate::common::CalendarDateTime; use crate::convert::{convert_string, ToModel}; +use crate::error::{AetoliaError, AetoliaResult}; use crate::model::property::{ GeographicPositionPropertyValue, Period, RecurrenceDateTimesPropertyValue, RequestStatusPropertyValue, TimeZoneIdPropertyValue, TriggerValue, }; use crate::parser::types::ContentLine; -use anyhow::Context; mod recur; impl ToModel for crate::parser::types::DateTimeStampProperty<'_> { type Model = crate::model::property::DateTimeStampProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::DateTimeStampProperty { value: ( time::Date::from_calendar_date( self.value.date.year as i32, - time::Month::try_from(self.value.date.month).context("Invalid month")?, + time::Month::try_from(self.value.date.month).map_err(AetoliaError::time)?, self.value.date.day, ) - .context("Invalid date")?, + .map_err(AetoliaError::time)?, time::Time::from_hms( self.value.time.hour, self.value.time.minute, self.value.time.second, ) - .context("Invalid time")?, + .map_err(AetoliaError::time)?, self.value.time.is_utc, ) .into(), @@ -38,7 +38,7 @@ impl ToModel for crate::parser::types::DateTimeStampProperty<'_> { impl ToModel for crate::parser::types::UniqueIdentifierProperty<'_> { type Model = crate::model::property::UniqueIdentifierProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::UniqueIdentifierProperty { value: convert_string(&self.value), params: self.other_params.to_model()?, @@ -49,7 +49,7 @@ impl ToModel for crate::parser::types::UniqueIdentifierProperty<'_> { impl ToModel for crate::parser::types::DateTimeStartProperty<'_> { type Model = crate::model::property::DateTimeStartProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let dt = self.value.to_model()?; Ok(crate::model::property::DateTimeStartProperty { @@ -62,7 +62,7 @@ impl ToModel for crate::parser::types::DateTimeStartProperty<'_> { impl ToModel for crate::parser::types::ClassificationProperty<'_> { type Model = crate::model::property::ClassificationProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ClassificationProperty { value: self.value.to_model()?, params: self.other_params.to_model()?, @@ -73,7 +73,7 @@ impl ToModel for crate::parser::types::ClassificationProperty<'_> { impl ToModel for crate::parser::types::Classification<'_> { type Model = crate::model::property::Classification; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(match self { crate::parser::types::Classification::Public => { crate::model::property::Classification::Public @@ -97,7 +97,7 @@ impl ToModel for crate::parser::types::Classification<'_> { impl ToModel for crate::parser::types::DateTimeCreatedProperty<'_> { type Model = crate::model::property::CreatedProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let (date, time, is_utc) = (&self.value).try_into()?; Ok(crate::model::property::CreatedProperty { @@ -110,7 +110,7 @@ impl ToModel for crate::parser::types::DateTimeCreatedProperty<'_> { impl ToModel for crate::parser::types::DescriptionProperty<'_> { type Model = crate::model::property::DescriptionProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::DescriptionProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -121,7 +121,7 @@ impl ToModel for crate::parser::types::DescriptionProperty<'_> { impl ToModel for crate::parser::types::GeographicPositionProperty<'_> { type Model = crate::model::property::GeographicPositionProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::GeographicPositionProperty { value: GeographicPositionPropertyValue { latitude: self.latitude, @@ -135,7 +135,7 @@ impl ToModel for crate::parser::types::GeographicPositionProperty<'_> { impl ToModel for crate::parser::types::LastModifiedProperty<'_> { type Model = crate::model::property::LastModifiedProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let (date, time, is_utc) = (&self.value).try_into()?; Ok(crate::model::property::LastModifiedProperty { @@ -148,7 +148,7 @@ impl ToModel for crate::parser::types::LastModifiedProperty<'_> { impl ToModel for crate::parser::types::LocationProperty<'_> { type Model = crate::model::property::LocationProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::LocationProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -159,7 +159,7 @@ impl ToModel for crate::parser::types::LocationProperty<'_> { impl ToModel for crate::parser::types::OrganizerProperty<'_> { type Model = crate::model::property::OrganizerProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::OrganizerProperty { value: convert_string(self.value), params: self.params.to_model()?, @@ -170,7 +170,7 @@ impl ToModel for crate::parser::types::OrganizerProperty<'_> { impl ToModel for crate::parser::types::PriorityProperty<'_> { type Model = crate::model::property::PriorityProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::PriorityProperty { value: self.value, params: self.other_params.to_model()?, @@ -181,7 +181,7 @@ impl ToModel for crate::parser::types::PriorityProperty<'_> { impl ToModel for crate::parser::types::SequenceProperty<'_> { type Model = crate::model::property::SequenceProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::SequenceProperty { value: self.value, params: self.other_params.to_model()?, @@ -192,7 +192,7 @@ impl ToModel for crate::parser::types::SequenceProperty<'_> { impl ToModel for crate::parser::types::StatusProperty<'_> { type Model = crate::model::property::StatusProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::StatusProperty { value: self.value.clone(), params: self.other_params.to_model()?, @@ -203,7 +203,7 @@ impl ToModel for crate::parser::types::StatusProperty<'_> { impl ToModel for crate::parser::types::SummaryProperty<'_> { type Model = crate::model::property::SummaryProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::SummaryProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -214,7 +214,7 @@ impl ToModel for crate::parser::types::SummaryProperty<'_> { impl ToModel for crate::parser::types::TimeTransparencyProperty<'_> { type Model = crate::model::property::TimeTransparencyProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeTransparencyProperty { value: self.value.clone(), params: self.other_params.to_model()?, @@ -225,7 +225,7 @@ impl ToModel for crate::parser::types::TimeTransparencyProperty<'_> { impl ToModel for crate::parser::types::UrlProperty<'_> { type Model = crate::model::property::UrlProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::UrlProperty { value: self.value.to_string(), params: self.other_params.to_model()?, @@ -236,7 +236,7 @@ impl ToModel for crate::parser::types::UrlProperty<'_> { impl ToModel for crate::parser::types::RecurrenceIdProperty<'_> { type Model = crate::model::property::RecurrenceIdProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let dt = self.value.to_model()?; Ok(crate::model::property::RecurrenceIdProperty { @@ -249,7 +249,7 @@ impl ToModel for crate::parser::types::RecurrenceIdProperty<'_> { impl ToModel for crate::parser::types::RecurrenceRuleProperty<'_> { type Model = crate::model::property::RecurrenceRuleProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::RecurrenceRuleProperty { value: self.value.to_model()?, params: self.other_params.to_model()?, @@ -260,7 +260,7 @@ impl ToModel for crate::parser::types::RecurrenceRuleProperty<'_> { impl ToModel for crate::parser::types::DateTimeEndProperty<'_> { type Model = crate::model::property::DateTimeEndProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let dt = self.value.to_model()?; Ok(crate::model::property::DateTimeEndProperty { @@ -273,7 +273,7 @@ impl ToModel for crate::parser::types::DateTimeEndProperty<'_> { impl ToModel for crate::parser::types::DurationProperty<'_> { type Model = crate::model::property::DurationProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::DurationProperty { value: self.value.to_model()?, params: self.other_params.to_model()?, @@ -284,7 +284,7 @@ impl ToModel for crate::parser::types::DurationProperty<'_> { impl ToModel for crate::parser::types::AttachProperty<'_> { type Model = crate::model::property::AttachProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let value = match self.value { crate::parser::types::AttachValue::Uri(uri) => convert_string(uri), crate::parser::types::AttachValue::Binary(binary) => convert_string(binary), @@ -300,7 +300,7 @@ impl ToModel for crate::parser::types::AttachProperty<'_> { impl ToModel for crate::parser::types::AttendeeProperty<'_> { type Model = crate::model::property::AttendeeProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::AttendeeProperty { value: convert_string(self.value), params: self.params.to_model()?, @@ -311,7 +311,7 @@ impl ToModel for crate::parser::types::AttendeeProperty<'_> { impl ToModel for crate::parser::types::CategoriesProperty<'_> { type Model = crate::model::property::CategoriesProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::CategoriesProperty { value: self.value.iter().map(|v| convert_string(v)).collect(), params: self.params.to_model()?, @@ -322,7 +322,7 @@ impl ToModel for crate::parser::types::CategoriesProperty<'_> { impl ToModel for crate::parser::types::CommentProperty<'_> { type Model = crate::model::property::CommentProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::CommentProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -333,7 +333,7 @@ impl ToModel for crate::parser::types::CommentProperty<'_> { impl ToModel for crate::parser::types::ContactProperty<'_> { type Model = crate::model::property::ContactProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ContactProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -344,7 +344,7 @@ impl ToModel for crate::parser::types::ContactProperty<'_> { impl ToModel for crate::parser::types::ExceptionDateTimesProperty<'_> { type Model = crate::model::property::ExceptionDateTimesProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ExceptionDateTimesProperty { value: self .value @@ -359,7 +359,7 @@ impl ToModel for crate::parser::types::ExceptionDateTimesProperty<'_> { impl ToModel for crate::parser::types::RequestStatusProperty<'_> { type Model = crate::model::property::RequestStatusProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::RequestStatusProperty { value: RequestStatusPropertyValue { status_code: self.status_code.clone(), @@ -374,7 +374,7 @@ impl ToModel for crate::parser::types::RequestStatusProperty<'_> { impl ToModel for crate::parser::types::RelatedToProperty<'_> { type Model = crate::model::property::RelatedToProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::RelatedToProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -385,7 +385,7 @@ impl ToModel for crate::parser::types::RelatedToProperty<'_> { impl ToModel for crate::parser::types::ResourcesProperty<'_> { type Model = crate::model::property::ResourcesProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ResourcesProperty { value: self.value.iter().map(|v| convert_string(v)).collect(), params: self.params.to_model()?, @@ -396,7 +396,7 @@ impl ToModel for crate::parser::types::ResourcesProperty<'_> { impl ToModel for crate::parser::types::XProperty<'_> { type Model = crate::model::property::XProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::XProperty { name: convert_string(self.name), value: convert_string(&self.value), @@ -408,7 +408,7 @@ impl ToModel for crate::parser::types::XProperty<'_> { impl ToModel for crate::parser::types::IanaProperty<'_> { type Model = crate::model::property::IanaProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::IanaProperty { name: convert_string(self.name), value: convert_string(&self.value), @@ -420,7 +420,7 @@ impl ToModel for crate::parser::types::IanaProperty<'_> { impl ToModel for crate::parser::types::RecurrenceDateTimesProperty<'_> { type Model = crate::model::property::RecurrenceDateTimesProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let date_times = self.value.to_model()?; let (date_times, periods) = if date_times.iter().all(|dt| dt.0.is_some()) { @@ -434,7 +434,7 @@ impl ToModel for crate::parser::types::RecurrenceDateTimesProperty<'_> { date_times.iter().map(|dt| dt.1.clone().unwrap()).collect(), ) } else { - return Err(anyhow::anyhow!("Invalid recurrence date-times")); + return Err(AetoliaError::other("Invalid recurrence date-times")); }; Ok(crate::model::property::RecurrenceDateTimesProperty { @@ -451,7 +451,7 @@ impl ToModel for crate::parser::types::RecurrenceDateTimesProperty<'_> { impl ToModel for crate::parser::types::Duration { type Model = crate::model::property::Duration; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::Duration { sign: self.sign, weeks: self.weeks, @@ -469,7 +469,7 @@ impl ToModel for crate::parser::types::DateOrDateTimeOrPeriod { Option, ); - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { match self { crate::parser::types::DateOrDateTimeOrPeriod::Date(date) => { Ok((Some((date.try_into()?, None, false)), None)) @@ -488,7 +488,7 @@ impl ToModel for crate::parser::types::DateOrDateTimeOrPeriod { impl ToModel for crate::parser::types::ProductIdProperty<'_> { type Model = crate::model::property::ProductIdProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ProductIdProperty { value: convert_string(&self.value), params: self.other_params.to_model()?, @@ -499,7 +499,7 @@ impl ToModel for crate::parser::types::ProductIdProperty<'_> { impl ToModel for crate::parser::types::VersionProperty<'_> { type Model = crate::model::property::VersionProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::VersionProperty { min_version: self.min_version.map(convert_string), max_version: convert_string(self.max_version), @@ -511,7 +511,7 @@ impl ToModel for crate::parser::types::VersionProperty<'_> { impl ToModel for crate::parser::types::CalendarScaleProperty<'_> { type Model = crate::model::property::CalendarScaleProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::CalendarScaleProperty { value: convert_string(&self.value), params: self.other_params.to_model()?, @@ -522,7 +522,7 @@ impl ToModel for crate::parser::types::CalendarScaleProperty<'_> { impl ToModel for crate::parser::types::MethodProperty<'_> { type Model = crate::model::property::MethodProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::MethodProperty { value: convert_string(self.value), params: self.other_params.to_model()?, @@ -533,7 +533,7 @@ impl ToModel for crate::parser::types::MethodProperty<'_> { impl ToModel for crate::parser::types::CalendarProperty<'_> { type Model = crate::model::property::CalendarProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { match self { crate::parser::types::CalendarProperty::ProductId(product_id) => Ok( crate::model::property::CalendarProperty::ProductId(product_id.to_model()?), @@ -560,7 +560,7 @@ impl ToModel for crate::parser::types::CalendarProperty<'_> { impl ToModel for crate::parser::types::DateTimeCompletedProperty<'_> { type Model = crate::model::property::DateTimeCompletedProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let (date, time, is_utc) = (&self.value).try_into()?; Ok(crate::model::property::DateTimeCompletedProperty { @@ -573,7 +573,7 @@ impl ToModel for crate::parser::types::DateTimeCompletedProperty<'_> { impl ToModel for crate::parser::types::PercentCompleteProperty<'_> { type Model = crate::model::property::PercentCompleteProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::PercentCompleteProperty { value: self.value, params: self.other_params.to_model()?, @@ -584,7 +584,7 @@ impl ToModel for crate::parser::types::PercentCompleteProperty<'_> { impl ToModel for crate::parser::types::DateTimeDueProperty<'_> { type Model = crate::model::property::DateTimeDueProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let dt = self.value.to_model()?; Ok(crate::model::property::DateTimeDueProperty { @@ -597,7 +597,7 @@ impl ToModel for crate::parser::types::DateTimeDueProperty<'_> { impl ToModel for crate::parser::types::FreeBusyTimeProperty<'_> { type Model = crate::model::property::FreeBusyTimeProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::FreeBusyTimeProperty { value: self.value.to_model()?, params: self.params.to_model()?, @@ -608,7 +608,7 @@ impl ToModel for crate::parser::types::FreeBusyTimeProperty<'_> { impl ToModel for crate::parser::types::TimeZoneIdProperty<'_> { type Model = crate::model::property::TimeZoneIdProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeZoneIdProperty { value: TimeZoneIdPropertyValue { id: convert_string(&self.value), @@ -622,7 +622,7 @@ impl ToModel for crate::parser::types::TimeZoneIdProperty<'_> { impl ToModel for crate::parser::types::TimeZoneUrlProperty<'_> { type Model = crate::model::property::TimeZoneUrlProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeZoneUrlProperty { value: convert_string(self.value), params: self.other_params.to_model()?, @@ -633,7 +633,7 @@ impl ToModel for crate::parser::types::TimeZoneUrlProperty<'_> { impl ToModel for crate::parser::types::TimeZoneOffsetProperty<'_> { type Model = crate::model::property::TimeZoneOffsetToProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeZoneOffsetToProperty { value: self.value.to_model()?, params: self.other_params.to_model()?, @@ -644,7 +644,7 @@ impl ToModel for crate::parser::types::TimeZoneOffsetProperty<'_> { impl ToModel for crate::parser::types::UtcOffset { type Model = crate::model::property::TimeZoneOffset; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeZoneOffset { sign: self.sign, hours: self.hours as u8, @@ -657,7 +657,7 @@ impl ToModel for crate::parser::types::UtcOffset { impl ToModel for crate::parser::types::TimeZoneNameProperty<'_> { type Model = crate::model::property::TimeZoneNameProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::TimeZoneNameProperty { value: convert_string(&self.value), params: self.params.to_model()?, @@ -668,7 +668,7 @@ impl ToModel for crate::parser::types::TimeZoneNameProperty<'_> { impl ToModel for crate::parser::types::ActionProperty<'_> { type Model = crate::model::property::ActionProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::ActionProperty { value: self.value.to_model()?, params: self.other_params.to_model()?, @@ -679,7 +679,7 @@ impl ToModel for crate::parser::types::ActionProperty<'_> { impl ToModel for crate::parser::types::Action<'_> { type Model = crate::model::property::Action; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(match self { crate::parser::types::Action::Audio => crate::model::property::Action::Audio, crate::parser::types::Action::Display => crate::model::property::Action::Display, @@ -697,7 +697,7 @@ impl ToModel for crate::parser::types::Action<'_> { impl ToModel for crate::parser::types::TriggerProperty<'_> { type Model = crate::model::property::TriggerProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { match &self.value { crate::parser::types::DurationOrDateTime::DateTime(date_time) => { let (date, time, is_utc) = date_time.try_into()?; @@ -719,7 +719,7 @@ impl ToModel for crate::parser::types::TriggerProperty<'_> { impl ToModel for crate::parser::types::RepeatProperty<'_> { type Model = crate::model::property::RepeatProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::RepeatProperty { value: self.value, params: self.other_params.to_model()?, @@ -730,7 +730,7 @@ impl ToModel for crate::parser::types::RepeatProperty<'_> { impl ToModel for crate::parser::types::ComponentProperty<'_> { type Model = crate::model::property::ComponentProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { match self { crate::parser::types::ComponentProperty::DateTimeStamp(date_time_stamp) => { Ok(crate::model::property::ComponentProperty::DateTimeStamp( @@ -907,7 +907,7 @@ impl ToModel for crate::parser::types::ComponentProperty<'_> { impl ToModel for ContentLine<'_> { type Model = crate::model::property::IanaProperty; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(crate::model::property::IanaProperty { name: convert_string(self.property_name), value: convert_string(&self.value), @@ -919,7 +919,7 @@ impl ToModel for ContentLine<'_> { impl ToModel for crate::parser::types::Period { type Model = Period; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(Period { start: (&self.start).try_into()?, end: match &self.end { @@ -937,7 +937,7 @@ impl ToModel for crate::parser::types::Period { impl ToModel for crate::parser::types::DateOrDateTime { type Model = CalendarDateTime; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { Ok(match self { crate::parser::types::DateOrDateTime::Date(date) => { (date.try_into()?, None, false).into() @@ -951,26 +951,26 @@ impl ToModel for crate::parser::types::DateOrDateTime { } impl TryFrom<&crate::parser::types::Date> for time::Date { - type Error = anyhow::Error; + type Error = AetoliaError; fn try_from(value: &crate::parser::types::Date) -> Result { time::Date::from_calendar_date( value.year as i32, - time::Month::try_from(value.month).context("Invalid month")?, + time::Month::try_from(value.month).map_err(AetoliaError::time)?, value.day, ) - .context("Invalid date") + .map_err(AetoliaError::time) } } impl TryFrom<&crate::parser::types::DateTime> for (time::Date, time::Time, bool) { - type Error = anyhow::Error; + type Error = AetoliaError; fn try_from(value: &crate::parser::types::DateTime) -> Result { Ok(( time::Date::try_from(&value.date)?, time::Time::from_hms(value.time.hour, value.time.minute, value.time.second) - .context("Invalid time")?, + .map_err(AetoliaError::time)?, value.time.is_utc, )) } diff --git a/src/convert/property/recur.rs b/src/convert/property/recur.rs index 9e52696..1537b61 100644 --- a/src/convert/property/recur.rs +++ b/src/convert/property/recur.rs @@ -1,12 +1,12 @@ use crate::convert::ToModel; +use crate::error::{AetoliaError, AetoliaResult}; use crate::model::property::RecurrenceRule; use crate::parser::types::RecurRulePart; -use anyhow::Context; impl ToModel for Vec { type Model = RecurrenceRule; - fn to_model(&self) -> anyhow::Result { + fn to_model(&self) -> AetoliaResult { let mut rule = RecurrenceRule::empty_with_capacity(self.len()); for part in self.iter() { match part { @@ -48,8 +48,8 @@ impl ToModel for Vec { rule = rule.set_by_month( month .iter() - .map(|m| time::Month::try_from(*m).context("Invalid month")) - .collect::>>()?, + .map(|m| time::Month::try_from(*m).map_err(AetoliaError::time)) + .collect::>>()?, ); } RecurRulePart::BySetPos(by_set_pos) => { diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..819f5b0 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,38 @@ +use std::fmt::{Display, Formatter}; +use std::io::Error; + +#[derive(Debug)] +pub enum AetoliaError { + IO(Error), + + Other(String), +} + +impl From for AetoliaError { + fn from(value: Error) -> Self { + Self::IO(value) + } +} + +impl AetoliaError { + pub fn time(e: impl Into) -> Self { + AetoliaError::Other(e.into().to_string()) + } + + pub fn other(msg: impl ToString) -> AetoliaError { + AetoliaError::Other(msg.to_string()) + } +} + +impl Display for AetoliaError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AetoliaError::IO(e) => e.fmt(f), + AetoliaError::Other(msg) => write!(f, "{}", msg), + } + } +} + +impl std::error::Error for AetoliaError {} + +pub type AetoliaResult = Result; diff --git a/src/lib.rs b/src/lib.rs index a7c7770..7928c04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,8 @@ pub mod serialize; /// Validation of iCalendar rules against the core representation. pub mod validate; +mod error; + #[cfg(test)] mod test_utils; @@ -35,6 +37,7 @@ mod test_utils; pub mod prelude { pub use crate::common::PropertyKind; pub use crate::common::*; + pub use crate::error::{AetoliaError, AetoliaResult}; pub use crate::model::access::*; pub use crate::model::component::*; pub use crate::model::object::*; diff --git a/src/model/property.rs b/src/model/property.rs index 163b3d9..583b4b7 100644 --- a/src/model/property.rs +++ b/src/model/property.rs @@ -17,6 +17,7 @@ use std::marker::PhantomData; mod duration; mod recur; +use crate::error::AetoliaResult; use crate::model::impl_property_access; pub use duration::*; pub use recur::*; @@ -1877,7 +1878,7 @@ impl Period { } } - pub fn expand(&self) -> anyhow::Result> { + pub fn expand(&self) -> AetoliaResult> { if self.start.2 { Ok(Some(( self.start.into(), diff --git a/src/ops.rs b/src/ops.rs index 87820c0..1f7d9eb 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -1,4 +1,5 @@ use crate::convert::ToModel; +use crate::error::{AetoliaError, AetoliaResult}; use crate::model::object::ICalObject; use crate::parser::{content_line_first_pass, ical_stream, Error}; use std::io::Read; @@ -13,17 +14,17 @@ use std::io::Read; /// you want to ensure that the data is reasonably correct. If you plan to ingest the data into /// another system, you should validate the result of this function because the parser /// and model permit a lot of inputs that could confuse other systems. -pub fn load_ical(input: impl AsRef<[u8]>) -> anyhow::Result> { +pub fn load_ical(input: impl AsRef<[u8]>) -> AetoliaResult> { let (rem, content) = content_line_first_pass::(input.as_ref()) - .map_err(|e| anyhow::anyhow!("First pass failed: {:?}", e))?; + .map_err(|e| AetoliaError::other(format!("First pass failed: {e}")))?; if !rem.is_empty() { - return Err(anyhow::anyhow!("Trailing data after first pass")); + return Err(AetoliaError::other("Trailing data after first pass")); } let (rem, stream) = ical_stream::(&content) - .map_err(|e| anyhow::anyhow!("Stream parsing failed: {:?}", e))?; + .map_err(|e| AetoliaError::other(format!("Stream parsing failed: {e}")))?; if !rem.is_empty() { - return Err(anyhow::anyhow!("Trailing data after stream")); + return Err(AetoliaError::other("Trailing data after stream")); } let model = stream.to_model()?; @@ -34,7 +35,7 @@ pub fn load_ical(input: impl AsRef<[u8]>) -> anyhow::Result> { /// Convenience function to load iCalendar data from a readable source. /// /// The data is read to the end and then passed to [load_ical]. -pub fn read_ical(mut input: R) -> anyhow::Result> { +pub fn read_ical(mut input: R) -> AetoliaResult> { let mut buffer = Vec::new(); input.read_to_end(&mut buffer)?; diff --git a/src/serialize.rs b/src/serialize.rs index c209128..b4e03c3 100644 --- a/src/serialize.rs +++ b/src/serialize.rs @@ -4,10 +4,11 @@ mod param; mod property; mod value; +use crate::error::AetoliaResult; use std::io::Write; pub trait WriteModel { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()>; + fn write_model(&self, writer: &mut W) -> AetoliaResult<()>; } #[cfg(test)] diff --git a/src/serialize/component.rs b/src/serialize/component.rs index 5889c0c..579519a 100644 --- a/src/serialize/component.rs +++ b/src/serialize/component.rs @@ -1,8 +1,9 @@ +use crate::error::AetoliaResult; use crate::serialize::WriteModel; use std::io::Write; impl WriteModel for crate::model::component::CalendarComponent { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::component::CalendarComponent; match self { diff --git a/src/serialize/object.rs b/src/serialize/object.rs index 742ddae..88e1223 100644 --- a/src/serialize/object.rs +++ b/src/serialize/object.rs @@ -1,8 +1,9 @@ +use crate::error::AetoliaResult; use crate::serialize::WriteModel; use std::io::Write; impl WriteModel for crate::model::object::ICalObject { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { writer.write_all(b"BEGIN:VCALENDAR")?; for property in &self.properties { writer.write_all(b"\r\n")?; @@ -19,7 +20,7 @@ impl WriteModel for crate::model::object::ICalObject { } impl WriteModel for crate::model::property::CalendarProperty { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::property::CalendarProperty; match self { diff --git a/src/serialize/param.rs b/src/serialize/param.rs index 9107a0e..2a371f1 100644 --- a/src/serialize/param.rs +++ b/src/serialize/param.rs @@ -1,3 +1,4 @@ +use crate::error::AetoliaResult; use crate::model::param::{ AlternateRepresentationParam, CalendarUserTypeParam, CommonNameParam, DelegatedFromParam, DelegatedToParam, DirectoryEntryReferenceParam, EncodingParam, FormatTypeParam, @@ -9,7 +10,7 @@ use crate::serialize::WriteModel; use std::io::Write; impl WriteModel for crate::model::param::Param { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::param::Param; match self { diff --git a/src/serialize/property.rs b/src/serialize/property.rs index f8d9542..0c6089b 100644 --- a/src/serialize/property.rs +++ b/src/serialize/property.rs @@ -1,9 +1,10 @@ +use crate::error::AetoliaResult; use crate::model::property::RecurrenceDateTimesPropertyValue; use crate::serialize::WriteModel; use std::io::Write; impl WriteModel for crate::model::property::ComponentProperty { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::property::ComponentProperty; match self { @@ -345,7 +346,7 @@ impl WriteModel for crate::model::property::ComponentProperty { } impl WriteModel for &[crate::model::param::Param] { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { for param in self.iter() { writer.write_all(b";")?; param.write_model(writer)?; diff --git a/src/serialize/value.rs b/src/serialize/value.rs index 77cfb8f..bc2cdce 100644 --- a/src/serialize/value.rs +++ b/src/serialize/value.rs @@ -1,10 +1,11 @@ use crate::common::LanguageTag; +use crate::error::AetoliaResult; use crate::serialize::WriteModel; use std::io::Write; use std::ops::Add; impl WriteModel for (time::Date, time::Time, bool) { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { self.0.write_model(writer)?; writer.write_all(b"T")?; self.1.write_model(writer)?; @@ -17,7 +18,7 @@ impl WriteModel for (time::Date, time::Time, bool) { } impl WriteModel for (time::Date, Option, bool) { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { match self.1 { Some(time) => { (self.0, time, self.2).write_model(writer)?; @@ -32,7 +33,7 @@ impl WriteModel for (time::Date, Option, bool) { } impl WriteModel for time::Date { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { let year = self.year(); write!(writer, "{:0>4}", year)?; write!(writer, "{:0>2}", self.month() as u8)?; @@ -43,7 +44,7 @@ impl WriteModel for time::Date { } impl WriteModel for time::Time { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { match self.hour() { h @ 10..=23 => { write!(writer, "{}", h)?; @@ -76,13 +77,13 @@ impl WriteModel for time::Time { } impl WriteModel for crate::common::CalendarDateTime { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { (*self.date(), self.time_opt().cloned(), self.is_utc()).write_model(writer) } } impl WriteModel for crate::common::Value { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Value; match self { @@ -141,7 +142,7 @@ impl WriteModel for crate::common::Value { } impl WriteModel for LanguageTag { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { writer.write_all(self.language.as_bytes())?; if let Some(ext_lang) = &self.ext_lang { writer.write_all(b"-")?; @@ -172,7 +173,7 @@ impl WriteModel for LanguageTag { } impl WriteModel for crate::common::Range { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Range; match self { @@ -186,7 +187,7 @@ impl WriteModel for crate::common::Range { } impl WriteModel for crate::common::Encoding { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Encoding; match self { @@ -203,7 +204,7 @@ impl WriteModel for crate::common::Encoding { } impl WriteModel for crate::common::CalendarUserType { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::CalendarUserType; match self { @@ -235,7 +236,7 @@ impl WriteModel for crate::common::CalendarUserType { } impl WriteModel for crate::common::Role { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Role; match self { @@ -264,7 +265,7 @@ impl WriteModel for crate::common::Role { } impl WriteModel for crate::common::ParticipationStatusUnknown { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::ParticipationStatusUnknown; match self { @@ -302,7 +303,7 @@ impl WriteModel for crate::common::ParticipationStatusUnknown { } impl WriteModel for bool { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { if *self { writer.write_all(b"TRUE")?; } else { @@ -314,7 +315,7 @@ impl WriteModel for bool { } impl WriteModel for crate::common::RelationshipType { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::RelationshipType; match self { @@ -340,7 +341,7 @@ impl WriteModel for crate::common::RelationshipType { } impl WriteModel for crate::common::FreeBusyTimeType { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::FreeBusyTimeType; match self { @@ -369,7 +370,7 @@ impl WriteModel for crate::common::FreeBusyTimeType { } impl WriteModel for crate::common::TriggerRelationship { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::TriggerRelationship; match self { @@ -386,7 +387,7 @@ impl WriteModel for crate::common::TriggerRelationship { } impl WriteModel for crate::model::property::Classification { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::property::Classification; match self { @@ -412,7 +413,7 @@ impl WriteModel for crate::model::property::Classification { } impl WriteModel for crate::common::TimeTransparency { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::TimeTransparency; match self { @@ -429,7 +430,7 @@ impl WriteModel for crate::common::TimeTransparency { } impl WriteModel for crate::model::property::RecurrenceRule { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::property::RecurRulePart; for part in &self.parts { @@ -508,7 +509,7 @@ impl WriteModel for crate::model::property::RecurrenceRule { } impl WriteModel for crate::common::RecurFreq { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::RecurFreq; match self { @@ -540,7 +541,7 @@ impl WriteModel for crate::common::RecurFreq { } impl + std::fmt::Display> WriteModel for Vec { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { if let Some(value) = self.first() { write!(writer, "{}", value)?; } @@ -553,7 +554,7 @@ impl + std::fmt::Display> WriteModel for Vec { } impl WriteModel for crate::common::OffsetWeekday { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { if let Some(offset_weeks) = &self.offset_weeks { write!(writer, "{}", offset_weeks)?; } @@ -565,7 +566,7 @@ impl WriteModel for crate::common::OffsetWeekday { } impl WriteModel for crate::common::Weekday { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Weekday; match self { @@ -597,7 +598,7 @@ impl WriteModel for crate::common::Weekday { } impl WriteModel for time::Month { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { write!(writer, "{}", (*self) as u8)?; Ok(()) @@ -605,8 +606,8 @@ impl WriteModel for time::Month { } impl WriteModel for crate::model::property::Duration { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { - let write_time: fn(&mut W, &crate::model::property::Duration) -> anyhow::Result<()> = + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { + let write_time: fn(&mut W, &crate::model::property::Duration) -> AetoliaResult<()> = |writer, duration| { if duration.hours.is_some() || duration.minutes.is_some() @@ -660,7 +661,7 @@ impl WriteModel for crate::model::property::Duration { } impl WriteModel for crate::common::Status { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::common::Status; match self { @@ -695,7 +696,7 @@ impl WriteModel for crate::common::Status { } impl WriteModel for crate::model::property::Period { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { self.start.write_model(writer)?; writer.write_all(b"/")?; match &self.end { @@ -712,7 +713,7 @@ impl WriteModel for crate::model::property::Period { } impl WriteModel for crate::model::property::TimeZoneOffset { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { if self.sign < 0 { writer.write_all(b"-")?; } else { @@ -730,7 +731,7 @@ impl WriteModel for crate::model::property::TimeZoneOffset { } impl WriteModel for crate::model::property::Action { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { use crate::model::property::Action; match self { @@ -756,7 +757,7 @@ impl WriteModel for crate::model::property::Action { } impl WriteModel for String { - fn write_model(&self, writer: &mut W) -> anyhow::Result<()> { + fn write_model(&self, writer: &mut W) -> AetoliaResult<()> { let mut out = Vec::with_capacity(self.len()); for c in self.chars() { if matches!(c as u8, b';' | b'\\' | b',') { diff --git a/src/validate.rs b/src/validate.rs index c36491d..3a04f4a 100644 --- a/src/validate.rs +++ b/src/validate.rs @@ -16,9 +16,11 @@ use crate::validate::component_properties::validate_component_properties; use crate::validate::params::validate_params; use std::collections::{HashMap, HashSet}; +use crate::error::AetoliaResult; +use crate::prelude::AetoliaError; pub use error::*; -pub fn validate_model(ical_object: &ICalObject) -> anyhow::Result> { +pub fn validate_model(ical_object: &ICalObject) -> AetoliaResult> { let mut errors = Vec::new(); let time_zone_ids = ical_object @@ -59,7 +61,7 @@ pub fn validate_model(ical_object: &ICalObject) -> anyhow::Result anyhow::Result<()> { + -> AetoliaResult<()> { for (alarm_index, alarm) in alarms.iter().enumerate() { errors.extend_from_slice( ICalendarError::many_from_nested_component_property_errors( @@ -249,33 +251,35 @@ pub fn validate_model(ical_object: &ICalObject) -> anyhow::Result anyhow::Result<()> { +fn validate_time(time: &crate::parser::types::Time) -> AetoliaResult<()> { if time.hour > 23 { - anyhow::bail!("Hour must be between 0 and 23"); + return Err(AetoliaError::other("Hour must be between 0 and 23")); } if time.minute > 59 { - anyhow::bail!("Minute must be between 0 and 59"); + return Err(AetoliaError::other("Minute must be between 0 and 59")); } if time.second > 60 { - anyhow::bail!("Second must be between 0 and 60"); + return Err(AetoliaError::other("Second must be between 0 and 60")); } Ok(()) } -fn validate_utc_offset(offset: &crate::parser::types::UtcOffset) -> anyhow::Result<()> { +fn validate_utc_offset(offset: &crate::parser::types::UtcOffset) -> AetoliaResult<()> { if offset.sign < 0 && (offset.hours == 0 && offset.minutes == 0 && (offset.seconds.is_none() || offset.seconds == Some(0))) { - anyhow::bail!("UTC offset must have a non-zero value if it is negative"); + return Err(AetoliaError::other( + "UTC offset must have a non-zero value if it is negative", + )); } if offset.minutes > 59 { - anyhow::bail!("Minutes must be between 0 and 59"); + return Err(AetoliaError::other("Minutes must be between 0 and 59")); } Ok(()) diff --git a/src/validate/component_properties.rs b/src/validate/component_properties.rs index cb2154a..ec8e011 100644 --- a/src/validate/component_properties.rs +++ b/src/validate/component_properties.rs @@ -1,4 +1,5 @@ use crate::common::{PropertyKind, Status, Value}; +use crate::error::AetoliaResult; use crate::model::param::Param; use crate::model::property::{ Action, ComponentProperty, DateTimeCompletedProperty, DateTimeDueProperty, DateTimeEndProperty, @@ -42,7 +43,7 @@ pub(super) fn validate_component_properties( calendar_info: &CalendarInfo, property_location: PropertyLocation, properties: &[ComponentProperty], -) -> anyhow::Result> { +) -> AetoliaResult> { let mut errors = Vec::new(); if properties.is_empty() { @@ -1860,7 +1861,7 @@ fn validate_free_busy_time( errors: &mut Vec, free_busy_time_property: &FreeBusyTimeProperty, index: usize, -) -> anyhow::Result<()> { +) -> AetoliaResult<()> { if !free_busy_time_property.value.iter().all(|p| { p.start.2 && match p.end { @@ -1883,7 +1884,7 @@ fn validate_free_busy_time( .value .iter() .map(|p| p.expand().map(|v| v.unwrap())) - .collect::>>()?; + .collect::>>()?; let all_ordered = date_times.windows(2).all(|w| { let (s1, e1) = &w[0]; let (s2, e2) = &w[1]; diff --git a/src/validate/recur.rs b/src/validate/recur.rs index ee596c1..18c1d1e 100644 --- a/src/validate/recur.rs +++ b/src/validate/recur.rs @@ -1,4 +1,5 @@ use crate::common::RecurFreq; +use crate::error::AetoliaResult; use crate::model::property::{ ComponentProperty, DateTimeQuery, DateTimeStartProperty, RecurRulePart, RecurrenceRule, }; @@ -15,7 +16,7 @@ pub(super) fn validate_recurrence_rule( maybe_dt_start: Option<&DateTimeStartProperty>, property_location: PropertyLocation, property_index: usize, -) -> anyhow::Result<()> { +) -> AetoliaResult<()> { let dt_start = if let Some(dt_start) = maybe_dt_start { dt_start } else { diff --git a/src/validate/value.rs b/src/validate/value.rs index 3cffeb0..23cf722 100644 --- a/src/validate/value.rs +++ b/src/validate/value.rs @@ -1,5 +1,6 @@ use crate::common::{Encoding, Value}; use crate::convert::ToModel; +use crate::error::{AetoliaError, AetoliaResult}; use crate::model::param::{EncodingParam, Param}; use crate::model::property::{ AttendeeProperty, ComponentProperty, DateTimeDueProperty, DateTimeEndProperty, @@ -21,7 +22,6 @@ use crate::validate::{ ComponentPropertyError, ComponentPropertyLocation, ICalendarErrorSeverity, PropertyLocation, WithinPropertyLocation, }; -use anyhow::Context; use nom::character::streaming::char; use nom::multi::separated_list1; use nom::AsBytes; @@ -32,7 +32,7 @@ pub(super) fn check_declared_value( maybe_dt_start: Option<&DateTimeStartProperty>, property: &ComponentProperty, property_index: usize, -) -> anyhow::Result<()> { +) -> AetoliaResult<()> { let declared_value_type = get_declared_value_type(property); let push_redundant_error_msg = @@ -61,9 +61,11 @@ pub(super) fn check_declared_value( if *encoding != Encoding::Base64 { let mut msg = b"Property is declared to have a binary value but the encoding is set to ".to_vec(); - encoding - .write_model(&mut msg) - .context("Failed to write encoding to model")?; + encoding.write_model(&mut msg).map_err(|e| { + AetoliaError::other(format!( + "Failed to write encoding to model: {e}" + )) + })?; msg.extend_from_slice(", instead of BASE64".as_bytes()); errors.push(ComponentPropertyError { @@ -807,7 +809,7 @@ pub(super) fn check_declared_value( if let Err(e) = validate_time(time) { errors.push(ComponentPropertyError { message: format!( - "Found an invalid time at index {} - {:?}", + "Found an invalid time at index {} - {}", index, e ), severity: ICalendarErrorSeverity::Warning, @@ -831,7 +833,7 @@ pub(super) fn check_declared_value( if let Err(e) = validate_time(time) { errors.push(ComponentPropertyError { message: format!( - "Found an invalid time at index {} - {:?}", + "Found an invalid time at index {} - {}", index, e ), severity: ICalendarErrorSeverity::Warning, @@ -937,7 +939,7 @@ pub(super) fn check_declared_value( Ok(offset) => { if let Err(e) = validate_utc_offset(&offset) { errors.push(ComponentPropertyError { - message: format!("Found an invalid UTC offset - {:?}", e), + message: format!("Found an invalid UTC offset - {e}"), severity: ICalendarErrorSeverity::Warning, location: Some(ComponentPropertyLocation { index: property_index, @@ -957,7 +959,7 @@ pub(super) fn check_declared_value( Ok(offset) => { if let Err(e) = validate_utc_offset(&offset) { errors.push(ComponentPropertyError { - message: format!("Found an invalid UTC offset - {:?}", e), + message: format!("Found an invalid UTC offset - {e}"), severity: ICalendarErrorSeverity::Warning, location: Some(ComponentPropertyLocation { index: property_index, @@ -1092,14 +1094,14 @@ fn is_period_valued(property_value: &String) -> bool { fn is_recur_valued( property_value: &String, -) -> anyhow::Result> { +) -> AetoliaResult> { let mut content = property_value.as_bytes().to_vec(); content.push(b'`'); let result = prop_value_recur::(content.as_bytes()); match result { Ok((rest, rule)) if rest.len() == 1 => Ok(rule), - _ => anyhow::bail!("Not a valid recur rule"), + _ => Err(AetoliaError::other("Not a valid recur rule")), } } @@ -1115,14 +1117,14 @@ fn is_text_valued(property_value: &String) -> bool { } } -fn is_time_valued(property_value: &String) -> anyhow::Result> { +fn is_time_valued(property_value: &String) -> AetoliaResult> { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); let result = separated_list1(char(','), prop_value_time::).parse(content.as_bytes()); match result { Ok((rest, times)) if rest.len() == 1 => Ok(times), - _ => anyhow::bail!("Not a valid time"), + _ => Err(AetoliaError::other("Not a valid time")), } } @@ -1137,15 +1139,13 @@ fn is_uri_valued(property_value: &str) -> bool { } } -fn is_utc_offset_valued( - property_value: &String, -) -> anyhow::Result { +fn is_utc_offset_valued(property_value: &String) -> AetoliaResult { let mut content = property_value.as_bytes().to_vec(); content.push(b';'); let result = prop_value_utc_offset::(content.as_bytes()); match result { Ok((rest, offset)) if rest.len() == 1 => Ok(offset), - _ => anyhow::bail!("Not a valid UTC offset"), + _ => Err(AetoliaError::other("Not a valid UTC offset")), } }