idem_handler/
status.rs

1use std::fmt::{Display, Formatter};
2use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
3
4#[derive(Debug)]
5pub struct HandlerExecutionError {
6    message: String,
7}
8
9impl Display for HandlerExecutionError {
10    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
11        write!(f, "Fatal error: {}", self.message)
12    }
13}
14
15pub struct HandlerStatus {
16    pub(crate) code: Code,
17    message: Option<&'static str>,
18    details: Option<&'static str>,
19}
20
21impl HandlerStatus {
22    pub fn code(&self) -> Code {
23        self.code
24    }
25    pub fn message(&self) -> &'static str {
26        self.message.unwrap_or_else(|| "")
27    }
28
29    pub fn details(&self) -> &'static str {
30        self.details.unwrap_or_else(|| "")
31    }
32
33    pub fn new(code: Code) -> HandlerStatus {
34        Self {
35            code,
36            message: None,
37            details: None,
38        }
39    }
40
41    pub fn set_message(mut self, message: &'static str) -> HandlerStatus {
42        self.message = Some(message);
43        self
44    }
45
46    pub fn set_details(mut self, description: &'static str) -> HandlerStatus {
47        self.details = Some(description);
48        self
49    }
50}
51
52#[derive(Clone, Copy)]
53pub struct Code(pub i32);
54
55impl Code {
56    pub const OK: Self = Self(1);
57    pub const REQUEST_COMPLETED: Self = Self(1 << 1);
58    pub const SERVER_ERROR: Self = Self(1 << 2);
59    pub const CLIENT_ERROR: Self = Self(1 << 3);
60    pub const DISABLED: Self = Self(1 << 4);
61    pub const TIMEOUT: Self = Self(1 << 5);
62    pub const CONTINUE: Self = Self(1 << 6);
63
64    pub fn any_flags(&self, flags: Code) -> bool {
65        self.0 & flags.0 != 0
66    }
67
68    pub fn any_flags_clear(&self, flags: Code) -> bool {
69        self.0 & flags.0 != flags.0
70    }
71
72    pub fn all_flags(&self, flags: Code) -> bool {
73        self.0 & flags.0 == flags.0
74    }
75
76    pub fn all_flags_clear(&self, flags: Code) -> bool {
77        self.0 & flags.0 == 0
78    }
79}
80
81impl PartialEq for Code {
82    fn eq(&self, other: &Self) -> bool {
83        self.0 == other.0
84    }
85}
86
87impl BitOrAssign for Code {
88    fn bitor_assign(&mut self, rhs: Self) {
89        self.0 |= rhs.0
90    }
91}
92
93impl BitAndAssign for Code {
94    fn bitand_assign(&mut self, rhs: Self) {
95        self.0 &= rhs.0
96    }
97}
98
99impl Not for Code {
100    type Output = Self;
101
102    fn not(self) -> Self::Output {
103        Self(!self.0)
104    }
105}
106
107impl BitAnd for Code {
108    type Output = Self;
109    fn bitand(self, rhs: Self) -> Self::Output {
110        Self(self.0 & rhs.0)
111    }
112}
113
114impl BitOr for Code {
115    type Output = Self;
116    fn bitor(self, rhs: Self) -> Self::Output {
117        Self(self.0 | rhs.0)
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use crate::status::Code;
124
125    #[test]
126    fn test_status_flags() {
127        let mut test_code = Code::OK;
128        test_code |= Code::REQUEST_COMPLETED;
129        assert!(test_code.all_flags(Code::OK | Code::REQUEST_COMPLETED));
130        assert!(test_code.all_flags_clear(Code::DISABLED | Code::TIMEOUT | Code::CONTINUE | Code::CLIENT_ERROR | Code::SERVER_ERROR));
131    }
132
133    #[test]
134    fn test_status_constructs() {
135        let test_code1 = Code::OK | Code::SERVER_ERROR;
136        let test_code2 = Code::from(test_code1 | Code::REQUEST_COMPLETED);
137        assert!(test_code2.all_flags(Code::OK | Code::SERVER_ERROR | Code::REQUEST_COMPLETED));
138    }
139}