1use super::keys::interface as interface_key;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum InterfaceKind {
5 Auto,
6 TcpClient,
7 TcpServer,
8 Udp,
9 Serial,
10 Kiss,
11 Ax25Kiss,
12 Rnode,
13 RnodeMulti,
14 Pipe,
15 Backbone,
16 BackboneClient,
17 I2p,
18 Weave,
19 PrnsUsbAuto,
20 PrnsBluetoothAuto,
21 PrnsWebSocketClient,
22 PrnsWebSocketServer,
23}
24
25impl InterfaceKind {
26 pub const CANONICAL_NAMES: &[&str] = &[
27 "AutoInterface",
28 "TCPClientInterface",
29 "TCPServerInterface",
30 "UDPInterface",
31 "SerialInterface",
32 "KISSInterface",
33 "AX25KISSInterface",
34 "RNodeInterface",
35 "RNodeMultiInterface",
36 "PipeInterface",
37 "BackboneInterface",
38 "BackboneClientInterface",
39 "I2PInterface",
40 "WeaveInterface",
41 "PrnsUsbAuto",
42 "PrnsBluetoothAuto",
43 "PrnsWebSocketClient",
44 "PrnsWebSocketServer",
45 ];
46
47 pub fn parse(value: &str) -> Option<Self> {
48 match value {
49 "AutoInterface" => Some(Self::Auto),
50 "TCPClientInterface" => Some(Self::TcpClient),
51 "TCPServerInterface" => Some(Self::TcpServer),
52 "UDPInterface" => Some(Self::Udp),
53 "SerialInterface" => Some(Self::Serial),
54 "KISSInterface" => Some(Self::Kiss),
55 "AX25KISSInterface" => Some(Self::Ax25Kiss),
56 "RNodeInterface" => Some(Self::Rnode),
57 "RNodeMultiInterface" => Some(Self::RnodeMulti),
58 "PipeInterface" => Some(Self::Pipe),
59 "BackboneInterface" => Some(Self::Backbone),
60 "BackboneClientInterface" => Some(Self::BackboneClient),
61 "I2PInterface" => Some(Self::I2p),
62 "WeaveInterface" => Some(Self::Weave),
63 _ => Self::parse_prns(value),
64 }
65 }
66
67 pub const fn canonical_name(self) -> &'static str {
68 match self {
69 Self::Auto => "AutoInterface",
70 Self::TcpClient => "TCPClientInterface",
71 Self::TcpServer => "TCPServerInterface",
72 Self::Udp => "UDPInterface",
73 Self::Serial => "SerialInterface",
74 Self::Kiss => "KISSInterface",
75 Self::Ax25Kiss => "AX25KISSInterface",
76 Self::Rnode => "RNodeInterface",
77 Self::RnodeMulti => "RNodeMultiInterface",
78 Self::Pipe => "PipeInterface",
79 Self::Backbone => "BackboneInterface",
80 Self::BackboneClient => "BackboneClientInterface",
81 Self::I2p => "I2PInterface",
82 Self::Weave => "WeaveInterface",
83 Self::PrnsUsbAuto => "PrnsUsbAuto",
84 Self::PrnsBluetoothAuto => "PrnsBluetoothAuto",
85 Self::PrnsWebSocketClient => "PrnsWebSocketClient",
86 Self::PrnsWebSocketServer => "PrnsWebSocketServer",
87 }
88 }
89
90 fn parse_prns(value: &str) -> Option<Self> {
91 if ["PrnsUsbAuto", "PrnsUsbAutoInterface"]
92 .iter()
93 .any(|candidate| value.eq_ignore_ascii_case(candidate))
94 {
95 return Some(Self::PrnsUsbAuto);
96 }
97 if [
98 "PrnsBluetoothAuto",
99 "PrnsBluetoothAutoInterface",
100 "PrnsBleAuto",
101 "PrnsBleAutoInterface",
102 ]
103 .iter()
104 .any(|candidate| value.eq_ignore_ascii_case(candidate))
105 {
106 return Some(Self::PrnsBluetoothAuto);
107 }
108 if ["PrnsWebSocketClient", "PrnsWebSocketClientInterface"]
109 .iter()
110 .any(|candidate| value.eq_ignore_ascii_case(candidate))
111 {
112 return Some(Self::PrnsWebSocketClient);
113 }
114 if ["PrnsWebSocketServer", "PrnsWebSocketServerInterface"]
115 .iter()
116 .any(|candidate| value.eq_ignore_ascii_case(candidate))
117 {
118 return Some(Self::PrnsWebSocketServer);
119 }
120 None
121 }
122
123 pub const fn cli_name(self) -> &'static str {
124 match self {
125 Self::Auto => "auto-wifi",
126 Self::TcpClient => "tcp-client",
127 Self::TcpServer => "tcp-server",
128 Self::Udp => "udp",
129 Self::Serial => "serial",
130 Self::Kiss => "kiss",
131 Self::Ax25Kiss => "ax25-kiss",
132 Self::Rnode => "rnode",
133 Self::RnodeMulti => "rnode-multi",
134 Self::Pipe => "pipe",
135 Self::Backbone => "backbone-server",
136 Self::BackboneClient => "backbone-client",
137 Self::I2p => "i2p",
138 Self::Weave => "weave",
139 Self::PrnsUsbAuto => "usb-auto",
140 Self::PrnsBluetoothAuto => "bluetooth-auto",
141 Self::PrnsWebSocketClient => "websocket-client",
142 Self::PrnsWebSocketServer => "websocket-server",
143 }
144 }
145
146 pub fn parse_cli(value: &str) -> Option<Self> {
147 let normalized = value.trim().to_ascii_lowercase();
148 match normalized.as_str() {
149 "auto" | "auto-wifi" | "wifi-auto" => Some(Self::Auto),
150 "tcp-client" => Some(Self::TcpClient),
151 "tcp-server" => Some(Self::TcpServer),
152 "udp" => Some(Self::Udp),
153 "serial" => Some(Self::Serial),
154 "kiss" => Some(Self::Kiss),
155 "ax25-kiss" | "ax25" => Some(Self::Ax25Kiss),
156 "rnode" => Some(Self::Rnode),
157 "rnode-multi" => Some(Self::RnodeMulti),
158 "pipe" => Some(Self::Pipe),
159 "backbone" | "backbone-server" => Some(Self::Backbone),
160 "backbone-client" => Some(Self::BackboneClient),
161 "i2p" => Some(Self::I2p),
162 "weave" => Some(Self::Weave),
163 "usb" | "usb-auto" => Some(Self::PrnsUsbAuto),
164 "bluetooth" | "bluetooth-auto" | "ble" | "ble-auto" => Some(Self::PrnsBluetoothAuto),
165 "websocket-client" | "ws-client" => Some(Self::PrnsWebSocketClient),
166 "websocket-server" | "ws-server" => Some(Self::PrnsWebSocketServer),
167 _ => Self::parse(value),
168 }
169 }
170
171 pub fn accepts_setting(self, key: &str) -> bool {
172 if interface_key::COMMON.contains(&key) {
173 return true;
174 }
175 let medium = match self {
176 Self::Auto => interface_key::AUTO,
177 Self::TcpClient => interface_key::TCP_CLIENT,
178 Self::TcpServer => interface_key::TCP_SERVER,
179 Self::Udp => interface_key::UDP,
180 Self::Serial => interface_key::SERIAL,
181 Self::Kiss => interface_key::KISS,
182 Self::Ax25Kiss => interface_key::AX25_KISS,
183 Self::Rnode => interface_key::RNODE,
184 Self::RnodeMulti => interface_key::RNODE_MULTI,
185 Self::Pipe => interface_key::PIPE,
186 Self::Backbone | Self::BackboneClient => interface_key::BACKBONE,
187 Self::I2p => interface_key::I2P,
188 Self::Weave => interface_key::WEAVE,
189 Self::PrnsUsbAuto | Self::PrnsBluetoothAuto => &[],
190 Self::PrnsWebSocketClient => interface_key::PRNS_WEBSOCKET_CLIENT,
191 Self::PrnsWebSocketServer => interface_key::PRNS_WEBSOCKET_SERVER,
192 };
193 medium.contains(&key)
194 }
195}
196
197pub(super) use InterfaceKind as InterfaceType;
198
199#[cfg(test)]
200mod tests {
201 use super::InterfaceKind;
202
203 #[test]
204 fn prns_names_normalize_without_relaxing_stock_names() {
205 for alias in [
206 "PrnsUsbAuto",
207 "prnsusbauto",
208 "PRNSUSBAUTOINTERFACE",
209 "PrnsBluetoothAuto",
210 "prnsbleauto",
211 "PRNSBLEAUTOINTERFACE",
212 "prnswebsocketclient",
213 "PRNSWEBSOCKETCLIENTINTERFACE",
214 "prnswebsocketserver",
215 "PRNSWEBSOCKETSERVERINTERFACE",
216 ] {
217 assert!(InterfaceKind::parse(alias).is_some(), "{alias}");
218 }
219 assert_eq!(InterfaceKind::parse("autointerface"), None);
220 }
221}