1use std::fmt;
4use std::str::FromStr;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ParseGatewayRegStateError(pub String);
9
10impl fmt::Display for ParseGatewayRegStateError {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "unknown gateway reg state: {}", self.0)
13 }
14}
15
16impl std::error::Error for ParseGatewayRegStateError {}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[non_exhaustive]
25#[allow(missing_docs)]
26pub enum GatewayRegState {
27 Unreged,
28 Trying,
29 Register,
30 Reged,
31 Unregister,
32 Failed,
33 FailWait,
34 Expired,
35 Noreg,
36 Down,
37 Timeout,
38}
39
40impl GatewayRegState {
41 pub const fn as_str(&self) -> &'static str {
43 match self {
44 Self::Unreged => "UNREGED",
45 Self::Trying => "TRYING",
46 Self::Register => "REGISTER",
47 Self::Reged => "REGED",
48 Self::Unregister => "UNREGISTER",
49 Self::Failed => "FAILED",
50 Self::FailWait => "FAIL_WAIT",
51 Self::Expired => "EXPIRED",
52 Self::Noreg => "NOREG",
53 Self::Down => "DOWN",
54 Self::Timeout => "TIMEOUT",
55 }
56 }
57}
58
59impl fmt::Display for GatewayRegState {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str(self.as_str())
62 }
63}
64
65impl FromStr for GatewayRegState {
66 type Err = ParseGatewayRegStateError;
67
68 fn from_str(s: &str) -> Result<Self, Self::Err> {
69 match s {
70 "UNREGED" => Ok(Self::Unreged),
71 "TRYING" => Ok(Self::Trying),
72 "REGISTER" => Ok(Self::Register),
73 "REGED" => Ok(Self::Reged),
74 "UNREGISTER" => Ok(Self::Unregister),
75 "FAILED" => Ok(Self::Failed),
76 "FAIL_WAIT" => Ok(Self::FailWait),
77 "EXPIRED" => Ok(Self::Expired),
78 "NOREG" => Ok(Self::Noreg),
79 "DOWN" => Ok(Self::Down),
80 "TIMEOUT" => Ok(Self::Timeout),
81 _ => Err(ParseGatewayRegStateError(s.to_string())),
82 }
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct ParseGatewayPingStatusError(pub String);
89
90impl fmt::Display for ParseGatewayPingStatusError {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 write!(f, "unknown gateway ping status: {}", self.0)
93 }
94}
95
96impl std::error::Error for ParseGatewayPingStatusError {}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103#[non_exhaustive]
104#[allow(missing_docs)]
105pub enum GatewayPingStatus {
106 Down,
107 Up,
108 Invalid,
109}
110
111impl GatewayPingStatus {
112 pub const fn as_str(&self) -> &'static str {
114 match self {
115 Self::Down => "DOWN",
116 Self::Up => "UP",
117 Self::Invalid => "INVALID",
118 }
119 }
120}
121
122impl fmt::Display for GatewayPingStatus {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 f.write_str(self.as_str())
125 }
126}
127
128impl FromStr for GatewayPingStatus {
129 type Err = ParseGatewayPingStatusError;
130
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 match s {
133 "DOWN" => Ok(Self::Down),
134 "UP" => Ok(Self::Up),
135 "INVALID" => Ok(Self::Invalid),
136 _ => Err(ParseGatewayPingStatusError(s.to_string())),
137 }
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 const ALL_REG_STATES: &[GatewayRegState] = &[
146 GatewayRegState::Unreged,
147 GatewayRegState::Trying,
148 GatewayRegState::Register,
149 GatewayRegState::Reged,
150 GatewayRegState::Unregister,
151 GatewayRegState::Failed,
152 GatewayRegState::FailWait,
153 GatewayRegState::Expired,
154 GatewayRegState::Noreg,
155 GatewayRegState::Down,
156 GatewayRegState::Timeout,
157 ];
158
159 #[test]
160 fn reg_state_round_trip() {
161 for &state in ALL_REG_STATES {
162 let wire = state.to_string();
163 let parsed: GatewayRegState = wire
164 .parse()
165 .unwrap();
166 assert_eq!(parsed, state, "round-trip failed for {wire}");
167 }
168 }
169
170 #[test]
171 fn reg_state_count() {
172 assert_eq!(ALL_REG_STATES.len(), 11);
173 }
174
175 #[test]
176 fn reg_state_rejects_unknown() {
177 assert!("BOGUS"
178 .parse::<GatewayRegState>()
179 .is_err());
180 assert!("reged"
181 .parse::<GatewayRegState>()
182 .is_err());
183 }
184
185 const ALL_PING_STATUSES: &[GatewayPingStatus] = &[
186 GatewayPingStatus::Down,
187 GatewayPingStatus::Up,
188 GatewayPingStatus::Invalid,
189 ];
190
191 #[test]
192 fn ping_status_round_trip() {
193 for &status in ALL_PING_STATUSES {
194 let wire = status.to_string();
195 let parsed: GatewayPingStatus = wire
196 .parse()
197 .unwrap();
198 assert_eq!(parsed, status, "round-trip failed for {wire}");
199 }
200 }
201
202 #[test]
203 fn ping_status_rejects_unknown() {
204 assert!("BOGUS"
205 .parse::<GatewayPingStatus>()
206 .is_err());
207 assert!("up"
208 .parse::<GatewayPingStatus>()
209 .is_err());
210 }
211}