1use bincode::de::Decoder;
2use bincode::enc::Encoder;
3use bincode::error::{DecodeError, EncodeError};
4use bincode::{Decode, Encode};
5use crsf::{LinkStatistics, RcChannels};
6use cu29::prelude::*;
7use serde::{Deserialize, Serialize};
8
9#[derive(Clone, Debug, Reflect)]
11#[reflect(opaque, from_reflect = false)]
12pub struct RcChannelsPayload(pub RcChannels);
13
14impl RcChannelsPayload {
15 pub fn inner(&self) -> &RcChannels {
17 &self.0
18 }
19
20 pub fn inner_mut(&mut self) -> &mut RcChannels {
22 &mut self.0
23 }
24}
25
26impl From<RcChannels> for RcChannelsPayload {
27 fn from(value: RcChannels) -> Self {
28 Self(value)
29 }
30}
31
32impl From<RcChannelsPayload> for RcChannels {
33 fn from(value: RcChannelsPayload) -> Self {
34 value.0
35 }
36}
37
38impl Default for RcChannelsPayload {
39 fn default() -> Self {
40 Self(RcChannels([0; 16]))
41 }
42}
43
44impl PartialEq for RcChannelsPayload {
45 fn eq(&self, other: &Self) -> bool {
46 self.0.0 == other.0.0
47 }
48}
49
50impl Eq for RcChannelsPayload {}
51
52impl Encode for RcChannelsPayload {
53 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
54 for value in self.0.0.iter() {
55 Encode::encode(value, encoder)?;
56 }
57 Ok(())
58 }
59}
60
61impl Decode<()> for RcChannelsPayload {
62 fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, DecodeError> {
63 let mut channels = [0u16; 16];
64 for slot in channels.iter_mut() {
65 *slot = Decode::decode(decoder)?;
66 }
67 Ok(Self(RcChannels(channels)))
68 }
69}
70
71impl Serialize for RcChannelsPayload {
72 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73 where
74 S: serde::Serializer,
75 {
76 self.inner().0.serialize(serializer)
77 }
78}
79
80impl<'de> Deserialize<'de> for RcChannelsPayload {
81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82 where
83 D: serde::Deserializer<'de>,
84 {
85 let channels = <[u16; 16]>::deserialize(deserializer)?;
86 Ok(Self(RcChannels(channels)))
87 }
88}
89
90#[derive(Clone, Debug, Reflect)]
92#[reflect(opaque, from_reflect = false)]
93pub struct LinkStatisticsPayload(pub LinkStatistics);
94
95impl LinkStatisticsPayload {
96 pub fn inner(&self) -> &LinkStatistics {
97 &self.0
98 }
99}
100
101impl From<LinkStatistics> for LinkStatisticsPayload {
102 fn from(value: LinkStatistics) -> Self {
103 Self(value)
104 }
105}
106
107impl From<LinkStatisticsPayload> for LinkStatistics {
108 fn from(value: LinkStatisticsPayload) -> Self {
109 value.0
110 }
111}
112
113impl PartialEq for LinkStatisticsPayload {
114 fn eq(&self, other: &Self) -> bool {
115 let LinkStatisticsPayload(link_a) = self;
116 let LinkStatisticsPayload(link_b) = other;
117 link_a.uplink_rssi_1 == link_b.uplink_rssi_1
118 && link_a.uplink_rssi_2 == link_b.uplink_rssi_2
119 && link_a.uplink_link_quality == link_b.uplink_link_quality
120 && link_a.uplink_snr == link_b.uplink_snr
121 && link_a.active_antenna == link_b.active_antenna
122 && link_a.rf_mode == link_b.rf_mode
123 && link_a.uplink_tx_power == link_b.uplink_tx_power
124 && link_a.downlink_rssi == link_b.downlink_rssi
125 && link_a.downlink_link_quality == link_b.downlink_link_quality
126 && link_a.downlink_snr == link_b.downlink_snr
127 }
128}
129
130impl Eq for LinkStatisticsPayload {}
131
132impl Default for LinkStatisticsPayload {
133 fn default() -> Self {
134 Self(LinkStatistics {
135 uplink_rssi_1: 0,
136 uplink_rssi_2: 0,
137 uplink_link_quality: 0,
138 uplink_snr: 0,
139 active_antenna: 0,
140 rf_mode: 0,
141 uplink_tx_power: 0,
142 downlink_rssi: 0,
143 downlink_link_quality: 0,
144 downlink_snr: 0,
145 })
146 }
147}
148impl Encode for LinkStatisticsPayload {
149 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
150 let stats = &self.0;
151 Encode::encode(&stats.uplink_rssi_1, encoder)?;
152 Encode::encode(&stats.uplink_rssi_2, encoder)?;
153 Encode::encode(&stats.uplink_link_quality, encoder)?;
154 Encode::encode(&stats.uplink_snr, encoder)?;
155 Encode::encode(&stats.active_antenna, encoder)?;
156 Encode::encode(&stats.rf_mode, encoder)?;
157 Encode::encode(&stats.uplink_tx_power, encoder)?;
158 Encode::encode(&stats.downlink_rssi, encoder)?;
159 Encode::encode(&stats.downlink_link_quality, encoder)?;
160 Encode::encode(&stats.downlink_snr, encoder)?;
161 Ok(())
162 }
163}
164
165impl Decode<()> for LinkStatisticsPayload {
166 fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, DecodeError> {
167 Ok(Self(LinkStatistics {
168 uplink_rssi_1: Decode::decode(decoder)?,
169 uplink_rssi_2: Decode::decode(decoder)?,
170 uplink_link_quality: Decode::decode(decoder)?,
171 uplink_snr: Decode::decode(decoder)?,
172 active_antenna: Decode::decode(decoder)?,
173 rf_mode: Decode::decode(decoder)?,
174 uplink_tx_power: Decode::decode(decoder)?,
175 downlink_rssi: Decode::decode(decoder)?,
176 downlink_link_quality: Decode::decode(decoder)?,
177 downlink_snr: Decode::decode(decoder)?,
178 }))
179 }
180}
181
182impl Serialize for LinkStatisticsPayload {
183 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184 where
185 S: serde::Serializer,
186 {
187 let stats = &self.0;
188 (
189 stats.uplink_rssi_1,
190 stats.uplink_rssi_2,
191 stats.uplink_link_quality,
192 stats.uplink_snr,
193 stats.active_antenna,
194 stats.rf_mode,
195 stats.uplink_tx_power,
196 stats.downlink_rssi,
197 stats.downlink_link_quality,
198 stats.downlink_snr,
199 )
200 .serialize(serializer)
201 }
202}
203
204impl<'de> Deserialize<'de> for LinkStatisticsPayload {
205 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
206 where
207 D: serde::Deserializer<'de>,
208 {
209 let (
210 uplink_rssi_1,
211 uplink_rssi_2,
212 uplink_link_quality,
213 uplink_snr,
214 active_antenna,
215 rf_mode,
216 uplink_tx_power,
217 downlink_rssi,
218 downlink_link_quality,
219 downlink_snr,
220 ) = <(u8, u8, u8, i8, u8, u8, u8, u8, u8, i8)>::deserialize(deserializer)?;
221 Ok(Self(LinkStatistics {
222 uplink_rssi_1,
223 uplink_rssi_2,
224 uplink_link_quality,
225 uplink_snr,
226 active_antenna,
227 rf_mode,
228 uplink_tx_power,
229 downlink_rssi,
230 downlink_link_quality,
231 downlink_snr,
232 }))
233 }
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239 use bincode::{config, decode_from_slice, encode_to_vec};
240
241 fn assert_roundtrip<T>(payload: &T)
242 where
243 T: Encode + Decode<()> + PartialEq + core::fmt::Debug,
244 {
245 let cfg = config::standard();
246 let encoded = encode_to_vec(payload, cfg).expect("encode");
247 let (decoded, consumed): (T, usize) = decode_from_slice(&encoded, cfg).expect("decode");
248 assert_eq!(consumed, encoded.len());
249 assert_eq!(decoded, *payload);
250 }
251
252 #[test]
253 fn rc_channels_round_trip() {
254 let mut channels = [0u16; 16];
255 for (idx, value) in channels.iter_mut().enumerate() {
256 *value = (idx as u16) * 42;
257 }
258 let payload = RcChannelsPayload(RcChannels(channels));
259 assert_roundtrip(&payload);
260 assert_eq!(payload.0.0, channels);
261 }
262
263 #[test]
264 fn link_statistics_round_trip() {
265 let stats = LinkStatistics {
266 uplink_rssi_1: 100,
267 uplink_rssi_2: 98,
268 uplink_link_quality: 95,
269 uplink_snr: -12,
270 active_antenna: 1,
271 rf_mode: 2,
272 uplink_tx_power: 5,
273 downlink_rssi: 110,
274 downlink_link_quality: 90,
275 downlink_snr: -9,
276 };
277 assert_roundtrip(&LinkStatisticsPayload(stats));
278 }
279}