style: apply cargo fmt to entire codebase

Standardize code formatting across all 173 Rust source files
using rustfmt. No functional changes - purely cosmetic.

This establishes a consistent code style baseline for the
project going forward.
This commit is contained in:
Dionisio
2026-02-14 01:29:34 +01:00
parent 67137a3ef2
commit 4c98c5a657
173 changed files with 23368 additions and 17590 deletions
+209 -181
View File
@@ -1,25 +1,24 @@
use chrono::{DateTime, Duration, TimeZone, Utc};
/**
* Calendar Event Entity
*
*
* This module defines the CalendarEvent entity, which represents an event or
* appointment in a calendar, following the iCalendar (RFC 5545) specification.
*
*
* Calendar events have properties like summary, description, location, start/end times,
* and can include recurrence rules for repeating events. Each event belongs to a
* specific calendar and stores its complete iCalendar representation.
*/
use uuid::Uuid;
use chrono::{DateTime, Utc, Duration, TimeZone};
use crate::common::errors::{Result, DomainError, ErrorKind};
use crate::common::errors::{DomainError, ErrorKind, Result};
// Re-export entity errors from the centralized module
pub use super::entity_errors::CalendarEventError;
/**
* CalendarEvent entity.
*
*
* Represents a calendar event or appointment that can be synced via CalDAV.
* Follows the iCalendar format (RFC 5545) for compatibility with CalDAV clients.
*/
@@ -27,40 +26,40 @@ pub use super::entity_errors::CalendarEventError;
pub struct CalendarEvent {
/// Unique identifier for the event
id: Uuid,
/// ID of the calendar this event belongs to
calendar_id: Uuid,
/// Short summary/title of the event
summary: String,
/// Detailed description of the event (optional)
description: Option<String>,
/// Location of the event (optional)
location: Option<String>,
/// Start time of the event
start_time: DateTime<Utc>,
/// End time of the event
end_time: DateTime<Utc>,
/// Whether this is an all-day event
all_day: bool,
/// Recurrence rule in iCalendar RRULE format (optional)
rrule: Option<String>,
/// Unique identifier in iCalendar format (used for CalDAV sync)
ical_uid: String,
/// Complete iCalendar data (VEVENT component)
ical_data: String,
/// Time when the event was created
created_at: DateTime<Utc>,
/// Time when the event was last modified
updated_at: DateTime<Utc>,
}
@@ -68,7 +67,7 @@ pub struct CalendarEvent {
impl CalendarEvent {
/**
* Creates a new calendar event with the given properties.
*
*
* @param calendar_id ID of the calendar this event belongs to
* @param summary Short summary/title of the event
* @param description Detailed description of the event (optional)
@@ -99,7 +98,7 @@ impl CalendarEvent {
"Event summary cannot be empty",
));
}
if end_time < start_time {
return Err(DomainError::new(
ErrorKind::InvalidInput,
@@ -107,17 +106,18 @@ impl CalendarEvent {
"End time cannot be before start time",
));
}
// Validate RRULE if provided (basic validation)
if let Some(ref rule) = rrule
&& !rule.starts_with("FREQ=") {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Recurrence rule must start with FREQ=",
));
}
&& !rule.starts_with("FREQ=")
{
return Err(DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Recurrence rule must start with FREQ=",
));
}
// Validate iCalendar data (basic validation)
if !ical_data.contains("BEGIN:VEVENT") || !ical_data.contains("END:VEVENT") {
return Err(DomainError::new(
@@ -126,9 +126,9 @@ impl CalendarEvent {
"iCalendar data must contain a VEVENT component",
));
}
let now = Utc::now();
Ok(Self {
id: Uuid::new_v4(),
calendar_id,
@@ -145,11 +145,11 @@ impl CalendarEvent {
updated_at: now,
})
}
/**
* Creates a calendar event with specific ID and timestamps.
* Typically used when reconstructing from storage.
*
*
* @param id Unique identifier for the event
* @param calendar_id ID of the calendar this event belongs to
* @param summary Short summary/title of the event
@@ -188,7 +188,7 @@ impl CalendarEvent {
"Event summary cannot be empty",
));
}
if end_time < start_time {
return Err(DomainError::new(
ErrorKind::InvalidInput,
@@ -196,7 +196,7 @@ impl CalendarEvent {
"End time cannot be before start time",
));
}
Ok(Self {
id,
calendar_id,
@@ -213,11 +213,11 @@ impl CalendarEvent {
updated_at,
})
}
/**
* Creates a calendar event from an iCalendar VEVENT component.
* Parses the iCalendar data to extract event properties.
*
*
* @param calendar_id ID of the calendar this event belongs to
* @param ical_data Complete iCalendar data (VEVENT component)
* @return Result containing the new CalendarEvent or a domain error
@@ -225,58 +225,63 @@ impl CalendarEvent {
pub fn from_ical(calendar_id: Uuid, ical_data: String) -> Result<Self> {
// This implementation would require a proper iCalendar parser
// For brevity, we're using a simplified version here
// Extract required fields from iCalendar data
let summary = Self::extract_ical_property(&ical_data, "SUMMARY")
.ok_or_else(|| DomainError::new(
let summary = Self::extract_ical_property(&ical_data, "SUMMARY").ok_or_else(|| {
DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Missing SUMMARY in iCalendar data",
))?;
let dtstart = Self::extract_ical_property(&ical_data, "DTSTART")
.ok_or_else(|| DomainError::new(
)
})?;
let dtstart = Self::extract_ical_property(&ical_data, "DTSTART").ok_or_else(|| {
DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Missing DTSTART in iCalendar data",
))?;
let dtend = Self::extract_ical_property(&ical_data, "DTEND")
.ok_or_else(|| DomainError::new(
)
})?;
let dtend = Self::extract_ical_property(&ical_data, "DTEND").ok_or_else(|| {
DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Missing DTEND in iCalendar data",
))?;
)
})?;
// Parse dates (simplified)
let start_time = Self::parse_ical_datetime(&dtstart)
.map_err(|e| DomainError::new(
let start_time = Self::parse_ical_datetime(&dtstart).map_err(|e| {
DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
format!("Invalid DTSTART: {}", e),
))?;
let end_time = Self::parse_ical_datetime(&dtend)
.map_err(|e| DomainError::new(
)
})?;
let end_time = Self::parse_ical_datetime(&dtend).map_err(|e| {
DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
format!("Invalid DTEND: {}", e),
))?;
)
})?;
// Determine if all-day event (simplified check)
let all_day = dtstart.contains("VALUE=DATE") && !dtstart.contains("T");
// Extract optional fields
let description = Self::extract_ical_property(&ical_data, "DESCRIPTION");
let location = Self::extract_ical_property(&ical_data, "LOCATION");
let rrule = Self::extract_ical_property(&ical_data, "RRULE");
// Extract UID or generate a new one
let ical_uid = Self::extract_ical_property(&ical_data, "UID")
.unwrap_or_else(|| Uuid::new_v4().to_string());
let now = Utc::now();
Ok(Self {
id: Uuid::new_v4(),
calendar_id,
@@ -293,84 +298,84 @@ impl CalendarEvent {
updated_at: now,
})
}
// Getters
/// Returns the event's unique identifier
pub fn id(&self) -> &Uuid {
&self.id
}
/// Returns the ID of the calendar this event belongs to
pub fn calendar_id(&self) -> &Uuid {
&self.calendar_id
}
/// Returns the event's summary/title
pub fn summary(&self) -> &str {
&self.summary
}
/// Returns the event's description, if any
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
/// Returns the event's location, if any
pub fn location(&self) -> Option<&str> {
self.location.as_deref()
}
/// Returns the event's start time
pub fn start_time(&self) -> &DateTime<Utc> {
&self.start_time
}
/// Returns the event's end time
pub fn end_time(&self) -> &DateTime<Utc> {
&self.end_time
}
/// Returns whether this is an all-day event
pub fn all_day(&self) -> bool {
self.all_day
}
/// Returns the event's recurrence rule, if any
pub fn rrule(&self) -> Option<&str> {
self.rrule.as_deref()
}
/// Returns the event's iCalendar UID
pub fn ical_uid(&self) -> &str {
&self.ical_uid
}
/// Returns the complete iCalendar data for the event
pub fn ical_data(&self) -> &str {
&self.ical_data
}
/// Returns the time when the event was created
pub fn created_at(&self) -> &DateTime<Utc> {
&self.created_at
}
/// Returns the time when the event was last modified
pub fn updated_at(&self) -> &DateTime<Utc> {
&self.updated_at
}
/// Returns the duration of the event
pub fn duration(&self) -> Duration {
self.end_time - self.start_time
}
// Setters and Mutators
/**
* Updates the event's summary/title.
*
*
* @param summary New summary/title for the event
* @return Result indicating success or containing a domain error
*/
@@ -382,58 +387,62 @@ impl CalendarEvent {
"Event summary cannot be empty",
));
}
// Clone the summary before updating the struct
let summary_clone = summary.clone();
self.summary = summary;
self.updated_at = Utc::now();
// Update iCalendar data using the cloned value
self.update_ical_property("SUMMARY", &summary_clone);
Ok(())
}
/**
* Updates the event's description.
*
*
* @param description New description for the event
*/
pub fn update_description(&mut self, description: Option<String>) {
self.description = description.clone();
self.updated_at = Utc::now();
// Update iCalendar data
match description {
Some(desc) => self.update_ical_property("DESCRIPTION", &desc),
None => self.remove_ical_property("DESCRIPTION"),
}
}
/**
* Updates the event's location.
*
*
* @param location New location for the event
*/
pub fn update_location(&mut self, location: Option<String>) {
self.location = location.clone();
self.updated_at = Utc::now();
// Update iCalendar data
match location {
Some(loc) => self.update_ical_property("LOCATION", &loc),
None => self.remove_ical_property("LOCATION"),
}
}
/**
* Updates the event's start and end times.
*
*
* @param start_time New start time for the event
* @param end_time New end time for the event
* @return Result indicating success or containing a domain error
*/
pub fn update_time_range(&mut self, start_time: DateTime<Utc>, end_time: DateTime<Utc>) -> Result<()> {
pub fn update_time_range(
&mut self,
start_time: DateTime<Utc>,
end_time: DateTime<Utc>,
) -> Result<()> {
if end_time < start_time {
return Err(DomainError::new(
ErrorKind::InvalidInput,
@@ -441,89 +450,90 @@ impl CalendarEvent {
"End time cannot be before start time",
));
}
self.start_time = start_time;
self.end_time = end_time;
self.updated_at = Utc::now();
// Update iCalendar data
let start_str = if self.all_day {
format!("{}T000000Z", start_time.format("%Y%m%d"))
} else {
format!("{}", start_time.format("%Y%m%dT%H%M%SZ"))
};
let end_str = if self.all_day {
format!("{}T000000Z", end_time.format("%Y%m%d"))
} else {
format!("{}", end_time.format("%Y%m%dT%H%M%SZ"))
};
self.update_ical_property("DTSTART", &start_str);
self.update_ical_property("DTEND", &end_str);
Ok(())
}
/**
* Updates whether this is an all-day event.
*
*
* @param all_day Whether this is an all-day event
*/
pub fn update_all_day(&mut self, all_day: bool) {
self.all_day = all_day;
self.updated_at = Utc::now();
// Update iCalendar data
let start_str = if all_day {
format!("VALUE=DATE:{}", self.start_time.format("%Y%m%d"))
} else {
format!("{}", self.start_time.format("%Y%m%dT%H%M%SZ"))
};
let end_str = if all_day {
format!("VALUE=DATE:{}", self.end_time.format("%Y%m%d"))
} else {
format!("{}", self.end_time.format("%Y%m%dT%H%M%SZ"))
};
self.update_ical_property("DTSTART", &start_str);
self.update_ical_property("DTEND", &end_str);
}
/**
* Updates the event's recurrence rule.
*
*
* @param rrule New recurrence rule for the event
* @return Result indicating success or containing a domain error
*/
pub fn update_rrule(&mut self, rrule: Option<String>) -> Result<()> {
// Validate RRULE if provided (basic validation)
if let Some(ref rule) = rrule
&& !rule.starts_with("FREQ=") {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Recurrence rule must start with FREQ=",
));
}
&& !rule.starts_with("FREQ=")
{
return Err(DomainError::new(
ErrorKind::InvalidInput,
"CalendarEvent",
"Recurrence rule must start with FREQ=",
));
}
self.rrule = rrule.clone();
self.updated_at = Utc::now();
// Update iCalendar data
match rrule {
Some(rule) => self.update_ical_property("RRULE", &rule),
None => self.remove_ical_property("RRULE"),
}
Ok(())
}
/**
* Updates the complete iCalendar data for the event.
* Also updates the event properties based on the new iCalendar data.
*
*
* @param ical_data New iCalendar data for the event
* @return Result indicating success or containing a domain error
*/
@@ -536,55 +546,57 @@ impl CalendarEvent {
"iCalendar data must contain a VEVENT component",
));
}
// Extract and update properties from iCalendar data
if let Some(summary) = Self::extract_ical_property(&ical_data, "SUMMARY") {
self.summary = summary;
}
self.description = Self::extract_ical_property(&ical_data, "DESCRIPTION");
self.location = Self::extract_ical_property(&ical_data, "LOCATION");
if let Some(dtstart) = Self::extract_ical_property(&ical_data, "DTSTART")
&& let Ok(start_time) = Self::parse_ical_datetime(&dtstart) {
self.start_time = start_time;
}
&& let Ok(start_time) = Self::parse_ical_datetime(&dtstart)
{
self.start_time = start_time;
}
if let Some(dtend) = Self::extract_ical_property(&ical_data, "DTEND")
&& let Ok(end_time) = Self::parse_ical_datetime(&dtend) {
self.end_time = end_time;
}
&& let Ok(end_time) = Self::parse_ical_datetime(&dtend)
{
self.end_time = end_time;
}
// Update all-day status based on DTSTART
if let Some(dtstart) = Self::extract_ical_property(&ical_data, "DTSTART") {
self.all_day = dtstart.contains("VALUE=DATE") && !dtstart.contains("T");
}
self.rrule = Self::extract_ical_property(&ical_data, "RRULE");
if let Some(uid) = Self::extract_ical_property(&ical_data, "UID") {
self.ical_uid = uid;
}
self.ical_data = ical_data;
self.updated_at = Utc::now();
Ok(())
}
/**
* Checks if this event belongs to the specified calendar.
*
*
* @param calendar_id ID of the calendar to check against
* @return true if the event belongs to the calendar, false otherwise
*/
pub fn belongs_to_calendar(&self, calendar_id: &Uuid) -> bool {
self.calendar_id == *calendar_id
}
/**
* Checks if this event occurs within the specified time range.
*
*
* @param start Start of the time range to check
* @param end End of the time range to check
* @return true if the event occurs within the range, false otherwise
@@ -594,20 +606,20 @@ impl CalendarEvent {
if self.start_time <= *end && self.end_time >= *start {
return true;
}
// If event has recurrence, check if any recurrence occurs in range
// Note: A full implementation would need a proper recurrence rule parser
if let Some(rrule) = &self.rrule {
// Simplified check for demonstration
// A real implementation would need to generate recurrence instances
// and check if any fall within the range
// For now, we'll just check if the recurrence hasn't ended
// or if it ended after the start of our range
if let Some(until_pos) = rrule.find("UNTIL=") {
let until_start = until_pos + 6; // "UNTIL=" is 6 chars
if let Some(until_end) = rrule[until_start..].find(';') {
let until_str = &rrule[until_start..until_start+until_end];
let until_str = &rrule[until_start..until_start + until_end];
if let Ok(until_date) = Self::parse_ical_datetime(until_str) {
return until_date >= *start;
}
@@ -623,15 +635,15 @@ impl CalendarEvent {
return true;
}
}
false
}
// Helper methods for iCalendar operations
/**
* Extracts a property value from iCalendar data.
*
*
* @param ical_data The iCalendar data to search in
* @param property_name The name of the property to extract
* @return Option containing the property value if found
@@ -640,33 +652,34 @@ impl CalendarEvent {
// Find the property in the iCalendar data
let search_str = format!("\n{}:", property_name);
let search_str_alt = format!("\r\n{}:", property_name);
let pos = ical_data.find(&search_str)
let pos = ical_data
.find(&search_str)
.or_else(|| ical_data.find(&search_str_alt));
if let Some(pos) = pos {
// Find the start of the value
let value_start = pos + search_str.len();
// Find the end of the value (next line or end of string)
let value_end = ical_data[value_start..]
.find('\n')
.map(|p| value_start + p)
.unwrap_or_else(|| ical_data.len());
// Extract and return the value
let value = ical_data[value_start..value_end].trim();
if !value.is_empty() {
return Some(value.to_string());
}
}
None
}
/**
* Parses an iCalendar datetime string into a DateTime object.
*
*
* @param datetime The iCalendar datetime string to parse
* @return Result containing the parsed DateTime or an error
*/
@@ -677,40 +690,49 @@ impl CalendarEvent {
if date_str.len() != 8 {
return Err("Invalid date format".to_string());
}
let year = date_str[0..4].parse::<i32>()
let year = date_str[0..4]
.parse::<i32>()
.map_err(|_| "Invalid year".to_string())?;
let month = date_str[4..6].parse::<u32>()
let month = date_str[4..6]
.parse::<u32>()
.map_err(|_| "Invalid month".to_string())?;
let day = date_str[6..8].parse::<u32>()
let day = date_str[6..8]
.parse::<u32>()
.map_err(|_| "Invalid day".to_string())?;
return match chrono::NaiveDate::from_ymd_opt(year, month, day) {
Some(date) => Ok(Utc.from_utc_datetime(&date.and_hms_opt(0, 0, 0).unwrap())),
None => Err("Invalid date components".to_string()),
};
}
// Handle standard UTC format (20230101T120000Z)
let datetime_str = datetime.split(':').next_back().unwrap_or(datetime);
if datetime_str.len() < 15 || !datetime_str.ends_with('Z') {
return Err("Invalid datetime format".to_string());
}
let year = datetime_str[0..4].parse::<i32>()
let year = datetime_str[0..4]
.parse::<i32>()
.map_err(|_| "Invalid year".to_string())?;
let month = datetime_str[4..6].parse::<u32>()
let month = datetime_str[4..6]
.parse::<u32>()
.map_err(|_| "Invalid month".to_string())?;
let day = datetime_str[6..8].parse::<u32>()
let day = datetime_str[6..8]
.parse::<u32>()
.map_err(|_| "Invalid day".to_string())?;
let hour = datetime_str[9..11].parse::<u32>()
let hour = datetime_str[9..11]
.parse::<u32>()
.map_err(|_| "Invalid hour".to_string())?;
let minute = datetime_str[11..13].parse::<u32>()
let minute = datetime_str[11..13]
.parse::<u32>()
.map_err(|_| "Invalid minute".to_string())?;
let second = datetime_str[13..15].parse::<u32>()
let second = datetime_str[13..15]
.parse::<u32>()
.map_err(|_| "Invalid second".to_string())?;
match chrono::NaiveDate::from_ymd_opt(year, month, day) {
Some(date) => match date.and_hms_opt(hour, minute, second) {
Some(datetime) => Ok(Utc.from_utc_datetime(&datetime)),
@@ -719,70 +741,76 @@ impl CalendarEvent {
None => Err("Invalid date components".to_string()),
}
}
/**
* Updates an iCalendar property in the event's iCalendar data.
*
*
* @param property_name The name of the property to update
* @param value The new value for the property
*/
fn update_ical_property(&mut self, property_name: &str, value: &str) {
let search_str = format!("\n{}:", property_name);
let search_str_alt = format!("\r\n{}:", property_name);
// Check if property exists
let pos = self.ical_data.find(&search_str)
let pos = self
.ical_data
.find(&search_str)
.or_else(|| self.ical_data.find(&search_str_alt));
if let Some(pos) = pos {
// Find the start of the value
let value_start = pos + search_str.len();
// Find the end of the value (next line or end of string)
let value_end = self.ical_data[value_start..]
.find('\n')
.map(|p| value_start + p)
.unwrap_or_else(|| self.ical_data.len());
// Replace the value
let before = &self.ical_data[..value_start];
let after = &self.ical_data[value_end..];
self.ical_data = format!("{}{}{}", before, value, after);
} else {
// Property doesn't exist, add it before END:VEVENT
let end_pos = self.ical_data.find("END:VEVENT")
let end_pos = self
.ical_data
.find("END:VEVENT")
.unwrap_or(self.ical_data.len());
let before = &self.ical_data[..end_pos];
let after = &self.ical_data[end_pos..];
self.ical_data = format!("{}{}:{}\n{}", before, property_name, value, after);
}
}
/**
* Removes an iCalendar property from the event's iCalendar data.
*
*
* @param property_name The name of the property to remove
*/
fn remove_ical_property(&mut self, property_name: &str) {
let search_str = format!("\n{}:", property_name);
let search_str_alt = format!("\r\n{}:", property_name);
// Check if property exists
let pos = self.ical_data.find(&search_str)
let pos = self
.ical_data
.find(&search_str)
.or_else(|| self.ical_data.find(&search_str_alt));
if let Some(pos) = pos {
// Find the end of the value (next line or end of string)
let value_end = self.ical_data[pos + 1..]
.find('\n')
.map(|p| pos + 1 + p)
.unwrap_or_else(|| self.ical_data.len());
// Remove the property
let before = &self.ical_data[..pos];
let after = &self.ical_data[value_end..];
self.ical_data = format!("{}{}", before, after);
}
}
}
}