1use std::{fmt, future::Future, pin::Pin, task::Context};
2
3use actix_rt::time::{Instant, Sleep};
4use tracing::trace;
5
6#[derive(Debug)]
7pub(super) enum TimerState {
8 Disabled,
9 Inactive,
10 Active { timer: Pin<Box<Sleep>> },
11}
12
13impl TimerState {
14 pub(super) fn new(enabled: bool) -> Self {
15 if enabled {
16 Self::Inactive
17 } else {
18 Self::Disabled
19 }
20 }
21
22 pub(super) fn is_enabled(&self) -> bool {
23 matches!(self, Self::Active { .. } | Self::Inactive)
24 }
25
26 pub(super) fn set(&mut self, timer: Sleep, line: u32) {
27 if matches!(self, Self::Disabled) {
28 trace!("setting disabled timer from line {}", line);
29 }
30
31 *self = Self::Active {
32 timer: Box::pin(timer),
33 };
34 }
35
36 pub(super) fn set_and_init(&mut self, cx: &mut Context<'_>, timer: Sleep, line: u32) {
37 self.set(timer, line);
38 self.init(cx);
39 }
40
41 pub(super) fn clear(&mut self, line: u32) {
42 if matches!(self, Self::Disabled) {
43 trace!("trying to clear a disabled timer from line {}", line);
44 }
45
46 if matches!(self, Self::Inactive) {
47 trace!("trying to clear an inactive timer from line {}", line);
48 }
49
50 *self = Self::Inactive;
51 }
52
53 pub(super) fn init(&mut self, cx: &mut Context<'_>) {
54 if let TimerState::Active { timer } = self {
55 let _ = timer.as_mut().poll(cx);
56 }
57 }
58}
59
60impl fmt::Display for TimerState {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 TimerState::Disabled => f.write_str("timer is disabled"),
64 TimerState::Inactive => f.write_str("timer is inactive"),
65 TimerState::Active { timer } => {
66 let deadline = timer.deadline();
67 let now = Instant::now();
68
69 if deadline < now {
70 f.write_str("timer is active and has reached deadline")
71 } else {
72 write!(
73 f,
74 "timer is active and due to expire in {} milliseconds",
75 ((deadline - now).as_secs_f32() * 1000.0)
76 )
77 }
78 }
79 }
80 }
81}