1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum QConstruct {
12 QAC,
14 QAX,
16 QAU,
18 QAo,
20 QAO,
22 QAS,
24 QAr,
26 QAR,
28 QAZ,
30}
31
32impl QConstruct {
33 #[must_use]
36 pub const fn as_str(self) -> &'static str {
37 match self {
38 Self::QAC => "qAC",
39 Self::QAX => "qAX",
40 Self::QAU => "qAU",
41 Self::QAo => "qAo",
42 Self::QAO => "qAO",
43 Self::QAS => "qAS",
44 Self::QAr => "qAr",
45 Self::QAR => "qAR",
46 Self::QAZ => "qAZ",
47 }
48 }
49
50 #[must_use]
53 pub fn from_path_element(s: &str) -> Option<Self> {
54 match s {
55 "qAC" => Some(Self::QAC),
56 "qAX" => Some(Self::QAX),
57 "qAU" => Some(Self::QAU),
58 "qAo" => Some(Self::QAo),
59 "qAO" => Some(Self::QAO),
60 "qAS" => Some(Self::QAS),
61 "qAr" => Some(Self::QAr),
62 "qAR" => Some(Self::QAR),
63 "qAZ" => Some(Self::QAZ),
64 _ => None,
65 }
66 }
67}
68
69impl std::fmt::Display for QConstruct {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 f.write_str(self.as_str())
72 }
73}
74
75#[must_use]
82pub fn format_is_packet_with_qconstruct(
83 source: &str,
84 destination: &str,
85 path: &[&str],
86 qconstruct: QConstruct,
87 gate_callsign: &str,
88 data: &str,
89) -> String {
90 let mut packet = format!("{source}>{destination}");
91 for p in path {
92 packet.push(',');
93 packet.push_str(p);
94 }
95 packet.push(',');
96 packet.push_str(qconstruct.as_str());
97 packet.push(',');
98 packet.push_str(gate_callsign);
99 packet.push(':');
100 packet.push_str(data);
101 packet.push_str("\r\n");
102 packet
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn qconstruct_round_trip() {
111 let all = [
112 QConstruct::QAC,
113 QConstruct::QAX,
114 QConstruct::QAU,
115 QConstruct::QAo,
116 QConstruct::QAO,
117 QConstruct::QAS,
118 QConstruct::QAr,
119 QConstruct::QAR,
120 QConstruct::QAZ,
121 ];
122 for q in all {
123 assert_eq!(
124 QConstruct::from_path_element(q.as_str()),
125 Some(q),
126 "round-trip failed for {q:?}"
127 );
128 }
129 assert_eq!(QConstruct::from_path_element("WIDE1-1"), None);
130 }
131
132 #[test]
133 fn format_is_packet_with_qconstruct_injects_tag() {
134 let pkt = format_is_packet_with_qconstruct(
135 "N0CALL",
136 "APK005",
137 &["WIDE1-1"],
138 QConstruct::QAC,
139 "N0CALL",
140 "!4903.50N/07201.75W-",
141 );
142 assert_eq!(
143 pkt,
144 "N0CALL>APK005,WIDE1-1,qAC,N0CALL:!4903.50N/07201.75W-\r\n"
145 );
146 }
147}