cookie/
expiration.rs

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