mls_rs/tree_kem/
lifetime.rs1use crate::{client::MlsError, time::MlsTime};
6use core::time::Duration;
7use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
8
9#[derive(Clone, Debug, PartialEq, Eq, MlsSize, MlsEncode, MlsDecode, Default)]
10#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[non_exhaustive]
13pub struct Lifetime {
14 pub not_before: MlsTime,
15 pub not_after: MlsTime,
16}
17
18impl Lifetime {
19 pub fn new(not_before: MlsTime, not_after: MlsTime) -> Lifetime {
20 Lifetime {
21 not_before,
22 not_after,
23 }
24 }
25
26 pub fn seconds(s: u64, maybe_not_before: Option<MlsTime>) -> Result<Self, MlsError> {
27 #[cfg(feature = "std")]
28 let not_before = MlsTime::now();
29 #[cfg(not(feature = "std"))]
30 let not_before = MlsTime::from(3600u64);
32
33 let not_before = if let Some(not_before_time) = maybe_not_before {
34 not_before_time
35 } else {
36 not_before
37 };
38
39 let not_after = MlsTime::from(
40 not_before
41 .seconds_since_epoch()
42 .checked_add(s)
43 .ok_or(MlsError::TimeOverflow)?,
44 );
45
46 Ok(Lifetime {
47 not_before: not_before - Duration::from_secs(3600),
49 not_after,
50 })
51 }
52
53 pub fn days(d: u32, maybe_not_before: Option<MlsTime>) -> Result<Self, MlsError> {
54 Self::seconds((d * 86400) as u64, maybe_not_before)
55 }
56
57 pub fn years(y: u8, maybe_not_before: Option<MlsTime>) -> Result<Self, MlsError> {
58 Self::days(365 * y as u32, maybe_not_before)
59 }
60
61 pub(crate) fn within_lifetime(&self, time: MlsTime) -> bool {
62 self.not_before <= time && time <= self.not_after
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use core::time::Duration;
69
70 use super::*;
71 use assert_matches::assert_matches;
72
73 const HOUR: Duration = Duration::from_secs(3600);
74 const DAY: Duration = Duration::from_secs(24 * 3600);
75
76 #[test]
77 fn test_lifetime_overflow() {
78 let res = Lifetime::seconds(u64::MAX, None);
79 assert_matches!(res, Err(MlsError::TimeOverflow))
80 }
81
82 #[test]
83 fn test_seconds() {
84 let seconds = 10;
85 let lifetime = Lifetime::seconds(seconds, None).unwrap();
86 assert_eq!(
87 lifetime.not_after - lifetime.not_before,
88 Duration::from_secs(3610)
89 );
90 }
91
92 #[test]
93 fn test_days() {
94 let days = 2;
95 let lifetime = Lifetime::days(days, None).unwrap();
96
97 assert_eq!(
98 lifetime.not_after - lifetime.not_before,
99 days * DAY + 1 * HOUR
100 );
101 }
102
103 #[test]
104 fn test_years() {
105 let years = 2;
106 let lifetime = Lifetime::years(years, None).unwrap();
107
108 assert_eq!(
109 lifetime.not_after - lifetime.not_before,
110 365 * DAY * (years as u32) + 1 * HOUR
111 );
112 }
113
114 #[test]
115 fn test_bounds() {
116 let test_lifetime = Lifetime {
117 not_before: MlsTime::from(5),
118 not_after: MlsTime::from(10),
119 };
120
121 assert!(!test_lifetime
122 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(4))));
123
124 assert!(!test_lifetime
125 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(11))));
126
127 assert!(test_lifetime
128 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(5))));
129
130 assert!(test_lifetime
131 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(10))));
132
133 assert!(test_lifetime
134 .within_lifetime(MlsTime::from_duration_since_epoch(Duration::from_secs(6))));
135 }
136}