feat(retention): implement retention policy configuration

- define struct for retention policy with message age and label generation
- add methods to create, access, and modify retention policies
- implement default values, cloning, equality, and debug formatting
This commit is contained in:
Jeremiah Russell
2025-10-19 07:43:56 +01:00
committed by Jeremiah Russell
parent 32db9cb51a
commit 1448c791d9

View File

@@ -3,23 +3,23 @@ mod message_age;
pub use message_age::MessageAge; pub use message_age::MessageAge;
/// Retention policy configuration for email messages. /// Retention policy configuration for email messages.
/// ///
/// A retention policy defines how old messages should be before they are subject /// A retention policy defines how old messages should be before they are subject
/// to retention actions (trash/delete), and whether a label should be automatically /// to retention actions (trash/delete), and whether a label should be automatically
/// generated to categorize messages matching this policy. /// generated to categorize messages matching this policy.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cull_gmail::{Retention, MessageAge}; /// use cull_gmail::{Retention, MessageAge};
/// ///
/// // Create a retention policy for messages older than 6 months /// // Create a retention policy for messages older than 6 months
/// let policy = Retention::new(MessageAge::Months(6), true); /// let policy = Retention::new(MessageAge::Months(6), true);
/// ///
/// // Create a retention policy without auto-generated labels /// // Create a retention policy without auto-generated labels
/// let policy = Retention::new(MessageAge::Years(1), false); /// let policy = Retention::new(MessageAge::Years(1), false);
/// ``` /// ```
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Retention { pub struct Retention {
age: MessageAge, age: MessageAge,
generate_label: bool, generate_label: bool,
@@ -36,20 +36,20 @@ impl Default for Retention {
impl Retention { impl Retention {
/// Create a new retention policy. /// Create a new retention policy.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `age` - The message age threshold for this retention policy /// * `age` - The message age threshold for this retention policy
/// * `generate_label` - Whether to automatically generate a label for messages matching this policy /// * `generate_label` - Whether to automatically generate a label for messages matching this policy
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cull_gmail::{Retention, MessageAge}; /// use cull_gmail::{Retention, MessageAge};
/// ///
/// // Policy for messages older than 30 days with auto-generated label /// // Policy for messages older than 30 days with auto-generated label
/// let policy = Retention::new(MessageAge::Days(30), true); /// let policy = Retention::new(MessageAge::Days(30), true);
/// ///
/// // Policy for messages older than 1 year without label generation /// // Policy for messages older than 1 year without label generation
/// let policy = Retention::new(MessageAge::Years(1), false); /// let policy = Retention::new(MessageAge::Years(1), false);
/// ``` /// ```
@@ -61,46 +61,48 @@ impl Retention {
} }
/// Get the message age threshold for this retention policy. /// Get the message age threshold for this retention policy.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cull_gmail::{Retention, MessageAge}; /// use cull_gmail::{Retention, MessageAge};
/// ///
/// let policy = Retention::new(MessageAge::Days(30), true); /// let policy = Retention::new(MessageAge::Days(30), true);
/// assert_eq!(policy.age(), &MessageAge::Days(30)); /// assert_eq!(policy.age(), &MessageAge::Days(30));
/// ``` /// ```
#[must_use]
pub fn age(&self) -> &MessageAge { pub fn age(&self) -> &MessageAge {
&self.age &self.age
} }
/// Check if this retention policy should generate automatic labels. /// Check if this retention policy should generate automatic labels.
/// ///
/// When `true`, messages matching this retention policy will be automatically /// When `true`, messages matching this retention policy will be automatically
/// tagged with a generated label based on the age specification. /// tagged with a generated label based on the age specification.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cull_gmail::{Retention, MessageAge}; /// use cull_gmail::{Retention, MessageAge};
/// ///
/// let policy = Retention::new(MessageAge::Days(30), true); /// let policy = Retention::new(MessageAge::Days(30), true);
/// assert_eq!(policy.generate_label(), true); /// assert_eq!(policy.generate_label(), true);
/// ///
/// let policy = Retention::new(MessageAge::Days(30), false); /// let policy = Retention::new(MessageAge::Days(30), false);
/// assert_eq!(policy.generate_label(), false); /// assert_eq!(policy.generate_label(), false);
/// ``` /// ```
#[must_use]
pub fn generate_label(&self) -> bool { pub fn generate_label(&self) -> bool {
self.generate_label self.generate_label
} }
/// Set whether this retention policy should generate automatic labels. /// Set whether this retention policy should generate automatic labels.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cull_gmail::{Retention, MessageAge}; /// use cull_gmail::{Retention, MessageAge};
/// ///
/// let mut policy = Retention::new(MessageAge::Days(30), false); /// let mut policy = Retention::new(MessageAge::Days(30), false);
/// policy.set_generate_label(true); /// policy.set_generate_label(true);
/// assert_eq!(policy.generate_label(), true); /// assert_eq!(policy.generate_label(), true);
@@ -118,32 +120,32 @@ mod tests {
fn test_retention_new() { fn test_retention_new() {
let age = MessageAge::Days(30); let age = MessageAge::Days(30);
let retention = Retention::new(age.clone(), true); let retention = Retention::new(age.clone(), true);
assert_eq!(retention.age(), &age); assert_eq!(retention.age(), &age);
assert_eq!(retention.generate_label(), true); assert!(retention.generate_label());
} }
#[test] #[test]
fn test_retention_new_no_label() { fn test_retention_new_no_label() {
let age = MessageAge::Years(1); let age = MessageAge::Years(1);
let retention = Retention::new(age.clone(), false); let retention = Retention::new(age.clone(), false);
assert_eq!(retention.age(), &age); assert_eq!(retention.age(), &age);
assert_eq!(retention.generate_label(), false); assert!(!retention.generate_label());
} }
#[test] #[test]
fn test_retention_set_generate_label() { fn test_retention_set_generate_label() {
let age = MessageAge::Months(6); let age = MessageAge::Months(6);
let mut retention = Retention::new(age.clone(), false); let mut retention = Retention::new(age.clone(), false);
assert_eq!(retention.generate_label(), false); assert!(!retention.generate_label());
retention.set_generate_label(true); retention.set_generate_label(true);
assert_eq!(retention.generate_label(), true); assert!(retention.generate_label());
retention.set_generate_label(false); retention.set_generate_label(false);
assert_eq!(retention.generate_label(), false); assert!(!retention.generate_label());
} }
#[test] #[test]
@@ -151,7 +153,7 @@ mod tests {
let age = MessageAge::Weeks(2); let age = MessageAge::Weeks(2);
let original = Retention::new(age.clone(), true); let original = Retention::new(age.clone(), true);
let cloned = original.clone(); let cloned = original.clone();
assert_eq!(original, cloned); assert_eq!(original, cloned);
assert_eq!(original.age(), cloned.age()); assert_eq!(original.age(), cloned.age());
assert_eq!(original.generate_label(), cloned.generate_label()); assert_eq!(original.generate_label(), cloned.generate_label());
@@ -162,23 +164,23 @@ mod tests {
let age1 = MessageAge::Days(30); let age1 = MessageAge::Days(30);
let age2 = MessageAge::Days(30); let age2 = MessageAge::Days(30);
let age3 = MessageAge::Days(31); let age3 = MessageAge::Days(31);
let retention1 = Retention::new(age1, true); let retention1 = Retention::new(age1, true);
let retention2 = Retention::new(age2, true); let retention2 = Retention::new(age2, true);
let retention3 = Retention::new(age3, true); let retention3 = Retention::new(age3, true);
let retention4 = Retention::new(MessageAge::Days(30), false); let retention4 = Retention::new(MessageAge::Days(30), false);
assert_eq!(retention1, retention2); assert_eq!(retention1, retention2);
assert_ne!(retention1, retention3); // different age assert_ne!(retention1, retention3); // different age
assert_ne!(retention1, retention4); // different generate_label assert_ne!(retention1, retention4); // different generate_label
} }
#[test] #[test]
fn test_retention_default() { fn test_retention_default() {
let default = Retention::default(); let default = Retention::default();
assert_eq!(default.age(), &MessageAge::Years(5)); assert_eq!(default.age(), &MessageAge::Years(5));
assert_eq!(default.generate_label(), true); assert!(default.generate_label());
} }
#[test] #[test]
@@ -187,23 +189,23 @@ mod tests {
let retention_weeks = Retention::new(MessageAge::Weeks(12), false); let retention_weeks = Retention::new(MessageAge::Weeks(12), false);
let retention_months = Retention::new(MessageAge::Months(3), true); let retention_months = Retention::new(MessageAge::Months(3), true);
let retention_years = Retention::new(MessageAge::Years(1), false); let retention_years = Retention::new(MessageAge::Years(1), false);
assert_eq!(retention_days.age().period_type(), "days"); assert_eq!(retention_days.age().period_type(), "days");
assert_eq!(retention_weeks.age().period_type(), "weeks"); assert_eq!(retention_weeks.age().period_type(), "weeks");
assert_eq!(retention_months.age().period_type(), "months"); assert_eq!(retention_months.age().period_type(), "months");
assert_eq!(retention_years.age().period_type(), "years"); assert_eq!(retention_years.age().period_type(), "years");
assert_eq!(retention_days.generate_label(), true); assert!(retention_days.generate_label());
assert_eq!(retention_weeks.generate_label(), false); assert!(!retention_weeks.generate_label());
assert_eq!(retention_months.generate_label(), true); assert!(retention_months.generate_label());
assert_eq!(retention_years.generate_label(), false); assert!(!retention_years.generate_label());
} }
#[test] #[test]
fn test_retention_debug() { fn test_retention_debug() {
let retention = Retention::new(MessageAge::Days(30), true); let retention = Retention::new(MessageAge::Days(30), true);
let debug_str = format!("{:?}", retention); let debug_str = format!("{:?}", retention);
assert!(debug_str.contains("Retention")); assert!(debug_str.contains("Retention"));
assert!(debug_str.contains("Days(30)")); assert!(debug_str.contains("Days(30)"));
assert!(debug_str.contains("true")); assert!(debug_str.contains("true"));