use std::cmp::Ordering;
use saa_schema::{saa_type, strum_macros::Display};
use super::timestamp::Timestamp;
use crate::AuthError;
#[saa_type]
#[derive(Display)]
pub enum Expiration {
#[strum(to_string = "expiration height: {0}")]
AtHeight(u64),
#[strum(to_string = "expiration time: {0}")]
AtTime(Timestamp),
#[strum(to_string = "expiration: never")]
Never {},
}
impl Default for Expiration {
fn default() -> Self {
Expiration::Never {}
}
}
#[saa_type]
#[derive(Display, Copy)]
pub enum Duration {
#[strum(to_string = "height: {0}")]
Height(u64),
#[strum(to_string = "time: {0}")]
Time(u64),
}
#[cfg(feature = "wasm")]
impl Expiration {
pub fn is_expired(&self, block: &crate::wasm::BlockInfo) -> bool {
match self {
Expiration::AtHeight(height) => block.height >= *height,
Expiration::AtTime(time) => block.time.seconds() >= time.seconds(),
Expiration::Never {} => false,
}
}
}
impl std::ops::Add<Duration> for Expiration {
type Output = Result<Expiration, AuthError>;
fn add(self, duration: Duration) -> Result<Expiration, AuthError> {
match (self, duration) {
(Expiration::AtTime(t), Duration::Time(delta)) => {
Ok(Expiration::AtTime(t.plus_seconds(delta)))
}
(Expiration::AtHeight(h), Duration::Height(delta)) => {
Ok(Expiration::AtHeight(h + delta))
}
(Expiration::Never {}, _) => Ok(Expiration::Never {}),
_ => Err(AuthError::generic("Cannot add height and time")),
}
}
}
impl PartialOrd for Expiration {
fn partial_cmp(&self, other: &Expiration) -> Option<Ordering> {
match (self, other) {
(Expiration::AtHeight(h1), Expiration::AtHeight(h2)) => Some(h1.cmp(h2)),
(Expiration::AtTime(t1), Expiration::AtTime(t2)) => Some(t1.cmp(t2)),
(Expiration::Never {}, Expiration::Never {}) => Some(Ordering::Equal),
(Expiration::Never {}, _) => Some(Ordering::Greater),
(_, Expiration::Never {}) => Some(Ordering::Less),
_ => None,
}
}
}