use crate::Duration;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{BlockInfo, StdError, StdResult, Timestamp};
use std::cmp::Ordering;
use std::fmt;
use std::ops::Add;
#[cw_serde]
#[derive(Copy)]
pub enum Scheduled {
AtHeight(u64),
AtTime(Timestamp),
}
impl fmt::Display for Scheduled {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Scheduled::AtHeight(height) => write!(f, "scheduled height: {}", height),
Scheduled::AtTime(time) => write!(f, "scheduled time: {}", time),
}
}
}
impl Scheduled {
#[allow(dead_code)]
pub fn is_triggered(&self, block: &BlockInfo) -> bool {
match self {
Scheduled::AtHeight(height) => block.height >= *height,
Scheduled::AtTime(time) => block.time >= *time,
}
}
}
impl Add<Duration> for Scheduled {
type Output = StdResult<Scheduled>;
fn add(self, duration: Duration) -> StdResult<Scheduled> {
match (self, duration) {
(Scheduled::AtTime(t), Duration::Time(delta)) => {
Ok(Scheduled::AtTime(t.plus_seconds(delta)))
}
(Scheduled::AtHeight(h), Duration::Height(delta)) => Ok(Scheduled::AtHeight(h + delta)),
_ => Err(StdError::generic_err("Cannot add height and time")),
}
}
}
impl PartialOrd for Scheduled {
fn partial_cmp(&self, other: &Scheduled) -> Option<Ordering> {
match (self, other) {
(Scheduled::AtHeight(h1), Scheduled::AtHeight(h2)) => Some(h1.cmp(h2)),
(Scheduled::AtTime(t1), Scheduled::AtTime(t2)) => Some(t1.cmp(t2)),
_ => None,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn compare_schedules() {
assert!(Scheduled::AtHeight(5) < Scheduled::AtHeight(10));
assert!(Scheduled::AtHeight(8) > Scheduled::AtHeight(7));
assert!(
Scheduled::AtTime(Timestamp::from_seconds(555))
< Scheduled::AtTime(Timestamp::from_seconds(777))
);
assert!(
Scheduled::AtTime(Timestamp::from_seconds(86))
< Scheduled::AtTime(Timestamp::from_seconds(100))
);
assert_eq!(
None,
Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230))
);
assert_eq!(
Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230)),
None
);
assert_eq!(
Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230)),
None
);
assert!(!(Scheduled::AtTime(Timestamp::from_seconds(1000)) == Scheduled::AtHeight(230)));
}
#[test]
fn schedule_addition() {
let end = Scheduled::AtHeight(12345) + Duration::Height(400);
assert_eq!(end.unwrap(), Scheduled::AtHeight(12745));
let end = Scheduled::AtTime(Timestamp::from_seconds(55544433)) + Duration::Time(40300);
assert_eq!(
end.unwrap(),
Scheduled::AtTime(Timestamp::from_seconds(55584733))
);
let end = Scheduled::AtHeight(12345) + Duration::Time(1500);
end.unwrap_err();
}
}