1use crate::Duration;
2use cosmwasm_schema::cw_serde;
3use cosmwasm_std::{BlockInfo, StdError, StdResult, Timestamp};
4use std::cmp::Ordering;
5use std::fmt;
6use std::ops::Add;
7
8#[cw_serde]
12#[derive(Copy)]
13pub enum Scheduled {
14 AtHeight(u64),
16 AtTime(Timestamp),
18}
19
20impl fmt::Display for Scheduled {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 match self {
23 Scheduled::AtHeight(height) => write!(f, "scheduled height: {}", height),
24 Scheduled::AtTime(time) => write!(f, "scheduled time: {}", time),
25 }
26 }
27}
28
29impl Scheduled {
30 #[allow(dead_code)]
31 pub fn is_triggered(&self, block: &BlockInfo) -> bool {
32 match self {
33 Scheduled::AtHeight(height) => block.height >= *height,
34 Scheduled::AtTime(time) => block.time >= *time,
35 }
36 }
37}
38
39impl Add<Duration> for Scheduled {
40 type Output = StdResult<Scheduled>;
41
42 fn add(self, duration: Duration) -> StdResult<Scheduled> {
43 match (self, duration) {
44 (Scheduled::AtTime(t), Duration::Time(delta)) => {
45 Ok(Scheduled::AtTime(t.plus_seconds(delta)))
46 }
47 (Scheduled::AtHeight(h), Duration::Height(delta)) => Ok(Scheduled::AtHeight(h + delta)),
48 _ => Err(StdError::msg("Cannot add height and time")),
49 }
50 }
51}
52
53impl PartialOrd for Scheduled {
54 fn partial_cmp(&self, other: &Scheduled) -> Option<Ordering> {
55 match (self, other) {
56 (Scheduled::AtHeight(h1), Scheduled::AtHeight(h2)) => Some(h1.cmp(h2)),
58 (Scheduled::AtTime(t1), Scheduled::AtTime(t2)) => Some(t1.cmp(t2)),
59 _ => None,
60 }
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::*;
67
68 #[test]
69 fn compare_schedules() {
70 assert!(Scheduled::AtHeight(5) < Scheduled::AtHeight(10));
72 assert!(Scheduled::AtHeight(8) > Scheduled::AtHeight(7));
73 assert!(
74 Scheduled::AtTime(Timestamp::from_seconds(555))
75 < Scheduled::AtTime(Timestamp::from_seconds(777))
76 );
77 assert!(
78 Scheduled::AtTime(Timestamp::from_seconds(86))
79 < Scheduled::AtTime(Timestamp::from_seconds(100))
80 );
81
82 assert_eq!(
84 None,
85 Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230))
86 );
87 assert_eq!(
88 Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230)),
89 None
90 );
91 assert_eq!(
92 Scheduled::AtTime(Timestamp::from_seconds(1000)).partial_cmp(&Scheduled::AtHeight(230)),
93 None
94 );
95 assert!(!(Scheduled::AtTime(Timestamp::from_seconds(1000)) == Scheduled::AtHeight(230)));
96 }
97
98 #[test]
99 fn schedule_addition() {
100 let end = Scheduled::AtHeight(12345) + Duration::Height(400);
102 assert_eq!(end.unwrap(), Scheduled::AtHeight(12745));
103
104 let end = Scheduled::AtTime(Timestamp::from_seconds(55544433)) + Duration::Time(40300);
106 assert_eq!(
107 end.unwrap(),
108 Scheduled::AtTime(Timestamp::from_seconds(55584733))
109 );
110
111 let end = Scheduled::AtHeight(12345) + Duration::Time(1500);
113 end.unwrap_err();
114 }
115}