cookie/
expiration.rs

1use time::OffsetDateTime;
2
3/// A cookie's expiration: either a date-time or session.
4///
5/// An `Expiration` is constructible with `Expiration::from()` via any of:
6///
7///   * `None` -> `Expiration::Session`
8///   * `Some(OffsetDateTime)` -> `Expiration::DateTime`
9///   * `OffsetDateTime` -> `Expiration::DateTime`
10///
11/// ```rust
12/// use cookie::Expiration;
13/// use time::OffsetDateTime;
14///
15/// let expires = Expiration::from(None);
16/// assert_eq!(expires, Expiration::Session);
17///
18/// let now = OffsetDateTime::now_utc();
19/// let expires = Expiration::from(now);
20/// assert_eq!(expires, Expiration::DateTime(now));
21///
22/// let expires = Expiration::from(Some(now));
23/// assert_eq!(expires, Expiration::DateTime(now));
24/// ```
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum Expiration {
27    /// Expiration for a "permanent" cookie at a specific date-time.
28    DateTime(OffsetDateTime),
29    /// Expiration for a "session" cookie. Browsers define the notion of a
30    /// "session" and will automatically expire session cookies when they deem
31    /// the "session" to be over. This is typically, but need not be, when the
32    /// browser is closed.
33    Session,
34}
35
36impl Expiration {
37    /// Returns `true` if `self` is an `Expiration::DateTime`.
38    ///
39    /// # Example
40    ///
41    /// ```rust
42    /// use cookie::Expiration;
43    /// use time::OffsetDateTime;
44    ///
45    /// let expires = Expiration::from(None);
46    /// assert!(!expires.is_datetime());
47    ///
48    /// let expires = Expiration::from(OffsetDateTime::now_utc());
49    /// assert!(expires.is_datetime());
50    /// ```
51    pub fn is_datetime(&self) -> bool {
52        match self {
53            Expiration::DateTime(_) => true,
54            Expiration::Session => false
55        }
56    }
57
58    /// Returns `true` if `self` is an `Expiration::Session`.
59    ///
60    /// # Example
61    ///
62    /// ```rust
63    /// use cookie::Expiration;
64    /// use time::OffsetDateTime;
65    ///
66    /// let expires = Expiration::from(None);
67    /// assert!(expires.is_session());
68    ///
69    /// let expires = Expiration::from(OffsetDateTime::now_utc());
70    /// assert!(!expires.is_session());
71    /// ```
72    pub fn is_session(&self) -> bool {
73        match self {
74            Expiration::DateTime(_) => false,
75            Expiration::Session => true
76        }
77    }
78
79    /// Returns the inner `OffsetDateTime` if `self` is a `DateTime`.
80    ///
81    /// # Example
82    ///
83    /// ```rust
84    /// use cookie::Expiration;
85    /// use time::OffsetDateTime;
86    ///
87    /// let expires = Expiration::from(None);
88    /// assert!(expires.datetime().is_none());
89    ///
90    /// let now = OffsetDateTime::now_utc();
91    /// let expires = Expiration::from(now);
92    /// assert_eq!(expires.datetime(), Some(now));
93    /// ```
94    pub fn datetime(self) -> Option<OffsetDateTime> {
95        match self {
96            Expiration::Session => None,
97            Expiration::DateTime(v) => Some(v)
98        }
99    }
100
101    /// Applied `f` to the inner `OffsetDateTime` if `self` is a `DateTime` and
102    /// returns the mapped `Expiration`.
103    ///
104    /// # Example
105    ///
106    /// ```rust
107    /// use cookie::Expiration;
108    /// use time::{OffsetDateTime, Duration};
109    ///
110    /// let now = OffsetDateTime::now_utc();
111    /// let one_week = Duration::weeks(1);
112    ///
113    /// let expires = Expiration::from(now);
114    /// assert_eq!(expires.map(|t| t + one_week).datetime(), Some(now + one_week));
115    ///
116    /// let expires = Expiration::from(None);
117    /// assert_eq!(expires.map(|t| t + one_week).datetime(), None);
118    /// ```
119    pub fn map<F>(self, f: F) -> Self
120        where F: FnOnce(OffsetDateTime) -> OffsetDateTime
121    {
122        match self {
123            Expiration::Session => Expiration::Session,
124            Expiration::DateTime(v) => Expiration::DateTime(f(v)),
125        }
126    }
127}
128
129impl<T: Into<Option<OffsetDateTime>>> From<T> for Expiration {
130    fn from(option: T) -> Self {
131        match option.into() {
132            Some(value) => Expiration::DateTime(value),
133            None => Expiration::Session
134        }
135    }
136}