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}