diff --git a/crates/caldav/src/calendar/methods/import.rs b/crates/caldav/src/calendar/methods/import.rs index 8cadeb6..4a82cb2 100644 --- a/crates/caldav/src/calendar/methods/import.rs +++ b/crates/caldav/src/calendar/methods/import.rs @@ -45,13 +45,13 @@ pub async fn route_import( // Extract calendar metadata let displayname = cal .get_property("X-WR-CALNAME") - .and_then(|prop| prop.value.to_owned()); + .and_then(|prop| prop.value.clone()); let description = cal .get_property("X-WR-CALDESC") - .and_then(|prop| prop.value.to_owned()); + .and_then(|prop| prop.value.clone()); let timezone_id = cal .get_property("X-WR-TIMEZONE") - .and_then(|prop| prop.value.to_owned()); + .and_then(|prop| prop.value.clone()); // These properties should not appear in the expanded calendar objects cal.remove_property("X-WR-CALNAME"); cal.remove_property("X-WR-CALDESC"); diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index 6381c5d..0ec65c9 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -79,8 +79,8 @@ pub async fn route_mkcalendar( _ => unreachable!("We never call with another method"), }; - if let Some("") = request.displayname.as_deref() { - request.displayname = None + if request.displayname.as_deref() == Some("") { + request.displayname = None; } let timezone_id = if let Some(tzid) = request.calendar_timezone_id { @@ -110,8 +110,8 @@ pub async fn route_mkcalendar( }; let calendar = Calendar { - id: cal_id.to_owned(), - principal: principal.to_owned(), + id: cal_id.clone(), + principal: principal.clone(), meta: CalendarMetadata { order: request.calendar_order.unwrap_or(0), displayname: request.displayname, diff --git a/crates/caldav/src/calendar/methods/post.rs b/crates/caldav/src/calendar/methods/post.rs index f246ea2..014d10a 100644 --- a/crates/caldav/src/calendar/methods/post.rs +++ b/crates/caldav/src/calendar/methods/post.rs @@ -49,12 +49,11 @@ pub async fn route_post( }; let subscription = Subscription { - id: sub_id.to_owned(), + id: sub_id.clone(), push_resource: request .subscription .web_push_subscription - .push_resource - .to_owned(), + .push_resource.clone(), topic: calendar_resource.cal.push_topic, expiration: expires.naive_local(), public_key: request diff --git a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs index e8b2d43..dd5af84 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs @@ -4,10 +4,10 @@ use rustical_ical::CalendarObject; use rustical_store::CalendarStore; use rustical_xml::XmlDeserialize; -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] // -pub(crate) struct CalendarMultigetRequest { +pub struct CalendarMultigetRequest { #[xml(ty = "untagged")] pub(crate) prop: PropfindType, #[xml(flatten)] @@ -27,13 +27,13 @@ pub async fn get_objects_calendar_multiget( for href in &cal_query.href { if let Some(filename) = href.strip_prefix(path) { - let filename = filename.trim_start_matches("/"); + let filename = filename.trim_start_matches('/'); if let Some(object_id) = filename.strip_suffix(".ics") { match store.get_object(principal, cal_id, object_id, false).await { Ok(object) => result.push(object), Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()), Err(err) => return Err(err.into()), - }; + } } else { not_found.push(href.to_owned()); continue; diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/elements.rs b/crates/caldav/src/calendar/methods/report/calendar_query/elements.rs index edfa64e..64ce9c4 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/elements.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/elements.rs @@ -3,18 +3,17 @@ use rustical_dav::xml::PropfindType; use rustical_ical::{CalendarObject, UtcDateTime}; use rustical_store::calendar_store::CalendarQuery; use rustical_xml::XmlDeserialize; -use std::ops::Deref; -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] -pub(crate) struct TimeRangeElement { +pub struct TimeRangeElement { #[xml(ty = "attr")] pub(crate) start: Option, #[xml(ty = "attr")] pub(crate) end: Option, } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] // https://www.rfc-editor.org/rfc/rfc4791#section-9.7.3 pub struct ParamFilterElement { @@ -27,7 +26,7 @@ pub struct ParamFilterElement { pub(crate) name: String, } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] pub struct TextMatchElement { #[xml(ty = "attr")] @@ -40,7 +39,7 @@ pub struct TextMatchElement { #[derive(XmlDeserialize, Clone, Debug, PartialEq)] #[allow(dead_code)] // https://www.rfc-editor.org/rfc/rfc4791#section-9.7.2 -pub(crate) struct PropFilterElement { +pub struct PropFilterElement { #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] pub(crate) is_not_defined: Option<()>, #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] @@ -57,7 +56,7 @@ pub(crate) struct PropFilterElement { #[derive(XmlDeserialize, Clone, Debug, PartialEq)] #[allow(dead_code)] // https://datatracker.ietf.org/doc/html/rfc4791#section-9.7.1 -pub(crate) struct CompFilterElement { +pub struct CompFilterElement { #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] pub(crate) is_not_defined: Option<()>, #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] @@ -81,7 +80,7 @@ impl CompFilterElement { // Client is asking for something different than a vcalendar (None, false) => return false, _ => {} - }; + } if self.time_range.is_some() { // should be applied on VEVENT/VTODO but not on VCALENDAR @@ -111,20 +110,20 @@ impl CompFilterElement { // Client is asking for something different than a vcalendar (None, false) => return false, _ => {} - }; + } // TODO: Implement prop-filter (and comp-filter?) at some point if let Some(time_range) = &self.time_range { if let Some(start) = &time_range.start && let Some(last_occurence) = cal_object.get_last_occurence().unwrap_or(None) - && start.deref() > &last_occurence.utc() + && **start > last_occurence.utc() { return false; } if let Some(end) = &time_range.end && let Some(first_occurence) = cal_object.get_first_occurence().unwrap_or(None) - && end.deref() < &first_occurence.utc() + && **end < first_occurence.utc() { return false; } @@ -136,7 +135,7 @@ impl CompFilterElement { #[derive(XmlDeserialize, Clone, Debug, PartialEq)] #[allow(dead_code)] // https://datatracker.ietf.org/doc/html/rfc4791#section-9.7 -pub(crate) struct FilterElement { +pub struct FilterElement { // This comp-filter matches on VCALENDAR #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] pub(crate) comp_filter: CompFilterElement, @@ -151,7 +150,7 @@ impl FilterElement { impl From<&FilterElement> for CalendarQuery { fn from(value: &FilterElement) -> Self { let comp_filter_vcalendar = &value.comp_filter; - for comp_filter in comp_filter_vcalendar.comp_filter.iter() { + for comp_filter in &comp_filter_vcalendar.comp_filter { // A calendar object cannot contain both VEVENT and VTODO, so we only have to handle // whatever we get first if matches!(comp_filter.name.as_str(), "VEVENT" | "VTODO") @@ -159,7 +158,7 @@ impl From<&FilterElement> for CalendarQuery { { let start = time_range.start.as_ref().map(|start| start.date_naive()); let end = time_range.end.as_ref().map(|end| end.date_naive()); - return CalendarQuery { + return Self { time_start: start, time_end: end, }; @@ -188,7 +187,7 @@ impl From<&CalendarQueryRequest> for CalendarQuery { value .filter .as_ref() - .map(CalendarQuery::from) + .map(Self::from) .unwrap_or_default() } } diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs b/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs index 302f33d..34d4835 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs @@ -3,7 +3,7 @@ use rustical_ical::CalendarObject; use rustical_store::CalendarStore; mod elements; -pub(crate) use elements::*; +pub use elements::*; pub async fn get_objects_calendar_query( cal_query: &CalendarQueryRequest, diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index 9af5cba..5952aea 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -41,11 +41,11 @@ pub(crate) enum ReportRequest { } impl ReportRequest { - fn props(&self) -> &PropfindType { + const fn props(&self) -> &PropfindType { match &self { - ReportRequest::CalendarMultiget(CalendarMultigetRequest { prop, .. }) => prop, - ReportRequest::CalendarQuery(CalendarQueryRequest { prop, .. }) => prop, - ReportRequest::SyncCollection(SyncCollectionRequest { prop, .. }) => prop, + Self::CalendarMultiget(CalendarMultigetRequest { prop, .. }) => prop, + Self::CalendarQuery(CalendarQueryRequest { prop, .. }) => prop, + Self::SyncCollection(SyncCollectionRequest { prop, .. }) => prop, } } } diff --git a/crates/caldav/src/calendar/prop.rs b/crates/caldav/src/calendar/prop.rs index e16e658..fa74bf6 100644 --- a/crates/caldav/src/calendar/prop.rs +++ b/crates/caldav/src/calendar/prop.rs @@ -3,13 +3,13 @@ use rustical_ical::CalendarObjectType; use rustical_xml::{XmlDeserialize, XmlSerialize}; use strum_macros::VariantArray; -#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, From, Into)] +#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, Eq, From, Into)] pub struct SupportedCalendarComponent { #[xml(ty = "attr")] pub name: CalendarObjectType, } -#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, PartialEq, Eq)] pub struct SupportedCalendarComponentSet { #[xml(ns = "rustical_dav::namespace::NS_CALDAV", flatten)] pub comp: Vec, @@ -36,7 +36,7 @@ impl From for Vec { } } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct CalendarData { #[xml(ty = "attr")] content_type: String, @@ -53,13 +53,13 @@ impl Default for CalendarData { } } -#[derive(Debug, Clone, XmlSerialize, Default, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, Default, PartialEq, Eq)] pub struct SupportedCalendarData { #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] calendar_data: CalendarData, } -#[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq, VariantArray)] pub enum ReportMethod { #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] CalendarQuery, diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index 1f36a69..785ca77 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -71,7 +71,7 @@ pub struct CalendarResource { impl ResourceName for CalendarResource { fn get_name(&self) -> String { - self.cal.id.to_owned() + self.cal.id.clone() } } @@ -89,7 +89,7 @@ impl SyncTokenExtension for CalendarResource { impl DavPushExtension for CalendarResource { fn get_topic(&self) -> String { - self.cal.push_topic.to_owned() + self.cal.push_topic.clone() } } @@ -135,7 +135,7 @@ impl Resource for CalendarResource { } CalendarPropName::CalendarTimezone => { CalendarProp::CalendarTimezone(self.cal.timezone_id.as_ref().and_then(|tzid| { - vtimezones_rs::VTIMEZONES.get(tzid).map(|tz| tz.to_string()) + vtimezones_rs::VTIMEZONES.get(tzid).map(|tz| (*tz).to_string()) })) } // chrono_tz uses the IANA database @@ -159,7 +159,7 @@ impl Resource for CalendarResource { CalendarProp::SupportedReportSet(SupportedReportSet::all()) } CalendarPropName::Source => CalendarProp::Source( - self.cal.subscription_url.to_owned().map(HrefElement::from), + self.cal.subscription_url.clone().map(HrefElement::from), ), CalendarPropName::MinDateTime => { CalendarProp::MinDateTime(CalDateTime::from(DateTime::::MIN_UTC).format()) diff --git a/crates/caldav/src/calendar/service.rs b/crates/caldav/src/calendar/service.rs index b9c2396..ec6384d 100644 --- a/crates/caldav/src/calendar/service.rs +++ b/crates/caldav/src/calendar/service.rs @@ -35,7 +35,7 @@ impl Clone for CalendarResourceService CalendarResourceService { - pub fn new(cal_store: Arc, sub_store: Arc) -> Self { + pub const fn new(cal_store: Arc, sub_store: Arc) -> Self { Self { cal_store, sub_store, diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index 2496ee0..1053076 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -78,12 +78,9 @@ pub async fn put_event( true }; - let object = match CalendarObject::from_ics(body.clone()) { - Ok(obj) => obj, - Err(_) => { - debug!("invalid calendar data:\n{body}"); - return Err(Error::PreconditionFailed(Precondition::ValidCalendarData)); - } + let object = if let Ok(obj) = CalendarObject::from_ics(body.clone()) { obj } else { + debug!("invalid calendar data:\n{body}"); + return Err(Error::PreconditionFailed(Precondition::ValidCalendarData)); }; if object.get_id() != object_id { error!( diff --git a/crates/caldav/src/calendar_object/prop.rs b/crates/caldav/src/calendar_object/prop.rs index ebd181d..0922e6d 100644 --- a/crates/caldav/src/calendar_object/prop.rs +++ b/crates/caldav/src/calendar_object/prop.rs @@ -2,7 +2,7 @@ use rustical_dav::extensions::CommonPropertiesProp; use rustical_ical::UtcDateTime; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone, EnumVariants, PropName)] #[xml(unit_variants_ident = "CalendarObjectPropName")] pub enum CalendarObjectProp { // WebDAV (RFC 2518) @@ -25,7 +25,7 @@ pub enum CalendarObjectPropWrapper { } #[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq, Hash)] -pub(crate) struct ExpandElement { +pub struct ExpandElement { #[xml(ty = "attr")] pub(crate) start: UtcDateTime, #[xml(ty = "attr")] diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index b58cec6..cd3690f 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -1,4 +1,4 @@ -use super::prop::*; +use super::prop::{CalendarObjectPropWrapper, CalendarObjectPropWrapperName, CalendarObjectPropName, CalendarObjectProp, CalendarData}; use crate::Error; use derive_more::derive::{From, Into}; use rustical_dav::{ diff --git a/crates/caldav/src/calendar_object/service.rs b/crates/caldav/src/calendar_object/service.rs index 11625ba..f6527c8 100644 --- a/crates/caldav/src/calendar_object/service.rs +++ b/crates/caldav/src/calendar_object/service.rs @@ -35,7 +35,7 @@ impl Clone for CalendarObjectResourceService { } impl CalendarObjectResourceService { - pub fn new(cal_store: Arc) -> Self { + pub const fn new(cal_store: Arc) -> Self { Self { cal_store } } } diff --git a/crates/caldav/src/error.rs b/crates/caldav/src/error.rs index 7273007..a3a56c5 100644 --- a/crates/caldav/src/error.rs +++ b/crates/caldav/src/error.rs @@ -62,23 +62,23 @@ pub enum Error { } impl Error { - pub fn status_code(&self) -> StatusCode { + #[must_use] pub fn status_code(&self) -> StatusCode { match self { - Error::StoreError(err) => match err { + Self::StoreError(err) => match err { rustical_store::Error::NotFound => StatusCode::NOT_FOUND, rustical_store::Error::AlreadyExists => StatusCode::CONFLICT, rustical_store::Error::ReadOnly => StatusCode::FORBIDDEN, _ => StatusCode::INTERNAL_SERVER_ERROR, }, - Error::ChronoParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, - Error::DavError(err) => StatusCode::try_from(err.status_code().as_u16()) + Self::ChronoParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::DavError(err) => StatusCode::try_from(err.status_code().as_u16()) .expect("Just converting between versions"), - Error::Unauthorized => StatusCode::UNAUTHORIZED, - Error::XmlDecodeError(_) => StatusCode::BAD_REQUEST, - Error::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, - Error::NotFound => StatusCode::NOT_FOUND, - Error::IcalError(err) => err.status_code(), - Error::PreconditionFailed(_err) => StatusCode::PRECONDITION_FAILED, + Self::Unauthorized => StatusCode::UNAUTHORIZED, + Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, + Self::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, + Self::NotFound => StatusCode::NOT_FOUND, + Self::IcalError(err) => err.status_code(), + Self::PreconditionFailed(_err) => StatusCode::PRECONDITION_FAILED, } } } diff --git a/crates/caldav/src/lib.rs b/crates/caldav/src/lib.rs index d527551..9db5f27 100644 --- a/crates/caldav/src/lib.rs +++ b/crates/caldav/src/lib.rs @@ -38,8 +38,8 @@ pub fn caldav_router::new(PrincipalResourceService { auth_provider: auth_provider.clone(), - sub_store: subscription_store.clone(), - cal_store: store.clone(), + sub_store: subscription_store, + cal_store: store, simplified_home_set, }) .axum_router() diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index b1cd88e..728765b 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -24,7 +24,7 @@ pub struct PrincipalResource { impl ResourceName for PrincipalResource { fn get_name(&self) -> String { - self.principal.id.to_owned() + self.principal.id.clone() } } @@ -56,7 +56,7 @@ impl Resource for PrincipalResource { PrincipalPropWrapperName::Principal(prop) => { PrincipalPropWrapper::Principal(match prop { PrincipalPropName::CalendarUserType => { - PrincipalProp::CalendarUserType(self.principal.principal_type.to_owned()) + PrincipalProp::CalendarUserType(self.principal.principal_type.clone()) } PrincipalPropName::PrincipalUrl => { PrincipalProp::PrincipalUrl(principal_url.into()) diff --git a/crates/caldav/src/principal/prop.rs b/crates/caldav/src/principal/prop.rs index 6777dfb..6285d8b 100644 --- a/crates/caldav/src/principal/prop.rs +++ b/crates/caldav/src/principal/prop.rs @@ -6,7 +6,7 @@ use rustical_store::auth::PrincipalType; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; use strum_macros::VariantArray; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone, EnumVariants, PropName)] #[xml(unit_variants_ident = "PrincipalPropName")] pub enum PrincipalProp { // Scheduling Extensions to CalDAV (RFC 6638) @@ -34,7 +34,7 @@ pub enum PrincipalProp { CalendarHomeSet(CalendarHomeSet), } -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone)] pub struct CalendarHomeSet(#[xml(ty = "untagged", flatten)] pub Vec); #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] @@ -44,7 +44,7 @@ pub enum PrincipalPropWrapper { Common(CommonPropertiesProp), } -#[derive(XmlSerialize, PartialEq, Clone, VariantArray)] +#[derive(XmlSerialize, PartialEq, Eq, Clone, VariantArray)] pub enum ReportMethod { // We don't actually support principal-match #[xml(ns = "rustical_dav::namespace::NS_DAV")] diff --git a/crates/carddav/src/address_object/prop.rs b/crates/carddav/src/address_object/prop.rs index b2068c9..0a33f5e 100644 --- a/crates/carddav/src/address_object/prop.rs +++ b/crates/carddav/src/address_object/prop.rs @@ -1,7 +1,7 @@ use rustical_dav::extensions::CommonPropertiesProp; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone, EnumVariants, PropName)] #[xml(unit_variants_ident = "AddressObjectPropName")] pub enum AddressObjectProp { // WebDAV (RFC 2518) diff --git a/crates/carddav/src/addressbook/methods/mkcol.rs b/crates/carddav/src/addressbook/methods/mkcol.rs index aa4720e..6fdc9af 100644 --- a/crates/carddav/src/addressbook/methods/mkcol.rs +++ b/crates/carddav/src/addressbook/methods/mkcol.rs @@ -8,7 +8,7 @@ use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore, auth::Pri use rustical_xml::{XmlDeserialize, XmlDocument, XmlRootTag}; use tracing::instrument; -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct Resourcetype { #[xml(ns = "rustical_dav::namespace::NS_CARDDAV")] addressbook: Option<()>, @@ -16,7 +16,7 @@ pub struct Resourcetype { collection: Option<()>, } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct MkcolAddressbookProp { #[xml(ns = "rustical_dav::namespace::NS_DAV")] resourcetype: Option, @@ -27,7 +27,7 @@ pub struct MkcolAddressbookProp { description: Option, } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct PropElement { #[xml(ns = "rustical_dav::namespace::NS_DAV")] prop: T, @@ -53,13 +53,13 @@ pub async fn route_mkcol( } let mut request = MkcolRequest::parse_str(&body)?.set.prop; - if let Some("") = request.displayname.as_deref() { - request.displayname = None + if request.displayname.as_deref() == Some("") { + request.displayname = None; } let addressbook = Addressbook { - id: addressbook_id.to_owned(), - principal: principal.to_owned(), + id: addressbook_id.clone(), + principal: principal.clone(), displayname: request.displayname, description: request.description, deleted_at: None, diff --git a/crates/carddav/src/addressbook/methods/post.rs b/crates/carddav/src/addressbook/methods/post.rs index de6b9ec..7b89a5e 100644 --- a/crates/carddav/src/addressbook/methods/post.rs +++ b/crates/carddav/src/addressbook/methods/post.rs @@ -45,12 +45,11 @@ pub async fn route_post( }; let subscription = Subscription { - id: sub_id.to_owned(), + id: sub_id.clone(), push_resource: request .subscription .web_push_subscription - .push_resource - .to_owned(), + .push_resource.clone(), topic: addressbook_resource.0.push_topic, expiration: expires.naive_local(), public_key: request diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index a3bf595..ae41dcb 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -13,7 +13,7 @@ use rustical_ical::AddressObject; use rustical_store::{AddressbookStore, auth::Principal}; use rustical_xml::XmlDeserialize; -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] #[allow(dead_code)] #[xml(ns = "rustical_dav::namespace::NS_DAV")] pub struct AddressbookMultigetRequest { @@ -35,7 +35,7 @@ pub async fn get_objects_addressbook_multiget( for href in &addressbook_multiget.href { if let Some(filename) = href.strip_prefix(path) { - let filename = filename.trim_start_matches("/"); + let filename = filename.trim_start_matches('/'); if let Some(object_id) = filename.strip_suffix(".vcf") { match store .get_object(principal, addressbook_id, object_id, false) @@ -44,7 +44,7 @@ pub async fn get_objects_addressbook_multiget( Ok(object) => result.push(object), Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()), Err(err) => return Err(err.into()), - }; + } } else { not_found.push(href.to_owned()); continue; diff --git a/crates/carddav/src/addressbook/methods/report/mod.rs b/crates/carddav/src/addressbook/methods/report/mod.rs index a242783..283f806 100644 --- a/crates/carddav/src/addressbook/methods/report/mod.rs +++ b/crates/carddav/src/addressbook/methods/report/mod.rs @@ -26,10 +26,10 @@ pub(crate) enum ReportRequest { } impl ReportRequest { - fn props(&self) -> &PropfindType { + const fn props(&self) -> &PropfindType { match self { - ReportRequest::AddressbookMultiget(AddressbookMultigetRequest { prop, .. }) => prop, - ReportRequest::SyncCollection(SyncCollectionRequest { prop, .. }) => prop, + Self::AddressbookMultiget(AddressbookMultigetRequest { prop, .. }) => prop, + Self::SyncCollection(SyncCollectionRequest { prop, .. }) => prop, } } } diff --git a/crates/carddav/src/addressbook/prop.rs b/crates/carddav/src/addressbook/prop.rs index 21f3013..def843f 100644 --- a/crates/carddav/src/addressbook/prop.rs +++ b/crates/carddav/src/addressbook/prop.rs @@ -29,7 +29,7 @@ pub enum AddressbookPropWrapper { Common(CommonPropertiesProp), } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct AddressDataType { #[xml(ty = "attr")] pub content_type: &'static str, @@ -37,7 +37,7 @@ pub struct AddressDataType { pub version: &'static str, } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct SupportedAddressData { #[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)] address_data_type: &'static [AddressDataType], @@ -60,7 +60,7 @@ impl Default for SupportedAddressData { } } -#[derive(Debug, Clone, XmlSerialize, PartialEq, VariantArray)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq, VariantArray)] pub enum ReportMethod { #[xml(ns = "rustical_dav::namespace::NS_CARDDAV")] AddressbookMultiget, diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 411698c..d62904b 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -17,7 +17,7 @@ pub struct AddressbookResource(pub(crate) Addressbook); impl ResourceName for AddressbookResource { fn get_name(&self) -> String { - self.0.id.to_owned() + self.0.id.clone() } } @@ -29,7 +29,7 @@ impl SyncTokenExtension for AddressbookResource { impl DavPushExtension for AddressbookResource { fn get_topic(&self) -> String { - self.0.push_topic.to_owned() + self.0.push_topic.clone() } } @@ -65,7 +65,7 @@ impl Resource for AddressbookResource { AddressbookProp::SupportedReportSet(SupportedReportSet::all()) } AddressbookPropName::AddressbookDescription => { - AddressbookProp::AddressbookDescription(self.0.description.to_owned()) + AddressbookProp::AddressbookDescription(self.0.description.clone()) } AddressbookPropName::SupportedAddressData => { AddressbookProp::SupportedAddressData(SupportedAddressData::default()) diff --git a/crates/carddav/src/addressbook/service.rs b/crates/carddav/src/addressbook/service.rs index 8f3b0d4..4ae19d6 100644 --- a/crates/carddav/src/addressbook/service.rs +++ b/crates/carddav/src/addressbook/service.rs @@ -26,7 +26,7 @@ pub struct AddressbookResourceService AddressbookResourceService { - pub fn new(addr_store: Arc, sub_store: Arc) -> Self { + pub const fn new(addr_store: Arc, sub_store: Arc) -> Self { Self { addr_store, sub_store, diff --git a/crates/carddav/src/error.rs b/crates/carddav/src/error.rs index 5bc0688..a79df8f 100644 --- a/crates/carddav/src/error.rs +++ b/crates/carddav/src/error.rs @@ -30,20 +30,20 @@ pub enum Error { } impl Error { - pub fn status_code(&self) -> StatusCode { + #[must_use] pub const fn status_code(&self) -> StatusCode { match self { - Error::StoreError(err) => match err { + Self::StoreError(err) => match err { rustical_store::Error::NotFound => StatusCode::NOT_FOUND, rustical_store::Error::AlreadyExists => StatusCode::CONFLICT, rustical_store::Error::ReadOnly => StatusCode::FORBIDDEN, _ => StatusCode::INTERNAL_SERVER_ERROR, }, - Error::ChronoParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, - Error::DavError(err) => err.status_code(), - Error::Unauthorized => StatusCode::UNAUTHORIZED, - Error::XmlDecodeError(_) => StatusCode::BAD_REQUEST, - Error::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, - Error::NotFound => StatusCode::NOT_FOUND, + Self::ChronoParseError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::DavError(err) => err.status_code(), + Self::Unauthorized => StatusCode::UNAUTHORIZED, + Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, + Self::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, + Self::NotFound => StatusCode::NOT_FOUND, Self::IcalError(err) => err.status_code(), } } diff --git a/crates/carddav/src/lib.rs b/crates/carddav/src/lib.rs index ce87be6..f9638c2 100644 --- a/crates/carddav/src/lib.rs +++ b/crates/carddav/src/lib.rs @@ -38,15 +38,15 @@ pub fn carddav_router, ) -> Router { let principal_service = PrincipalResourceService::new( - store.clone(), + store, auth_provider.clone(), - subscription_store.clone(), + subscription_store, ); Router::new() .nest( prefix, RootResourceService::<_, Principal, CardDavPrincipalUri>::new( - principal_service.clone(), + principal_service, ) .axum_router() .layer(AuthenticationLayer::new(auth_provider)) diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index 39daa7f..bb43c10 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -20,7 +20,7 @@ pub struct PrincipalResource { impl ResourceName for PrincipalResource { fn get_name(&self) -> String { - self.principal.id.to_owned() + self.principal.id.clone() } } diff --git a/crates/carddav/src/principal/prop.rs b/crates/carddav/src/principal/prop.rs index 8bf79a4..2689589 100644 --- a/crates/carddav/src/principal/prop.rs +++ b/crates/carddav/src/principal/prop.rs @@ -4,7 +4,7 @@ use rustical_dav::{ }; use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone, EnumVariants, PropName)] #[xml(unit_variants_ident = "PrincipalPropName")] pub enum PrincipalProp { // WebDAV Access Control (RFC 3744) @@ -27,7 +27,7 @@ pub enum PrincipalProp { PrincipalAddress(Option), } -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone)] pub struct AddressbookHomeSet(#[xml(ty = "untagged", flatten)] pub Vec); #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumVariants, PropName)] diff --git a/crates/carddav/src/principal/service.rs b/crates/carddav/src/principal/service.rs index 18f734f..22b07bb 100644 --- a/crates/carddav/src/principal/service.rs +++ b/crates/carddav/src/principal/service.rs @@ -34,7 +34,7 @@ impl Clon impl PrincipalResourceService { - pub fn new(addr_store: Arc, auth_provider: Arc, sub_store: Arc) -> Self { + pub const fn new(addr_store: Arc, auth_provider: Arc, sub_store: Arc) -> Self { Self { addr_store, auth_provider, diff --git a/crates/dav/src/error.rs b/crates/dav/src/error.rs index 207ffb1..ab614cd 100644 --- a/crates/dav/src/error.rs +++ b/crates/dav/src/error.rs @@ -35,7 +35,7 @@ pub enum Error { } impl Error { - pub fn status_code(&self) -> StatusCode { + #[must_use] pub const fn status_code(&self) -> StatusCode { match self { Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR, Self::NotFound => StatusCode::NOT_FOUND, @@ -50,8 +50,8 @@ impl Error { | XmlError::InvalidValue(_) => StatusCode::UNPROCESSABLE_ENTITY, _ => StatusCode::BAD_REQUEST, }, - Error::PropReadOnly => StatusCode::CONFLICT, - Error::PreconditionFailed => StatusCode::PRECONDITION_FAILED, + Self::PropReadOnly => StatusCode::CONFLICT, + Self::PreconditionFailed => StatusCode::PRECONDITION_FAILED, Self::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Forbidden => StatusCode::FORBIDDEN, } @@ -68,7 +68,7 @@ impl axum::response::IntoResponse for Error { } let mut resp = axum::response::Response::builder().status(self.status_code()); - if matches!(&self, &Error::Unauthorized) { + if matches!(&self, &Self::Unauthorized) { resp.headers_mut() .expect("This must always work") .insert("WWW-Authenticate", "Basic".parse().unwrap()); diff --git a/crates/dav/src/extensions/common.rs b/crates/dav/src/extensions/common.rs index 91898f3..b9ad129 100644 --- a/crates/dav/src/extensions/common.rs +++ b/crates/dav/src/extensions/common.rs @@ -40,7 +40,7 @@ pub trait CommonPropertiesExtension: Resource { CommonPropertiesProp::Resourcetype(self.get_resourcetype()) } CommonPropertiesPropName::Displayname => { - CommonPropertiesProp::Displayname(self.get_displayname().map(|s| s.to_string())) + CommonPropertiesProp::Displayname(self.get_displayname().map(std::string::ToString::to_string)) } CommonPropertiesPropName::CurrentUserPrincipal => { CommonPropertiesProp::CurrentUserPrincipal( diff --git a/crates/dav/src/extensions/synctoken.rs b/crates/dav/src/extensions/synctoken.rs index ca9e48e..a75d1c4 100644 --- a/crates/dav/src/extensions/synctoken.rs +++ b/crates/dav/src/extensions/synctoken.rs @@ -1,6 +1,6 @@ use rustical_xml::{EnumVariants, PropName, XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, PropName, EnumVariants)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone, PropName, EnumVariants)] #[xml(unit_variants_ident = "SyncTokenExtensionPropName")] pub enum SyncTokenExtensionProp { // Collection Synchronization (RFC 6578) diff --git a/crates/dav/src/header/depth.rs b/crates/dav/src/header/depth.rs index 21592c6..70baa92 100644 --- a/crates/dav/src/header/depth.rs +++ b/crates/dav/src/header/depth.rs @@ -19,7 +19,7 @@ impl IntoResponse for InvalidDepthHeader { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Depth { Zero, One, @@ -29,9 +29,9 @@ pub enum Depth { impl ValueSerialize for Depth { fn serialize(&self) -> String { match self { - Depth::Zero => "0", - Depth::One => "1", - Depth::Infinity => "infinity", + Self::Zero => "0", + Self::One => "1", + Self::Infinity => "infinity", } .to_owned() } @@ -55,9 +55,9 @@ impl TryFrom<&[u8]> for Depth { fn try_from(value: &[u8]) -> Result { match value { - b"0" => Ok(Depth::Zero), - b"1" => Ok(Depth::One), - b"Infinity" | b"infinity" => Ok(Depth::Infinity), + b"0" => Ok(Self::Zero), + b"1" => Ok(Self::One), + b"Infinity" | b"infinity" => Ok(Self::Infinity), _ => Err(InvalidDepthHeader), } } diff --git a/crates/dav/src/header/overwrite.rs b/crates/dav/src/header/overwrite.rs index 06cbb9e..3cd646e 100644 --- a/crates/dav/src/header/overwrite.rs +++ b/crates/dav/src/header/overwrite.rs @@ -14,7 +14,7 @@ impl IntoResponse for InvalidOverwriteHeader { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct Overwrite(pub bool); impl Default for Overwrite { diff --git a/crates/dav/src/privileges.rs b/crates/dav/src/privileges.rs index beb3347..bc7ebb2 100644 --- a/crates/dav/src/privileges.rs +++ b/crates/dav/src/privileges.rs @@ -41,13 +41,13 @@ impl XmlSerialize for UserPrivilegeSet { } } -#[derive(Debug, Clone, Default, PartialEq)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct UserPrivilegeSet { privileges: HashSet, } impl UserPrivilegeSet { - pub fn has(&self, privilege: &UserPrivilege) -> bool { + #[must_use] pub fn has(&self, privilege: &UserPrivilege) -> bool { if (privilege == &UserPrivilege::WriteProperties || privilege == &UserPrivilege::WriteContent) && self.privileges.contains(&UserPrivilege::Write) @@ -57,13 +57,13 @@ impl UserPrivilegeSet { self.privileges.contains(privilege) || self.privileges.contains(&UserPrivilege::All) } - pub fn all() -> Self { + #[must_use] pub fn all() -> Self { Self { privileges: HashSet::from([UserPrivilege::All]), } } - pub fn owner_only(is_owner: bool) -> Self { + #[must_use] pub fn owner_only(is_owner: bool) -> Self { if is_owner { Self::all() } else { @@ -71,7 +71,7 @@ impl UserPrivilegeSet { } } - pub fn owner_read(is_owner: bool) -> Self { + #[must_use] pub fn owner_read(is_owner: bool) -> Self { if is_owner { Self::read_only() } else { @@ -79,7 +79,7 @@ impl UserPrivilegeSet { } } - pub fn owner_write_properties(is_owner: bool) -> Self { + #[must_use] pub fn owner_write_properties(is_owner: bool) -> Self { // Content is read-only but we can write properties if is_owner { Self::write_properties() @@ -88,7 +88,7 @@ impl UserPrivilegeSet { } } - pub fn read_only() -> Self { + #[must_use] pub fn read_only() -> Self { Self { privileges: HashSet::from([ UserPrivilege::Read, @@ -98,7 +98,7 @@ impl UserPrivilegeSet { } } - pub fn write_properties() -> Self { + #[must_use] pub fn write_properties() -> Self { Self { privileges: HashSet::from([ UserPrivilege::Read, diff --git a/crates/dav/src/resource/axum_methods.rs b/crates/dav/src/resource/axum_methods.rs index 638f9ee..98b6fed 100644 --- a/crates/dav/src/resource/axum_methods.rs +++ b/crates/dav/src/resource/axum_methods.rs @@ -9,42 +9,42 @@ pub type MethodFunction = pub trait AxumMethods: Sized + Send + Sync + 'static { #[inline] - fn report() -> Option> { + #[must_use] fn report() -> Option> { None } #[inline] - fn get() -> Option> { + #[must_use] fn get() -> Option> { None } #[inline] - fn post() -> Option> { + #[must_use] fn post() -> Option> { None } #[inline] - fn mkcol() -> Option> { + #[must_use] fn mkcol() -> Option> { None } #[inline] - fn mkcalendar() -> Option> { + #[must_use] fn mkcalendar() -> Option> { None } #[inline] - fn put() -> Option> { + #[must_use] fn put() -> Option> { None } #[inline] - fn import() -> Option> { + #[must_use] fn import() -> Option> { None } #[inline] - fn allow_header() -> Allow { + #[must_use] fn allow_header() -> Allow { let mut allow = vec![ Method::from_str("PROPFIND").unwrap(), Method::from_str("PROPPATCH").unwrap(), diff --git a/crates/dav/src/resource/axum_service.rs b/crates/dav/src/resource/axum_service.rs index 20487b5..8cbdb37 100644 --- a/crates/dav/src/resource/axum_service.rs +++ b/crates/dav/src/resource/axum_service.rs @@ -23,7 +23,7 @@ pub struct AxumService { } impl AxumService { - pub fn new(resource_service: RS) -> Self { + pub const fn new(resource_service: RS) -> Self { Self { resource_service } } } @@ -103,7 +103,7 @@ where } } _ => {} - }; + } Box::pin(async move { Ok(Response::builder() .status(StatusCode::METHOD_NOT_ALLOWED) diff --git a/crates/dav/src/resource/methods/copy.rs b/crates/dav/src/resource/methods/copy.rs index daa11a8..bec1372 100644 --- a/crates/dav/src/resource/methods/copy.rs +++ b/crates/dav/src/resource/methods/copy.rs @@ -12,7 +12,7 @@ use serde::Deserialize; use tracing::instrument; #[instrument(skip(path, resource_service,))] -pub(crate) async fn axum_route_copy( +pub async fn axum_route_copy( Path(path): Path, State(resource_service): State, depth: Option, diff --git a/crates/dav/src/resource/methods/delete.rs b/crates/dav/src/resource/methods/delete.rs index d7b5c47..febc887 100644 --- a/crates/dav/src/resource/methods/delete.rs +++ b/crates/dav/src/resource/methods/delete.rs @@ -7,7 +7,7 @@ use axum_extra::TypedHeader; use headers::{IfMatch, IfNoneMatch}; use http::HeaderMap; -pub(crate) async fn axum_route_delete( +pub async fn axum_route_delete( Path(path): Path, State(resource_service): State, principal: R::Principal, @@ -24,8 +24,7 @@ pub(crate) async fn axum_route_delete( } let no_trash = header_map .get("X-No-Trashbin") - .map(|val| matches!(val.to_str(), Ok("1"))) - .unwrap_or(false); + .is_some_and(|val| matches!(val.to_str(), Ok("1"))); route_delete( &path, &principal, diff --git a/crates/dav/src/resource/methods/mod.rs b/crates/dav/src/resource/methods/mod.rs index a8610a3..2b770af 100644 --- a/crates/dav/src/resource/methods/mod.rs +++ b/crates/dav/src/resource/methods/mod.rs @@ -4,8 +4,8 @@ mod mv; mod propfind; mod proppatch; -pub(crate) use copy::axum_route_copy; -pub(crate) use delete::axum_route_delete; -pub(crate) use mv::axum_route_move; -pub(crate) use propfind::axum_route_propfind; -pub(crate) use proppatch::axum_route_proppatch; +pub use copy::axum_route_copy; +pub use delete::axum_route_delete; +pub use mv::axum_route_move; +pub use propfind::axum_route_propfind; +pub use proppatch::axum_route_proppatch; diff --git a/crates/dav/src/resource/methods/mv.rs b/crates/dav/src/resource/methods/mv.rs index a2ce1d4..a10d5d8 100644 --- a/crates/dav/src/resource/methods/mv.rs +++ b/crates/dav/src/resource/methods/mv.rs @@ -12,7 +12,7 @@ use serde::Deserialize; use tracing::instrument; #[instrument(skip(path, resource_service,))] -pub(crate) async fn axum_route_move( +pub async fn axum_route_move( Path(path): Path, State(resource_service): State, depth: Option, diff --git a/crates/dav/src/resource/methods/propfind.rs b/crates/dav/src/resource/methods/propfind.rs index 3f630cb..361c3e4 100644 --- a/crates/dav/src/resource/methods/propfind.rs +++ b/crates/dav/src/resource/methods/propfind.rs @@ -15,7 +15,7 @@ type RSMultistatus = MultistatusElement< >; #[instrument(skip(path, resource_service, puri))] -pub(crate) async fn axum_route_propfind( +pub async fn axum_route_propfind( Path(path): Path, State(resource_service): State, depth: Depth, @@ -36,7 +36,7 @@ pub(crate) async fn axum_route_propfind( .await } -pub(crate) async fn route_propfind( +pub async fn route_propfind( path_components: &R::PathComponents, path: &str, body: &str, diff --git a/crates/dav/src/resource/methods/proppatch.rs b/crates/dav/src/resource/methods/proppatch.rs index 4ba6adf..dc24821 100644 --- a/crates/dav/src/resource/methods/proppatch.rs +++ b/crates/dav/src/resource/methods/proppatch.rs @@ -61,7 +61,7 @@ enum Operation { #[xml(ns = "crate::namespace::NS_DAV")] struct PropertyupdateElement(#[xml(ty = "untagged", flatten)] Vec>); -pub(crate) async fn axum_route_proppatch( +pub async fn axum_route_proppatch( Path(path): Path, State(resource_service): State, principal: R::Principal, @@ -71,7 +71,7 @@ pub(crate) async fn axum_route_proppatch( route_proppatch(&path, uri.path(), &body, &principal, &resource_service).await } -pub(crate) async fn route_proppatch( +pub async fn route_proppatch( path_components: &R::PathComponents, path: &str, body: &str, @@ -96,7 +96,7 @@ pub(crate) async fn route_proppatch( let mut props_conflict = Vec::new(); let mut props_not_found = Vec::new(); - for operation in operations.into_iter() { + for operation in operations { match operation { Operation::Set(SetPropertyElement { prop: SetPropertyPropWrapperWrapper(properties), @@ -113,7 +113,7 @@ pub(crate) async fn route_proppatch( Err(Error::PropReadOnly) => props_conflict .push((ns.map(NamespaceOwned::from), propname.to_owned())), Err(err) => return Err(err.into()), - }; + } } SetPropertyPropWrapper::Invalid(invalid) => { let propname = invalid.tag_name(); @@ -131,7 +131,7 @@ pub(crate) async fn route_proppatch( // This happens in following cases: // - read-only properties with #[serde(skip_deserializing)] // - internal properties - props_conflict.push(full_propname) + props_conflict.push(full_propname); } else { props_not_found.push((None, propname)); } @@ -154,7 +154,7 @@ pub(crate) async fn route_proppatch( }, // I guess removing a nonexisting property should be successful :) Err(_) => props_ok.push((None, propname)), - }; + } } } } diff --git a/crates/dav/src/resource/mod.rs b/crates/dav/src/resource/mod.rs index f55a6f8..9717ce1 100644 --- a/crates/dav/src/resource/mod.rs +++ b/crates/dav/src/resource/mod.rs @@ -42,7 +42,7 @@ pub trait Resource: Clone + Send + 'static { fn get_resourcetype(&self) -> Resourcetype; - fn list_props() -> Vec<(Option>, &'static str)> { + #[must_use] fn list_props() -> Vec<(Option>, &'static str)> { Self::Prop::variant_names() } @@ -106,13 +106,13 @@ pub trait Resource: Clone + Send + 'static { fn parse_propfind( body: &str, ) -> Result::Names>, rustical_xml::XmlError> { - if !body.is_empty() { - PropfindElement::parse_str(body) - } else { + if body.is_empty() { Ok(PropfindElement { prop: PropfindType::Allprop, include: None, }) + } else { + PropfindElement::parse_str(body) } } @@ -139,7 +139,7 @@ pub trait Resource: Clone + Send + 'static { .collect_vec(); return Ok(ResponseElement { - href: path.to_owned(), + href: path.clone(), propstat: vec![PropstatWrapper::TagList(PropstatElement { prop: TagList::from(props), status: StatusCode::OK, @@ -181,7 +181,7 @@ pub trait Resource: Clone + Send + 'static { })); } Ok(ResponseElement { - href: path.to_owned(), + href: path.clone(), propstat: propstats, ..Default::default() }) diff --git a/crates/dav/src/resources/root.rs b/crates/dav/src/resources/root.rs index 9d59fd8..7a1eb47 100644 --- a/crates/dav/src/resources/root.rs +++ b/crates/dav/src/resources/root.rs @@ -63,7 +63,7 @@ pub struct RootResourceService RootResourceService { - pub fn new(principal_resource_service: PRS) -> Self { + pub const fn new(principal_resource_service: PRS) -> Self { Self(principal_resource_service, PhantomData, PhantomData) } } @@ -88,7 +88,7 @@ where async fn get_resource( &self, - _: &(), + (): &(), _show_deleted: bool, ) -> Result { Ok(RootResource::::default()) diff --git a/crates/dav/src/xml/group.rs b/crates/dav/src/xml/group.rs index fe54805..fce2d28 100644 --- a/crates/dav/src/xml/group.rs +++ b/crates/dav/src/xml/group.rs @@ -1,8 +1,8 @@ use crate::xml::HrefElement; use rustical_xml::{XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone)] pub struct GroupMembership(#[xml(ty = "untagged", flatten)] pub Vec); -#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone)] +#[derive(XmlDeserialize, XmlSerialize, PartialEq, Eq, Clone)] pub struct GroupMemberSet(#[xml(ty = "untagged", flatten)] pub Vec); diff --git a/crates/dav/src/xml/href.rs b/crates/dav/src/xml/href.rs index a392663..8faba2c 100644 --- a/crates/dav/src/xml/href.rs +++ b/crates/dav/src/xml/href.rs @@ -1,14 +1,14 @@ use derive_more::From; use rustical_xml::{XmlDeserialize, XmlSerialize}; -#[derive(XmlDeserialize, XmlSerialize, Debug, Clone, From, PartialEq)] +#[derive(XmlDeserialize, XmlSerialize, Debug, Clone, From, PartialEq, Eq)] pub struct HrefElement { #[xml(ns = "crate::namespace::NS_DAV")] pub href: String, } impl HrefElement { - pub fn new(href: String) -> Self { + #[must_use] pub const fn new(href: String) -> Self { Self { href } } } diff --git a/crates/dav/src/xml/multistatus.rs b/crates/dav/src/xml/multistatus.rs index 0e2cc0b..689a105 100644 --- a/crates/dav/src/xml/multistatus.rs +++ b/crates/dav/src/xml/multistatus.rs @@ -26,7 +26,7 @@ fn xml_serialize_status( namespaces: &HashMap, writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { - XmlSerialize::serialize(&format!("HTTP/1.1 {}", status), ns, tag, namespaces, writer) + XmlSerialize::serialize(&format!("HTTP/1.1 {status}"), ns, tag, namespaces, writer) } #[derive(XmlSerialize)] @@ -64,7 +64,7 @@ fn xml_serialize_optional_status( writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { XmlSerialize::serialize( - &val.map(|status| format!("HTTP/1.1 {}", status)), + &val.map(|status| format!("HTTP/1.1 {status}")), ns, tag, namespaces, diff --git a/crates/dav/src/xml/propfind.rs b/crates/dav/src/xml/propfind.rs index 8962268..7e85ed7 100644 --- a/crates/dav/src/xml/propfind.rs +++ b/crates/dav/src/xml/propfind.rs @@ -15,7 +15,7 @@ pub struct PropfindElement { pub include: Option>, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct PropElement( // valid pub Vec, @@ -82,7 +82,7 @@ impl XmlDeserialize for PropElement { } } -#[derive(Debug, Clone, XmlDeserialize, PartialEq)] +#[derive(Debug, Clone, XmlDeserialize, PartialEq, Eq)] pub enum PropfindType { #[xml(ns = "crate::namespace::NS_DAV")] Propname, diff --git a/crates/dav/src/xml/report_set.rs b/crates/dav/src/xml/report_set.rs index 4134c27..e5c5323 100644 --- a/crates/dav/src/xml/report_set.rs +++ b/crates/dav/src/xml/report_set.rs @@ -2,7 +2,7 @@ use rustical_xml::XmlSerialize; use strum::VariantArray; // RFC 3253 section-3.1.5 -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct SupportedReportSet { #[xml(flatten)] #[xml(ns = "crate::namespace::NS_DAV")] @@ -10,7 +10,7 @@ pub struct SupportedReportSet { } impl SupportedReportSet { - pub fn new(methods: Vec) -> Self { + #[must_use] pub fn new(methods: Vec) -> Self { Self { supported_report: methods .into_iter() @@ -27,7 +27,7 @@ impl SupportedReportSet { } } -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub struct ReportWrapper { #[xml(ns = "crate::namespace::NS_DAV")] report: T, diff --git a/crates/dav/src/xml/resourcetype.rs b/crates/dav/src/xml/resourcetype.rs index 8b9dcb5..0a00bde 100644 --- a/crates/dav/src/xml/resourcetype.rs +++ b/crates/dav/src/xml/resourcetype.rs @@ -1,9 +1,9 @@ use rustical_xml::XmlSerialize; -#[derive(Debug, Clone, PartialEq, XmlSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, XmlSerialize)] pub struct Resourcetype(#[xml(flatten, ty = "untagged")] pub &'static [ResourcetypeInner]); -#[derive(Debug, Clone, PartialEq, XmlSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, XmlSerialize)] pub struct ResourcetypeInner( #[xml(ty = "namespace")] pub Option>, #[xml(ty = "tag_name")] pub &'static str, diff --git a/crates/dav/src/xml/sync_collection.rs b/crates/dav/src/xml/sync_collection.rs index 50d14a8..30fa10b 100644 --- a/crates/dav/src/xml/sync_collection.rs +++ b/crates/dav/src/xml/sync_collection.rs @@ -2,7 +2,7 @@ use rustical_xml::{ValueDeserialize, ValueSerialize, XmlDeserialize, XmlRootTag} use super::PropfindType; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum SyncLevel { One, Infinity, @@ -25,15 +25,15 @@ impl ValueDeserialize for SyncLevel { impl ValueSerialize for SyncLevel { fn serialize(&self) -> String { match self { - SyncLevel::One => "1", - SyncLevel::Infinity => "Infinity", + Self::One => "1", + Self::Infinity => "Infinity", } .to_owned() } } // https://datatracker.ietf.org/doc/html/rfc5323#section-5.17 -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct LimitElement { #[xml(ns = "crate::namespace::NS_DAV")] pub nresults: NresultsElement, @@ -53,7 +53,7 @@ impl From for u64 { } } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct NresultsElement(#[xml(ty = "text")] u64); #[derive(XmlDeserialize, Clone, Debug, PartialEq, XmlRootTag)] diff --git a/crates/dav/src/xml/tag_list.rs b/crates/dav/src/xml/tag_list.rs index 506d22d..41779e3 100644 --- a/crates/dav/src/xml/tag_list.rs +++ b/crates/dav/src/xml/tag_list.rs @@ -6,7 +6,7 @@ use quick_xml::{ use rustical_xml::{NamespaceOwned, XmlSerialize}; use std::collections::HashMap; -#[derive(Clone, Debug, PartialEq, From)] +#[derive(Clone, Debug, PartialEq, Eq, From)] pub struct TagList(Vec<(Option, String)>); impl XmlSerialize for TagList { @@ -18,13 +18,12 @@ impl XmlSerialize for TagList { writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { let prefix = ns - .map(|ns| namespaces.get(&ns)) - .unwrap_or(None) + .and_then(|ns| namespaces.get(&ns)) .map(|prefix| { - if !prefix.is_empty() { - format!("{prefix}:") - } else { + if prefix.is_empty() { String::new() + } else { + format!("{prefix}:") } }); let has_prefix = prefix.is_some(); diff --git a/crates/dav_push/src/lib.rs b/crates/dav_push/src/lib.rs index 835c530..431061e 100644 --- a/crates/dav_push/src/lib.rs +++ b/crates/dav_push/src/lib.rs @@ -125,7 +125,7 @@ impl DavPushController { subsciption.id, subsciption.topic ); self.try_delete_subscription(&subsciption.id).await; - }; + } } if let Err(err) = self.send_payload(&payload, &subsciption).await { @@ -207,7 +207,7 @@ enum NotifierError { impl NotifierError { // Decide whether the error should cause the subscription to be removed - pub fn is_permament_error(&self) -> bool { + pub const fn is_permament_error(&self) -> bool { match self { Self::InvalidPublicKeyType(_) | Self::InvalidEndpointUrl(_) diff --git a/crates/dav_push/src/prop.rs b/crates/dav_push/src/prop.rs index f995967..01237a1 100644 --- a/crates/dav_push/src/prop.rs +++ b/crates/dav_push/src/prop.rs @@ -1,7 +1,7 @@ use rustical_dav::header::Depth; use rustical_xml::{Unparsed, XmlDeserialize, XmlSerialize}; -#[derive(Debug, Clone, XmlSerialize, PartialEq)] +#[derive(Debug, Clone, XmlSerialize, PartialEq, Eq)] pub enum Transport { #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")] WebPush, @@ -33,12 +33,12 @@ pub enum Trigger { PropertyUpdate(PropertyUpdate), } -#[derive(XmlSerialize, XmlDeserialize, PartialEq, Clone, Debug)] +#[derive(XmlSerialize, XmlDeserialize, PartialEq, Eq, Clone, Debug)] pub struct ContentUpdate( #[xml(rename = "depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth, ); -#[derive(XmlSerialize, PartialEq, Clone, Debug)] +#[derive(XmlSerialize, PartialEq, Eq, Clone, Debug)] pub struct PropertyUpdate( #[xml(rename = "depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth, ); diff --git a/crates/dav_push/src/register.rs b/crates/dav_push/src/register.rs index 4a159dc..d721050 100644 --- a/crates/dav_push/src/register.rs +++ b/crates/dav_push/src/register.rs @@ -15,7 +15,7 @@ pub struct WebPushSubscription { pub auth_secret: String, } -#[derive(XmlDeserialize, Clone, Debug, PartialEq)] +#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)] pub struct SubscriptionPublicKey { #[xml(ty = "attr", rename = "type")] pub ty: String, diff --git a/crates/frontend/src/config.rs b/crates/frontend/src/config.rs index dee7e71..8d0ef26 100644 --- a/crates/frontend/src/config.rs +++ b/crates/frontend/src/config.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -fn default_true() -> bool { +const fn default_true() -> bool { true } diff --git a/crates/frontend/src/lib.rs b/crates/frontend/src/lib.rs index c16a58d..0aee30b 100644 --- a/crates/frontend/src/lib.rs +++ b/crates/frontend/src/lib.rs @@ -106,11 +106,11 @@ pub fn frontend_router(auth_provider: Arc .route("/", post(post_nextcloud_login)) .layer(Extension(nextcloud_flows)) .layer(Extension(auth_provider.clone())) - .layer(AuthenticationLayer::new(auth_provider.clone())) + .layer(AuthenticationLayer::new(auth_provider)) .layer(middleware::from_fn(unauthorized_handler)) } diff --git a/crates/frontend/src/nextcloud_login/routes.rs b/crates/frontend/src/nextcloud_login/routes.rs index 3510a75..ce25b5e 100644 --- a/crates/frontend/src/nextcloud_login/routes.rs +++ b/crates/frontend/src/nextcloud_login/routes.rs @@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize}; use std::sync::Arc; use tracing::instrument; -pub(crate) async fn post_nextcloud_login( +pub async fn post_nextcloud_login( Extension(state): Extension>, TypedHeader(user_agent): TypedHeader, Host(host): Host, @@ -35,9 +35,9 @@ pub(crate) async fn post_nextcloud_login( flows.insert( flow_id.clone(), NextcloudFlow { - app_name: app_name.to_owned(), + app_name: app_name.clone(), created_at: Utc::now(), - token: token.to_owned(), + token: token.clone(), response: None, }, ); @@ -52,11 +52,11 @@ pub(crate) async fn post_nextcloud_login( #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub(crate) struct NextcloudPollForm { +pub struct NextcloudPollForm { token: String, } -pub(crate) async fn post_nextcloud_poll( +pub async fn post_nextcloud_poll( Extension(state): Extension>, Path(flow_id): Path, Extension(auth_provider): Extension>, @@ -75,8 +75,8 @@ pub(crate) async fn post_nextcloud_poll( auth_provider .add_app_token( &response.login_name, - flow.app_name.to_owned(), - response.app_password.to_owned(), + flow.app_name.clone(), + response.app_password.clone(), ) .await?; flows.remove(&flow_id); @@ -98,7 +98,7 @@ struct NextcloudLoginPage { } #[instrument(skip(state))] -pub(crate) async fn get_nextcloud_flow( +pub async fn get_nextcloud_flow( Extension(state): Extension>, Path(flow_id): Path, user: Principal, @@ -107,7 +107,7 @@ pub(crate) async fn get_nextcloud_flow( Ok(Html( NextcloudLoginPage { username: user.displayname.unwrap_or(user.id), - app_name: flow.app_name.to_owned(), + app_name: flow.app_name.clone(), } .render() .unwrap(), @@ -119,7 +119,7 @@ pub(crate) async fn get_nextcloud_flow( } #[derive(Debug, Clone, Deserialize, Serialize)] -pub(crate) struct NextcloudAuthorizeForm { +pub struct NextcloudAuthorizeForm { app_name: String, } @@ -130,7 +130,7 @@ struct NextcloudLoginSuccessPage { } #[instrument(skip(state))] -pub(crate) async fn post_nextcloud_flow( +pub async fn post_nextcloud_flow( user: Principal, Extension(state): Extension>, Path(flow_id): Path, @@ -141,12 +141,12 @@ pub(crate) async fn post_nextcloud_flow( flow.app_name = form.app_name; flow.response = Some(NextcloudSuccessResponse { server: format!("https://{host}"), - login_name: user.id.to_owned(), + login_name: user.id.clone(), app_password: generate_app_token(), }); Ok(Html( NextcloudLoginSuccessPage { - app_name: flow.app_name.to_owned(), + app_name: flow.app_name.clone(), } .render() .unwrap(), diff --git a/crates/frontend/src/routes/app_token.rs b/crates/frontend/src/routes/app_token.rs index fdf174c..6fc6e26 100644 --- a/crates/frontend/src/routes/app_token.rs +++ b/crates/frontend/src/routes/app_token.rs @@ -40,7 +40,7 @@ pub struct AppleConfig { } #[derive(Debug, Clone, Deserialize)] -pub(crate) struct PostAppTokenForm { +pub struct PostAppTokenForm { name: String, #[serde(default)] apple: bool, @@ -57,7 +57,7 @@ pub async fn route_post_app_token( assert_eq!(user_id, user.id); let token = generate_app_token(); let mut token_id = auth_provider - .add_app_token(&user.id, name.to_owned(), token.clone()) + .add_app_token(&user.id, name.clone(), token.clone()) .await?; // Get first 4 characters of token identifier token_id.truncate(4); @@ -70,7 +70,7 @@ pub async fn route_post_app_token( hostname: hostname.clone(), caldav_principal_url: format!("https://{hostname}/caldav-compat/principal/{user_id}"), carddav_principal_url: format!("https://{hostname}/carddav/principal/{user_id}"), - user: user.id.to_owned(), + user: user.id.clone(), token, caldav_profile_uuid: Uuid::new_v4(), carddav_profile_uuid: Uuid::new_v4(), diff --git a/crates/ical/src/address_object.rs b/crates/ical/src/address_object.rs index 5e3e987..5726036 100644 --- a/crates/ical/src/address_object.rs +++ b/crates/ical/src/address_object.rs @@ -45,32 +45,32 @@ impl AddressObject { Ok(Self { id, vcf, vcard }) } - pub fn get_id(&self) -> &str { + #[must_use] pub fn get_id(&self) -> &str { &self.id } - pub fn get_etag(&self) -> String { + #[must_use] pub fn get_etag(&self) -> String { let mut hasher = Sha256::new(); hasher.update(self.get_id()); hasher.update(self.get_vcf()); format!("\"{:x}\"", hasher.finalize()) } - pub fn get_vcf(&self) -> &str { + #[must_use] pub fn get_vcf(&self) -> &str { &self.vcf } - pub fn get_anniversary(&self) -> Option<(CalDateTime, bool)> { + #[must_use] pub fn get_anniversary(&self) -> Option<(CalDateTime, bool)> { let prop = self.vcard.get_property("ANNIVERSARY")?.value.as_deref()?; CalDateTime::parse_vcard(prop).ok() } - pub fn get_birthday(&self) -> Option<(CalDateTime, bool)> { + #[must_use] pub fn get_birthday(&self) -> Option<(CalDateTime, bool)> { let prop = self.vcard.get_property("BDAY")?.value.as_deref()?; CalDateTime::parse_vcard(prop).ok() } - pub fn get_full_name(&self) -> Option<&str> { + #[must_use] pub fn get_full_name(&self) -> Option<&str> { let prop = self.vcard.get_property("FN")?; prop.value.as_deref() } @@ -94,7 +94,7 @@ impl AddressObject { let year_suffix = year.map(|year| format!(" ({year})")).unwrap_or_default(); Some(CalendarObject::from_ics(format!( - r#"BEGIN:VCALENDAR + r"BEGIN:VCALENDAR VERSION:2.0 CALSCALE:GREGORIAN PRODID:-//github.com/lennart-k/rustical birthday calendar//EN @@ -111,7 +111,7 @@ ACTION:DISPLAY DESCRIPTION:💍 {fullname}{year_suffix} END:VALARM END:VEVENT -END:VCALENDAR"#, +END:VCALENDAR", ))?) } else { None @@ -135,7 +135,7 @@ END:VCALENDAR"#, let year_suffix = year.map(|year| format!(" ({year})")).unwrap_or_default(); Some(CalendarObject::from_ics(format!( - r#"BEGIN:VCALENDAR + r"BEGIN:VCALENDAR VERSION:2.0 CALSCALE:GREGORIAN PRODID:-//github.com/lennart-k/rustical birthday calendar//EN @@ -152,7 +152,7 @@ ACTION:DISPLAY DESCRIPTION:🎂 {fullname}{year_suffix} END:VALARM END:VEVENT -END:VCALENDAR"#, +END:VCALENDAR", ))?) } else { None diff --git a/crates/ical/src/error.rs b/crates/ical/src/error.rs index 0821e5f..5805901 100644 --- a/crates/ical/src/error.rs +++ b/crates/ical/src/error.rs @@ -24,7 +24,7 @@ pub enum Error { } impl Error { - pub fn status_code(&self) -> StatusCode { + #[must_use] pub const fn status_code(&self) -> StatusCode { match self { Self::InvalidData(_) => StatusCode::BAD_REQUEST, Self::MissingCalendar | Self::MissingContact => StatusCode::BAD_REQUEST, diff --git a/crates/ical/src/icalendar/event.rs b/crates/ical/src/icalendar/event.rs index f07918f..25ad480 100644 --- a/crates/ical/src/icalendar/event.rs +++ b/crates/ical/src/icalendar/event.rs @@ -15,7 +15,7 @@ pub struct EventObject { } impl EventObject { - pub fn get_uid(&self) -> &str { + #[must_use] pub fn get_uid(&self) -> &str { self.event.get_uid() } @@ -43,7 +43,7 @@ impl EventObject { if let Some(dtend) = self.get_dtend()? { return Ok(Some(dtend)); - }; + } let duration = self.event.get_duration().unwrap_or(Duration::days(1)); @@ -96,7 +96,7 @@ impl EventObject { &self, start: Option>, end: Option>, - overrides: &[EventObject], + overrides: &[Self], ) -> Result, Error> { if let Some(mut rrule_set) = self.recurrence_ruleset()? { if let Some(start) = start { @@ -150,7 +150,7 @@ impl EventObject { ev.set_property(Property { name: "RECURRENCE-ID".to_string(), - value: Some(dateformat.to_owned()), + value: Some(dateformat.clone()), params: None, }); ev.set_property(Property { diff --git a/crates/ical/src/icalendar/object.rs b/crates/ical/src/icalendar/object.rs index 20be88e..9dbe7c5 100644 --- a/crates/ical/src/icalendar/object.rs +++ b/crates/ical/src/icalendar/object.rs @@ -26,11 +26,11 @@ pub enum CalendarObjectType { } impl CalendarObjectType { - pub fn as_str(&self) -> &'static str { + #[must_use] pub const fn as_str(&self) -> &'static str { match self { - CalendarObjectType::Event => "VEVENT", - CalendarObjectType::Todo => "VTODO", - CalendarObjectType::Journal => "VJOURNAL", + Self::Event => "VEVENT", + Self::Todo => "VTODO", + Self::Journal => "VJOURNAL", } } } @@ -66,9 +66,9 @@ pub enum CalendarObjectComponent { impl From<&CalendarObjectComponent> for CalendarObjectType { fn from(value: &CalendarObjectComponent) -> Self { match value { - CalendarObjectComponent::Event(..) => CalendarObjectType::Event, - CalendarObjectComponent::Todo(..) => CalendarObjectType::Todo, - CalendarObjectComponent::Journal(..) => CalendarObjectType::Journal, + CalendarObjectComponent::Event(..) => Self::Event, + CalendarObjectComponent::Todo(..) => Self::Todo, + CalendarObjectComponent::Journal(..) => Self::Journal, } } } @@ -154,10 +154,10 @@ impl CalendarObject { )); } - if !cal.events.is_empty() as u8 - + !cal.todos.is_empty() as u8 - + !cal.journals.is_empty() as u8 - + !cal.free_busys.is_empty() as u8 + if u8::from(!cal.events.is_empty()) + + u8::from(!cal.todos.is_empty()) + + u8::from(!cal.journals.is_empty()) + + u8::from(!cal.free_busys.is_empty()) != 1 { // https://datatracker.ietf.org/doc/html/rfc4791#section-4.1 @@ -208,15 +208,15 @@ impl CalendarObject { }) } - pub fn get_vtimezones(&self) -> &HashMap { + #[must_use] pub const fn get_vtimezones(&self) -> &HashMap { &self.vtimezones } - pub fn get_data(&self) -> &CalendarObjectComponent { + #[must_use] pub const fn get_data(&self) -> &CalendarObjectComponent { &self.data } - pub fn get_id(&self) -> &str { + #[must_use] pub fn get_id(&self) -> &str { match &self.data { // We've made sure before that the first component exists and all components share the // same UID @@ -226,22 +226,22 @@ impl CalendarObject { } } - pub fn get_etag(&self) -> String { + #[must_use] pub fn get_etag(&self) -> String { let mut hasher = Sha256::new(); hasher.update(self.get_id()); hasher.update(self.get_ics()); format!("\"{:x}\"", hasher.finalize()) } - pub fn get_ics(&self) -> &str { + #[must_use] pub fn get_ics(&self) -> &str { &self.ics } - pub fn get_component_name(&self) -> &str { + #[must_use] pub fn get_component_name(&self) -> &str { self.get_object_type().as_str() } - pub fn get_object_type(&self) -> CalendarObjectType { + #[must_use] pub fn get_object_type(&self) -> CalendarObjectType { (&self.data).into() } @@ -250,7 +250,7 @@ impl CalendarObject { CalendarObjectComponent::Event(main_event, overrides) => Ok(overrides .iter() .chain([main_event].into_iter()) - .map(|event| event.get_dtstart()) + .map(super::event::EventObject::get_dtstart) .collect::, _>>()? .into_iter() .flatten() @@ -264,7 +264,7 @@ impl CalendarObject { CalendarObjectComponent::Event(main_event, overrides) => Ok(overrides .iter() .chain([main_event].into_iter()) - .map(|event| event.get_last_occurence()) + .map(super::event::EventObject::get_last_occurence) .collect::, _>>()? .into_iter() .flatten() diff --git a/crates/ical/src/timestamp.rs b/crates/ical/src/timestamp.rs index 8b0d229..74a9720 100644 --- a/crates/ical/src/timestamp.rs +++ b/crates/ical/src/timestamp.rs @@ -73,7 +73,7 @@ impl From for DateTime { value .as_datetime() .into_owned() - .with_timezone(&value.timezone().to_owned().into()) + .with_timezone(&value.timezone().into()) } } @@ -102,13 +102,13 @@ impl Ord for CalDateTime { impl From> for CalDateTime { fn from(value: DateTime) -> Self { - CalDateTime::DateTime(value.with_timezone(&ICalTimezone::Local)) + Self::DateTime(value.with_timezone(&ICalTimezone::Local)) } } impl From> for CalDateTime { fn from(value: DateTime) -> Self { - CalDateTime::DateTime(value.with_timezone(&ICalTimezone::Olson(chrono_tz::UTC))) + Self::DateTime(value.with_timezone(&ICalTimezone::Olson(chrono_tz::UTC))) } } @@ -158,7 +158,7 @@ impl CalDateTime { Self::parse(prop_value, timezone) } - pub fn format(&self) -> String { + #[must_use] pub fn format(&self) -> String { match self { Self::DateTime(datetime) => match datetime.timezone() { ICalTimezone::Olson(chrono_tz::UTC) => datetime.format(UTC_DATE_TIME).to_string(), @@ -168,25 +168,25 @@ impl CalDateTime { } } - pub fn format_date(&self) -> String { + #[must_use] pub fn format_date(&self) -> String { match self { Self::DateTime(datetime) => datetime.format(LOCAL_DATE).to_string(), Self::Date(date, _) => date.format(LOCAL_DATE).to_string(), } } - pub fn date(&self) -> NaiveDate { + #[must_use] pub fn date(&self) -> NaiveDate { match self { Self::DateTime(datetime) => datetime.date_naive(), Self::Date(date, _) => date.to_owned(), } } - pub fn is_date(&self) -> bool { + #[must_use] pub const fn is_date(&self) -> bool { matches!(&self, Self::Date(_, _)) } - pub fn as_datetime(&self) -> Cow<'_, DateTime> { + #[must_use] pub fn as_datetime(&self) -> Cow<'_, DateTime> { match self { Self::DateTime(datetime) => Cow::Borrowed(datetime), Self::Date(date, tz) => Cow::Owned( @@ -201,14 +201,14 @@ impl CalDateTime { pub fn parse(value: &str, timezone: Option) -> Result { if let Ok(datetime) = NaiveDateTime::parse_from_str(value, LOCAL_DATE_TIME) { if let Some(timezone) = timezone { - return Ok(CalDateTime::DateTime( + return Ok(Self::DateTime( datetime .and_local_timezone(timezone.into()) .earliest() .ok_or(CalDateTimeError::LocalTimeGap)?, )); } - return Ok(CalDateTime::DateTime( + return Ok(Self::DateTime( datetime .and_local_timezone(ICalTimezone::Local) .earliest() @@ -220,17 +220,16 @@ impl CalDateTime { return Ok(datetime.and_utc().into()); } let timezone = timezone - .map(ICalTimezone::Olson) - .unwrap_or(ICalTimezone::Local); + .map_or(ICalTimezone::Local, ICalTimezone::Olson); if let Ok(date) = NaiveDate::parse_from_str(value, LOCAL_DATE) { - return Ok(CalDateTime::Date(date, timezone)); + return Ok(Self::Date(date, timezone)); } if let Ok(date) = NaiveDate::parse_from_str(value, "%Y-%m-%d") { - return Ok(CalDateTime::Date(date, timezone)); + return Ok(Self::Date(date, timezone)); } if let Ok(date) = NaiveDate::parse_from_str(value, "%Y%m%d") { - return Ok(CalDateTime::Date(date, timezone)); + return Ok(Self::Date(date, timezone)); } Err(CalDateTimeError::InvalidDatetimeFormat(value.to_string())) @@ -250,7 +249,7 @@ impl CalDateTime { let day = captures.name("d").unwrap().as_str().parse().ok().unwrap(); return Ok(( - CalDateTime::Date( + Self::Date( NaiveDate::from_ymd_opt(year, month, day) .ok_or(CalDateTimeError::ParseError(value.to_string()))?, ICalTimezone::Local, @@ -261,14 +260,14 @@ impl CalDateTime { Err(CalDateTimeError::InvalidDatetimeFormat(value.to_string())) } - pub fn utc(&self) -> DateTime { + #[must_use] pub fn utc(&self) -> DateTime { self.as_datetime().to_utc() } - pub fn timezone(&self) -> ICalTimezone { + #[must_use] pub fn timezone(&self) -> ICalTimezone { match &self { - CalDateTime::DateTime(datetime) => datetime.timezone(), - CalDateTime::Date(_, tz) => tz.to_owned(), + Self::DateTime(datetime) => datetime.timezone(), + Self::Date(_, tz) => tz.to_owned(), } } } @@ -282,107 +281,107 @@ impl From for DateTime { impl Datelike for CalDateTime { fn year(&self) -> i32 { match &self { - CalDateTime::DateTime(datetime) => datetime.year(), - CalDateTime::Date(date, _) => date.year(), + Self::DateTime(datetime) => datetime.year(), + Self::Date(date, _) => date.year(), } } fn month(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.month(), - CalDateTime::Date(date, _) => date.month(), + Self::DateTime(datetime) => datetime.month(), + Self::Date(date, _) => date.month(), } } fn month0(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.month0(), - CalDateTime::Date(date, _) => date.month0(), + Self::DateTime(datetime) => datetime.month0(), + Self::Date(date, _) => date.month0(), } } fn day(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.day(), - CalDateTime::Date(date, _) => date.day(), + Self::DateTime(datetime) => datetime.day(), + Self::Date(date, _) => date.day(), } } fn day0(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.day0(), - CalDateTime::Date(date, _) => date.day0(), + Self::DateTime(datetime) => datetime.day0(), + Self::Date(date, _) => date.day0(), } } fn ordinal(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.ordinal(), - CalDateTime::Date(date, _) => date.ordinal(), + Self::DateTime(datetime) => datetime.ordinal(), + Self::Date(date, _) => date.ordinal(), } } fn ordinal0(&self) -> u32 { match &self { - CalDateTime::DateTime(datetime) => datetime.ordinal0(), - CalDateTime::Date(date, _) => date.ordinal0(), + Self::DateTime(datetime) => datetime.ordinal0(), + Self::Date(date, _) => date.ordinal0(), } } fn weekday(&self) -> chrono::Weekday { match &self { - CalDateTime::DateTime(datetime) => datetime.weekday(), - CalDateTime::Date(date, _) => date.weekday(), + Self::DateTime(datetime) => datetime.weekday(), + Self::Date(date, _) => date.weekday(), } } fn iso_week(&self) -> chrono::IsoWeek { match &self { - CalDateTime::DateTime(datetime) => datetime.iso_week(), - CalDateTime::Date(date, _) => date.iso_week(), + Self::DateTime(datetime) => datetime.iso_week(), + Self::Date(date, _) => date.iso_week(), } } fn with_year(&self, year: i32) -> Option { match &self { - CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_year(year)?)), - CalDateTime::Date(date, tz) => Some(Self::Date(date.with_year(year)?, tz.to_owned())), + Self::DateTime(datetime) => Some(Self::DateTime(datetime.with_year(year)?)), + Self::Date(date, tz) => Some(Self::Date(date.with_year(year)?, tz.to_owned())), } } fn with_month(&self, month: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month(month)?)), - CalDateTime::Date(date, tz) => Some(Self::Date(date.with_month(month)?, tz.to_owned())), + Self::DateTime(datetime) => Some(Self::DateTime(datetime.with_month(month)?)), + Self::Date(date, tz) => Some(Self::Date(date.with_month(month)?, tz.to_owned())), } } fn with_month0(&self, month0: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month0(month0)?)), - CalDateTime::Date(date, tz) => { + Self::DateTime(datetime) => Some(Self::DateTime(datetime.with_month0(month0)?)), + Self::Date(date, tz) => { Some(Self::Date(date.with_month0(month0)?, tz.to_owned())) } } } fn with_day(&self, day: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day(day)?)), - CalDateTime::Date(date, tz) => Some(Self::Date(date.with_day(day)?, tz.to_owned())), + Self::DateTime(datetime) => Some(Self::DateTime(datetime.with_day(day)?)), + Self::Date(date, tz) => Some(Self::Date(date.with_day(day)?, tz.to_owned())), } } fn with_day0(&self, day0: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day0(day0)?)), - CalDateTime::Date(date, tz) => Some(Self::Date(date.with_day0(day0)?, tz.to_owned())), + Self::DateTime(datetime) => Some(Self::DateTime(datetime.with_day0(day0)?)), + Self::Date(date, tz) => Some(Self::Date(date.with_day0(day0)?, tz.to_owned())), } } fn with_ordinal(&self, ordinal: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => { + Self::DateTime(datetime) => { Some(Self::DateTime(datetime.with_ordinal(ordinal)?)) } - CalDateTime::Date(date, tz) => { + Self::Date(date, tz) => { Some(Self::Date(date.with_ordinal(ordinal)?, tz.to_owned())) } } } fn with_ordinal0(&self, ordinal0: u32) -> Option { match &self { - CalDateTime::DateTime(datetime) => { + Self::DateTime(datetime) => { Some(Self::DateTime(datetime.with_ordinal0(ordinal0)?)) } - CalDateTime::Date(date, tz) => { + Self::Date(date, tz) => { Some(Self::Date(date.with_ordinal0(ordinal0)?, tz.to_owned())) } } diff --git a/crates/ical/src/timezone.rs b/crates/ical/src/timezone.rs index 6205ab2..aea5c9e 100644 --- a/crates/ical/src/timezone.rs +++ b/crates/ical/src/timezone.rs @@ -26,7 +26,7 @@ impl From for ICalTimezone { } } -#[derive(Debug, Clone, PartialEq, Display)] +#[derive(Debug, Clone, PartialEq, Eq, Display)] pub enum CalTimezoneOffset { Local(chrono::FixedOffset), Olson(chrono_tz::TzOffset), diff --git a/crates/oidc/src/lib.rs b/crates/oidc/src/lib.rs index b86b463..eb63b0c 100644 --- a/crates/oidc/src/lib.rs +++ b/crates/oidc/src/lib.rs @@ -83,7 +83,7 @@ async fn get_oidc_client( })?; Ok(CoreClient::from_provider_metadata( - provider_metadata.clone(), + provider_metadata, client_id.clone(), client_secret.clone(), ) diff --git a/crates/store/src/addressbook.rs b/crates/store/src/addressbook.rs index 98c332b..120781c 100644 --- a/crates/store/src/addressbook.rs +++ b/crates/store/src/addressbook.rs @@ -14,7 +14,7 @@ pub struct Addressbook { } impl Addressbook { - pub fn format_synctoken(&self) -> String { + #[must_use] pub fn format_synctoken(&self) -> String { format_synctoken(self.synctoken) } } diff --git a/crates/store/src/auth/middleware.rs b/crates/store/src/auth/middleware.rs index eaf6ad9..f8a75b7 100644 --- a/crates/store/src/auth/middleware.rs +++ b/crates/store/src/auth/middleware.rs @@ -23,7 +23,7 @@ impl Clone for AuthenticationLayer { } impl AuthenticationLayer { - pub fn new(auth_provider: Arc) -> Self { + pub const fn new(auth_provider: Arc) -> Self { Self { auth_provider } } } diff --git a/crates/store/src/auth/principal.rs b/crates/store/src/auth/principal.rs index b52ee18..4ca71f7 100644 --- a/crates/store/src/auth/principal.rs +++ b/crates/store/src/auth/principal.rs @@ -35,7 +35,7 @@ impl Principal { /// Returns true if the user is either /// - the principal itself /// - has full access to the prinicpal (is member) - pub fn is_principal(&self, principal: &str) -> bool { + #[must_use] pub fn is_principal(&self, principal: &str) -> bool { if self.id == principal { return true; } diff --git a/crates/store/src/auth/principal_type.rs b/crates/store/src/auth/principal_type.rs index 89bc24e..69a5ca3 100644 --- a/crates/store/src/auth/principal_type.rs +++ b/crates/store/src/auth/principal_type.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use rustical_xml::ValueSerialize; use serde::{Deserialize, Serialize}; -/// https://datatracker.ietf.org/doc/html/rfc5545#section-3.2.3 -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, clap::ValueEnum)] +/// +#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, clap::ValueEnum)] #[serde(rename_all = "lowercase")] pub enum PrincipalType { #[default] @@ -36,13 +36,13 @@ impl TryFrom<&str> for PrincipalType { } impl PrincipalType { - pub fn as_str(&self) -> &'static str { + #[must_use] pub const fn as_str(&self) -> &'static str { match self { - PrincipalType::Individual => "INDIVIDUAL", - PrincipalType::Group => "GROUP", - PrincipalType::Resource => "RESOURCE", - PrincipalType::Room => "ROOM", - PrincipalType::Unknown => "UNKNOWN", + Self::Individual => "INDIVIDUAL", + Self::Group => "GROUP", + Self::Resource => "RESOURCE", + Self::Room => "ROOM", + Self::Unknown => "UNKNOWN", } } } diff --git a/crates/store/src/calendar.rs b/crates/store/src/calendar.rs index 54d5721..a8a7567 100644 --- a/crates/store/src/calendar.rs +++ b/crates/store/src/calendar.rs @@ -32,19 +32,19 @@ pub struct Calendar { } impl Calendar { - pub fn format_synctoken(&self) -> String { + #[must_use] pub fn format_synctoken(&self) -> String { format_synctoken(self.synctoken) } - pub fn get_timezone(&self) -> Option { + #[must_use] pub fn get_timezone(&self) -> Option { self.timezone_id .as_ref() .and_then(|tzid| chrono_tz::Tz::from_str(tzid).ok()) } - pub fn get_vtimezone(&self) -> Option<&'static str> { + #[must_use] pub fn get_vtimezone(&self) -> Option<&'static str> { self.timezone_id .as_ref() - .and_then(|tzid| vtimezones_rs::VTIMEZONES.get(tzid).cloned()) + .and_then(|tzid| vtimezones_rs::VTIMEZONES.get(tzid).copied()) } } diff --git a/crates/store/src/contact_birthday_store.rs b/crates/store/src/contact_birthday_store.rs index 246d436..507f328 100644 --- a/crates/store/src/contact_birthday_store.rs +++ b/crates/store/src/contact_birthday_store.rs @@ -8,7 +8,7 @@ use rustical_ical::{AddressObject, CalendarObject, CalendarObjectType}; use sha2::{Digest, Sha256}; use std::{collections::HashMap, sync::Arc}; -pub(crate) const BIRTHDAYS_PREFIX: &str = "_birthdays_"; +pub const BIRTHDAYS_PREFIX: &str = "_birthdays_"; #[derive(Constructor, Clone)] pub struct ContactBirthdayStore(Arc); @@ -43,7 +43,7 @@ fn birthday_calendar(addressbook: Addressbook) -> Calendar { } } -/// Objects are all prefixed with BIRTHDAYS_PREFIX +/// Objects are all prefixed with `BIRTHDAYS_PREFIX` #[async_trait] impl CalendarStore for ContactBirthdayStore { async fn get_calendar( @@ -165,7 +165,7 @@ impl CalendarStore for ContactBirthdayStore { let cal_id = cal_id .strip_prefix(BIRTHDAYS_PREFIX) .ok_or(Error::NotFound)?; - let (addressobject_id, date_type) = object_id.rsplit_once("-").ok_or(Error::NotFound)?; + let (addressobject_id, date_type) = object_id.rsplit_once('-').ok_or(Error::NotFound)?; self.0 .get_object(principal, cal_id, addressobject_id, show_deleted) .await? diff --git a/crates/store/src/error.rs b/crates/store/src/error.rs index f6218d2..5739b1d 100644 --- a/crates/store/src/error.rs +++ b/crates/store/src/error.rs @@ -30,7 +30,7 @@ pub enum Error { } impl Error { - pub fn status_code(&self) -> StatusCode { + #[must_use] pub const fn status_code(&self) -> StatusCode { match self { Self::NotFound => StatusCode::NOT_FOUND, Self::AlreadyExists => StatusCode::CONFLICT, diff --git a/crates/store/src/synctoken.rs b/crates/store/src/synctoken.rs index 67425bf..b7dbcf9 100644 --- a/crates/store/src/synctoken.rs +++ b/crates/store/src/synctoken.rs @@ -1,10 +1,10 @@ const SYNC_NAMESPACE: &str = "github.com/lennart-k/rustical/ns/"; -pub fn format_synctoken(synctoken: i64) -> String { +#[must_use] pub fn format_synctoken(synctoken: i64) -> String { format!("{SYNC_NAMESPACE}{synctoken}") } -pub fn parse_synctoken(synctoken: &str) -> Option { +#[must_use] pub fn parse_synctoken(synctoken: &str) -> Option { if !synctoken.starts_with(SYNC_NAMESPACE) { return None; } diff --git a/crates/store_sqlite/src/addressbook_store.rs b/crates/store_sqlite/src/addressbook_store.rs index 2928f9d..b6897a2 100644 --- a/crates/store_sqlite/src/addressbook_store.rs +++ b/crates/store_sqlite/src/addressbook_store.rs @@ -138,26 +138,23 @@ impl SqliteAddressbookStore { addressbook_id: &str, use_trashbin: bool, ) -> Result<(), rustical_store::Error> { - match use_trashbin { - true => { - sqlx::query!( - r#"UPDATE addressbooks SET deleted_at = datetime() WHERE (principal, id) = (?, ?)"#, - principal, addressbook_id - ) - .execute(executor) - .await.map_err(crate::Error::from)?; - } - false => { - sqlx::query!( - r#"DELETE FROM addressbooks WHERE (principal, id) = (?, ?)"#, - principal, - addressbook_id - ) - .execute(executor) - .await - .map_err(crate::Error::from)?; - } - }; + if use_trashbin { + sqlx::query!( + r#"UPDATE addressbooks SET deleted_at = datetime() WHERE (principal, id) = (?, ?)"#, + principal, addressbook_id + ) + .execute(executor) + .await.map_err(crate::Error::from)?; + } else { + sqlx::query!( + r#"DELETE FROM addressbooks WHERE (principal, id) = (?, ?)"#, + principal, + addressbook_id + ) + .execute(executor) + .await + .map_err(crate::Error::from)?; + } Ok(()) } @@ -208,8 +205,7 @@ impl SqliteAddressbookStore { let new_synctoken = changes .last() - .map(|&Row { synctoken, .. }| synctoken) - .unwrap_or(0); + .map_or(0, |&Row { synctoken, .. }| synctoken); for Row { object_id, .. } in changes { match Self::_get_object(&mut *conn, principal, addressbook_id, &object_id, false).await @@ -259,7 +255,7 @@ impl SqliteAddressbookStore { .fetch_all(executor) .await.map_err(crate::Error::from)? .into_iter() - .map(|row| row.try_into()) + .map(std::convert::TryInto::try_into) .collect() } @@ -325,28 +321,25 @@ impl SqliteAddressbookStore { object_id: &str, use_trashbin: bool, ) -> Result<(), rustical_store::Error> { - match use_trashbin { - true => { - sqlx::query!( - "UPDATE addressobjects SET deleted_at = datetime(), updated_at = datetime() WHERE (principal, addressbook_id, id) = (?, ?, ?)", - principal, - addressbook_id, - object_id - ) - .execute(executor) - .await.map_err(crate::Error::from)?; - } - false => { - sqlx::query!( - "DELETE FROM addressobjects WHERE addressbook_id = ? AND id = ?", - addressbook_id, - object_id - ) - .execute(executor) - .await - .map_err(crate::Error::from)?; - } - }; + if use_trashbin { + sqlx::query!( + "UPDATE addressobjects SET deleted_at = datetime(), updated_at = datetime() WHERE (principal, addressbook_id, id) = (?, ?, ?)", + principal, + addressbook_id, + object_id + ) + .execute(executor) + .await.map_err(crate::Error::from)?; + } else { + sqlx::query!( + "DELETE FROM addressobjects WHERE addressbook_id = ? AND id = ?", + addressbook_id, + object_id + ) + .execute(executor) + .await + .map_err(crate::Error::from)?; + } Ok(()) } @@ -440,7 +433,7 @@ impl AddressbookStore for SqliteAddressbookStore { }) { error!("Push notification about deleted addressbook failed: {err}"); - }; + } Ok(()) } @@ -474,9 +467,9 @@ impl AddressbookStore for SqliteAddressbookStore { let mut deleted_sizes = vec![]; for (size, deleted) in Self::_list_objects(&self.db, principal, addressbook_id).await? { if deleted { - deleted_sizes.push(size) + deleted_sizes.push(size); } else { - sizes.push(size) + sizes.push(size); } } Ok(CollectionMetadata { @@ -521,8 +514,8 @@ impl AddressbookStore for SqliteAddressbookStore { Self::_put_object( &mut *tx, - principal.to_owned(), - addressbook_id.to_owned(), + principal.clone(), + addressbook_id.clone(), object, overwrite, ) @@ -548,7 +541,7 @@ impl AddressbookStore for SqliteAddressbookStore { .push_topic, }) { error!("Push notification about deleted addressbook failed: {err}"); - }; + } Ok(()) } @@ -585,7 +578,7 @@ impl AddressbookStore for SqliteAddressbookStore { .push_topic, }) { error!("Push notification about deleted addressbook failed: {err}"); - }; + } Ok(()) } @@ -619,7 +612,7 @@ impl AddressbookStore for SqliteAddressbookStore { .push_topic, }) { error!("Push notification about deleted addressbook failed: {err}"); - }; + } Ok(()) } diff --git a/crates/store_sqlite/src/calendar_store.rs b/crates/store_sqlite/src/calendar_store.rs index 8127913..7e0d12b 100644 --- a/crates/store_sqlite/src/calendar_store.rs +++ b/crates/store_sqlite/src/calendar_store.rs @@ -22,7 +22,7 @@ impl TryFrom for CalendarObject { type Error = rustical_store::Error; fn try_from(value: CalendarObjectRow) -> Result { - let object = CalendarObject::from_ics(value.ics)?; + let object = Self::from_ics(value.ics)?; if object.get_id() != value.id { return Err(rustical_store::Error::IcalError( rustical_ical::Error::InvalidData(format!( @@ -213,24 +213,21 @@ impl SqliteCalendarStore { id: &str, use_trashbin: bool, ) -> Result<(), Error> { - match use_trashbin { - true => sqlx::query!( - r#"UPDATE calendars SET deleted_at = datetime() WHERE (principal, id) = (?, ?)"#, - principal, - id - ) - .execute(executor) - .await - .map_err(crate::Error::from)?, - false => sqlx::query!( - r#"DELETE FROM calendars WHERE (principal, id) = (?, ?)"#, - principal, - id - ) - .execute(executor) - .await - .map_err(crate::Error::from)?, - }; + if use_trashbin { sqlx::query!( + r#"UPDATE calendars SET deleted_at = datetime() WHERE (principal, id) = (?, ?)"#, + principal, + id + ) + .execute(executor) + .await + .map_err(crate::Error::from)? } else { sqlx::query!( + r#"DELETE FROM calendars WHERE (principal, id) = (?, ?)"#, + principal, + id + ) + .execute(executor) + .await + .map_err(crate::Error::from)? }; Ok(()) } @@ -286,7 +283,7 @@ impl SqliteCalendarStore { .fetch_all(executor) .await.map_err(crate::Error::from)? .into_iter() - .map(|row| row.try_into()) + .map(std::convert::TryInto::try_into) .collect() } @@ -320,7 +317,7 @@ impl SqliteCalendarStore { .await .map_err(crate::Error::from)? .into_iter() - .map(|row| row.try_into()) + .map(std::convert::TryInto::try_into) .collect() } @@ -411,28 +408,25 @@ impl SqliteCalendarStore { id: &str, use_trashbin: bool, ) -> Result<(), Error> { - match use_trashbin { - true => { - sqlx::query!( - "UPDATE calendarobjects SET deleted_at = datetime(), updated_at = datetime() WHERE (principal, cal_id, id) = (?, ?, ?)", - principal, - cal_id, - id - ) - .execute(executor) - .await.map_err(crate::Error::from)?; - } - false => { - sqlx::query!( - "DELETE FROM calendarobjects WHERE cal_id = ? AND id = ?", - cal_id, - id - ) - .execute(executor) - .await - .map_err(crate::Error::from)?; - } - }; + if use_trashbin { + sqlx::query!( + "UPDATE calendarobjects SET deleted_at = datetime(), updated_at = datetime() WHERE (principal, cal_id, id) = (?, ?, ?)", + principal, + cal_id, + id + ) + .execute(executor) + .await.map_err(crate::Error::from)?; + } else { + sqlx::query!( + "DELETE FROM calendarobjects WHERE cal_id = ? AND id = ?", + cal_id, + id + ) + .execute(executor) + .await + .map_err(crate::Error::from)?; + } Ok(()) } @@ -484,8 +478,7 @@ impl SqliteCalendarStore { let new_synctoken = changes .last() - .map(|&Row { synctoken, .. }| synctoken) - .unwrap_or(0); + .map_or(0, |&Row { synctoken, .. }| synctoken); for Row { object_id, .. } in changes { match Self::_get_object(&mut *conn, principal, cal_id, &object_id, false).await { @@ -562,7 +555,7 @@ impl CalendarStore for SqliteCalendarStore { }) { error!("Push notification about deleted calendar failed: {err}"); - }; + } Ok(()) } @@ -627,9 +620,9 @@ impl CalendarStore for SqliteCalendarStore { let mut deleted_sizes = vec![]; for (size, deleted) in Self::_list_objects(&self.db, principal, cal_id).await? { if deleted { - deleted_sizes.push(size) + deleted_sizes.push(size); } else { - sizes.push(size) + sizes.push(size); } } Ok(CollectionMetadata { @@ -680,8 +673,8 @@ impl CalendarStore for SqliteCalendarStore { Self::_put_object( &mut *tx, - principal.to_owned(), - cal_id.to_owned(), + principal.clone(), + cal_id.clone(), object, overwrite, ) @@ -706,7 +699,7 @@ impl CalendarStore for SqliteCalendarStore { .push_topic, }) { error!("Push notification about deleted calendar failed: {err}"); - }; + } Ok(()) } @@ -731,7 +724,7 @@ impl CalendarStore for SqliteCalendarStore { topic: self.get_calendar(principal, cal_id, true).await?.push_topic, }) { error!("Push notification about deleted calendar failed: {err}"); - }; + } Ok(()) } @@ -756,7 +749,7 @@ impl CalendarStore for SqliteCalendarStore { topic: self.get_calendar(principal, cal_id, true).await?.push_topic, }) { error!("Push notification about deleted calendar failed: {err}"); - }; + } Ok(()) } diff --git a/crates/store_sqlite/src/error.rs b/crates/store_sqlite/src/error.rs index 3c55fd4..38e2af8 100644 --- a/crates/store_sqlite/src/error.rs +++ b/crates/store_sqlite/src/error.rs @@ -15,16 +15,16 @@ pub enum Error { impl From for Error { fn from(value: sqlx::Error) -> Self { match value { - sqlx::Error::RowNotFound => Error::StoreError(rustical_store::Error::NotFound), + sqlx::Error::RowNotFound => Self::StoreError(rustical_store::Error::NotFound), sqlx::Error::Database(err) => { if err.is_unique_violation() { warn!("{err:?}"); - Error::StoreError(rustical_store::Error::AlreadyExists) + Self::StoreError(rustical_store::Error::AlreadyExists) } else { - Error::SqlxError(sqlx::Error::Database(err)) + Self::SqlxError(sqlx::Error::Database(err)) } } - err => Error::SqlxError(err), + err => Self::SqlxError(err), } } } diff --git a/crates/store_sqlite/src/lib.rs b/crates/store_sqlite/src/lib.rs index eb0e0c6..fe94488 100644 --- a/crates/store_sqlite/src/lib.rs +++ b/crates/store_sqlite/src/lib.rs @@ -26,7 +26,7 @@ pub struct SqliteStore { } impl SqliteStore { - pub fn new(db: SqlitePool) -> Self { + #[must_use] pub const fn new(db: SqlitePool) -> Self { Self { db } } } diff --git a/crates/store_sqlite/src/principal_store.rs b/crates/store_sqlite/src/principal_store.rs index 1259f5e..f774fe4 100644 --- a/crates/store_sqlite/src/principal_store.rs +++ b/crates/store_sqlite/src/principal_store.rs @@ -25,7 +25,7 @@ impl TryFrom for Principal { type Error = Error; fn try_from(value: PrincipalRow) -> Result { - Ok(Principal { + Ok(Self { id: value.id, displayname: value.displayname, password: value.password_hash.map(Secret::from), diff --git a/crates/xml/src/de.rs b/crates/xml/src/de.rs index 458ab69..25c12a8 100644 --- a/crates/xml/src/de.rs +++ b/crates/xml/src/de.rs @@ -62,13 +62,13 @@ impl XmlDocument for T { format!("{root_ns:?}"), Self::root_tag().to_owned(), )); - }; + } return Self::deserialize(&mut reader, &start, empty); } Event::Eof => return Err(XmlError::Eof), _ => return Err(XmlError::UnsupportedEvent("unknown, todo")), - }; + } } } } @@ -88,7 +88,7 @@ impl XmlDeserialize for () { Event::End(e) if e.name() == start.name() => return Ok(()), Event::Eof => return Err(XmlError::Eof), _ => {} - }; + } } } } diff --git a/crates/xml/src/namespace.rs b/crates/xml/src/namespace.rs index c3a97df..40b6a67 100644 --- a/crates/xml/src/namespace.rs +++ b/crates/xml/src/namespace.rs @@ -1,6 +1,6 @@ use quick_xml::name::Namespace; -#[derive(Debug, Clone, Default, PartialEq)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct NamespaceOwned(pub Vec); impl<'a> From> for NamespaceOwned { @@ -28,7 +28,7 @@ impl<'a> From<&'a Namespace<'a>> for NamespaceOwned { } impl NamespaceOwned { - pub fn as_ref(&self) -> Namespace<'_> { + #[must_use] pub fn as_ref(&self) -> Namespace<'_> { Namespace(&self.0) } } diff --git a/crates/xml/src/se.rs b/crates/xml/src/se.rs index 7ef9fff..ab13622 100644 --- a/crates/xml/src/se.rs +++ b/crates/xml/src/se.rs @@ -65,13 +65,12 @@ impl XmlSerialize for () { writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { let prefix = ns - .map(|ns| namespaces.get(&ns)) - .unwrap_or(None) + .and_then(|ns| namespaces.get(&ns)) .map(|prefix| { - if !prefix.is_empty() { - [*prefix, ":"].concat() - } else { + if prefix.is_empty() { String::new() + } else { + [*prefix, ":"].concat() } }); let has_prefix = prefix.is_some(); diff --git a/crates/xml/src/unparsed.rs b/crates/xml/src/unparsed.rs index bdb371e..37d0708 100644 --- a/crates/xml/src/unparsed.rs +++ b/crates/xml/src/unparsed.rs @@ -5,11 +5,11 @@ use quick_xml::events::BytesStart; use crate::{XmlDeserialize, XmlError}; // TODO: actually implement -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Unparsed(BytesStart<'static>); impl Unparsed { - pub fn tag_name(&self) -> String { + #[must_use] pub fn tag_name(&self) -> String { // TODO: respect namespace? String::from_utf8_lossy(self.0.local_name().as_ref()).to_string() } diff --git a/crates/xml/src/value.rs b/crates/xml/src/value.rs index cfc9b9a..23d938d 100644 --- a/crates/xml/src/value.rs +++ b/crates/xml/src/value.rs @@ -60,7 +60,7 @@ impl_value_parse!(usize); impl ValueSerialize for &str { fn serialize(&self) -> String { - self.to_string() + (*self).to_string() } } @@ -98,7 +98,7 @@ impl XmlDeserialize for T { Event::End(_) => break, Event::Eof => return Err(XmlError::Eof), _ => return Err(XmlError::UnsupportedEvent("todo")), - }; + } } } @@ -115,13 +115,12 @@ impl XmlSerialize for T { writer: &mut quick_xml::Writer<&mut Vec>, ) -> std::io::Result<()> { let prefix = ns - .map(|ns| namespaces.get(&ns)) - .unwrap_or(None) + .and_then(|ns| namespaces.get(&ns)) .map(|prefix| { - if !prefix.is_empty() { - [*prefix, ":"].concat() - } else { + if prefix.is_empty() { String::new() + } else { + [*prefix, ":"].concat() } }); let has_prefix = prefix.is_some(); diff --git a/src/app.rs b/src/app.rs index 24ac237..08e5bfd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -43,7 +43,7 @@ pub fn make_app( ) -> Router<()> { let birthday_store = Arc::new(ContactBirthdayStore::new(addr_store.clone())); let combined_cal_store = - Arc::new(CombinedCalendarStore::new(cal_store.clone()).with_store(birthday_store)); + Arc::new(CombinedCalendarStore::new(cal_store).with_store(birthday_store)); let mut router = Router::new() .merge(caldav_router( @@ -104,24 +104,19 @@ pub fn make_app( router = router.merge(frontend_router( "/frontend", auth_provider.clone(), - combined_cal_store.clone(), - addr_store.clone(), + combined_cal_store, + addr_store, frontend_config, oidc_config, )); } if nextcloud_login_config.enabled { - router = router.nest( - "/index.php/login/v2", - nextcloud_login_router(auth_provider.clone()), - ); + router = router.nest("/index.php/login/v2", nextcloud_login_router(auth_provider)); } if dav_push_enabled { - router = router.merge(rustical_dav_push::subscription_service( - subscription_store.clone(), - )); + router = router.merge(rustical_dav_push::subscription_service(subscription_store)); } router @@ -178,11 +173,11 @@ pub fn make_app( tracing::error!("client error"); } } - }; + } }) .on_failure( |_error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| { - tracing::error!("something went wrong") + tracing::error!("something went wrong"); }, ), ) diff --git a/src/commands/membership.rs b/src/commands/membership.rs index 5447e63..8e893b3 100644 --- a/src/commands/membership.rs +++ b/src/commands/membership.rs @@ -38,9 +38,9 @@ pub async fn handle_membership_command( MembershipArgs { command }: MembershipArgs, ) -> anyhow::Result<()> { let id = match &command { - MembershipCommand::Assign(AssignArgs { id, .. }) => id, - MembershipCommand::Remove(RemoveArgs { id, .. }) => id, - MembershipCommand::List(ListArgs { id }) => id, + MembershipCommand::Assign(AssignArgs { id, .. }) + | MembershipCommand::Remove(RemoveArgs { id, .. }) + | MembershipCommand::List(ListArgs { id }) => id, }; match &command { diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 47bc2f3..7dd5ecd 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,5 +1,6 @@ use crate::config::{ - Config, DataStoreConfig, DavPushConfig, HttpConfig, SqliteDataStoreConfig, TracingConfig, + Config, DataStoreConfig, DavPushConfig, HttpConfig, NextcloudLoginConfig, + SqliteDataStoreConfig, TracingConfig, }; use clap::Parser; use rustical_frontend::FrontendConfig; @@ -23,7 +24,7 @@ pub fn cmd_gen_config(_args: GenConfigArgs) -> anyhow::Result<()> { }, oidc: None, dav_push: DavPushConfig::default(), - nextcloud_login: Default::default(), + nextcloud_login: NextcloudLoginConfig::default(), }; let generated_config = toml::to_string(&config)?; println!("{generated_config}"); diff --git a/src/commands/principals.rs b/src/commands/principals.rs index 88e41e2..70d8aa8 100644 --- a/src/commands/principals.rs +++ b/src/commands/principals.rs @@ -140,7 +140,7 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> { .unwrap() .to_string() .into(), - ) + ); } if name.is_some() { principal.displayname = name; @@ -152,7 +152,7 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> { println!("Principal {id} updated"); } Command::Membership(args) => { - handle_membership_command(principal_store.as_ref(), args).await? + handle_membership_command(principal_store.as_ref(), args).await?; } } Ok(()) diff --git a/src/config.rs b/src/config.rs index 0fe6a2b..f0bbbb7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -41,7 +41,7 @@ pub struct TracingConfig { pub opentelemetry: bool, } -fn default_true() -> bool { +const fn default_true() -> bool { true } diff --git a/src/main.rs b/src/main.rs index ace4304..5459874 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,7 +66,7 @@ async fn get_data_stores( let addressbook_store = Arc::new(SqliteAddressbookStore::new(db.clone(), send.clone())); let cal_store = Arc::new(SqliteCalendarStore::new(db.clone(), send)); let subscription_store = Arc::new(SqliteStore::new(db.clone())); - let principal_store = Arc::new(SqlitePrincipalStore::new(db.clone())); + let principal_store = Arc::new(SqlitePrincipalStore::new(db)); ( addressbook_store, cal_store, @@ -128,7 +128,7 @@ async fn main() -> Result<()> { let listener = tokio::net::TcpListener::bind(&address).await?; tasks.push(tokio::spawn(async move { info!("RustiCal serving on http://{address}"); - axum::serve(listener, app).await.unwrap() + axum::serve(listener, app).await.unwrap(); })); for task in tasks {