1use std::cmp::Ordering;
2use saa_schema::{saa_type, strum_macros::Display};
3use super::timestamp::Timestamp;
4use crate::AuthError;
5
6
7
8
9#[saa_type]
10#[derive(Display)]
11pub enum Expiration {
12 #[strum(to_string = "expiration height: {0}")]
14 AtHeight(u64),
15 #[strum(to_string = "expiration time: {0}")]
17 AtTime(Timestamp),
18 #[strum(to_string = "expiration: never")]
20 Never {},
21}
22
23
24impl Default for Expiration {
26 fn default() -> Self {
27 Expiration::Never {}
28 }
29}
30
31
32
33#[saa_type]
37#[derive(Display, Copy)]
38pub enum Duration {
39 #[strum(to_string = "height: {0}")]
41 Height(u64),
42 #[strum(to_string = "time: {0}")]
44 Time(u64),
45}
46
47
48
49#[cfg(feature = "wasm")]
50impl Expiration {
51 pub fn is_expired(&self, block: &crate::wasm::BlockInfo) -> bool {
52 match self {
53 Expiration::AtHeight(height) => block.height >= *height,
54 Expiration::AtTime(time) => block.time.seconds() >= time.seconds(),
55 Expiration::Never {} => false,
56 }
57 }
58}
59
60
61impl std::ops::Add<Duration> for Expiration {
62 type Output = Result<Expiration, AuthError>;
63
64 fn add(self, duration: Duration) -> Result<Expiration, AuthError> {
65 match (self, duration) {
66 (Expiration::AtTime(t), Duration::Time(delta)) => {
67 Ok(Expiration::AtTime(t.plus_seconds(delta)))
68 }
69 (Expiration::AtHeight(h), Duration::Height(delta)) => {
70 Ok(Expiration::AtHeight(h + delta))
71 }
72 (Expiration::Never {}, _) => Ok(Expiration::Never {}),
73 _ => Err(AuthError::generic("Cannot add height and time")),
74 }
75 }
76}
77
78
79impl PartialOrd for Expiration {
80 fn partial_cmp(&self, other: &Expiration) -> Option<Ordering> {
81 match (self, other) {
82 (Expiration::AtHeight(h1), Expiration::AtHeight(h2)) => Some(h1.cmp(h2)),
84 (Expiration::AtTime(t1), Expiration::AtTime(t2)) => Some(t1.cmp(t2)),
85 (Expiration::Never {}, Expiration::Never {}) => Some(Ordering::Equal),
87 (Expiration::Never {}, _) => Some(Ordering::Greater),
88 (_, Expiration::Never {}) => Some(Ordering::Less),
89 _ => None,
91 }
92 }
93}