1 use self::Kind::*;
2 use std::error;
3 use std::fmt;
4 
5 /// Errors encountered by the timer implementation.
6 ///
7 /// Currently, there are two different errors that can occur:
8 ///
9 /// * `shutdown` occurs when a timer operation is attempted, but the timer
10 ///   instance has been dropped. In this case, the operation will never be able
11 ///   to complete and the `shutdown` error is returned. This is a permanent
12 ///   error, i.e., once this error is observed, timer operations will never
13 ///   succeed in the future.
14 ///
15 /// * `at_capacity` occurs when a timer operation is attempted, but the timer
16 ///   instance is currently handling its maximum number of outstanding delays.
17 ///   In this case, the operation is not able to be performed at the current
18 ///   moment, and `at_capacity` is returned. This is a transient error, i.e., at
19 ///   some point in the future, if the operation is attempted again, it might
20 ///   succeed. Callers that observe this error should attempt to [shed load]. One
21 ///   way to do this would be dropping the future that issued the timer operation.
22 ///
23 /// [shed load]: https://en.wikipedia.org/wiki/Load_Shedding
24 #[derive(Debug)]
25 pub struct Error(Kind);
26 
27 #[derive(Debug, Clone, Copy)]
28 #[repr(u8)]
29 enum Kind {
30     Shutdown = 1,
31     AtCapacity = 2,
32     Invalid = 3,
33 }
34 
35 impl Error {
36     /// Creates an error representing a shutdown timer.
shutdown() -> Error37     pub fn shutdown() -> Error {
38         Error(Shutdown)
39     }
40 
41     /// Returns `true` if the error was caused by the timer being shutdown.
is_shutdown(&self) -> bool42     pub fn is_shutdown(&self) -> bool {
43         match self.0 {
44             Kind::Shutdown => true,
45             _ => false,
46         }
47     }
48 
49     /// Creates an error representing a timer at capacity.
at_capacity() -> Error50     pub fn at_capacity() -> Error {
51         Error(AtCapacity)
52     }
53 
54     /// Returns `true` if the error was caused by the timer being at capacity.
is_at_capacity(&self) -> bool55     pub fn is_at_capacity(&self) -> bool {
56         match self.0 {
57             Kind::AtCapacity => true,
58             _ => false,
59         }
60     }
61 
62     /// Create an error representing a misconfigured timer.
invalid() -> Error63     pub fn invalid() -> Error {
64         Error(Invalid)
65     }
66 
67     /// Returns `true` if the error was caused by the timer being misconfigured.
is_invalid(&self) -> bool68     pub fn is_invalid(&self) -> bool {
69         match self.0 {
70             Kind::Invalid => true,
71             _ => false,
72         }
73     }
74 
as_u8(&self) -> u875     pub(crate) fn as_u8(&self) -> u8 {
76         self.0 as u8
77     }
78 
from_u8(n: u8) -> Self79     pub(crate) fn from_u8(n: u8) -> Self {
80         Error(match n {
81             1 => Shutdown,
82             2 => AtCapacity,
83             3 => Invalid,
84             _ => panic!("u8 does not correspond to any time error variant"),
85         })
86     }
87 }
88 
89 impl error::Error for Error {}
90 
91 impl fmt::Display for Error {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result92     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
93         use self::Kind::*;
94         let descr = match self.0 {
95             Shutdown => "the timer is shutdown, must be called from the context of Tokio runtime",
96             AtCapacity => "timer is at capacity and cannot create a new entry",
97             Invalid => "timer duration exceeds maximum duration",
98         };
99         write!(fmt, "{}", descr)
100     }
101 }
102