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