uf_crsf/packets/
flight_mode.rs1use crate::packets::CrsfPacket;
2use crate::packets::PacketType;
3use crate::CrsfParsingError;
4use heapless::String;
5
6const MAX_FLIGHT_MODE_LEN: usize = 59;
7
8#[derive(Clone, Debug, PartialEq)]
12pub struct FlightMode {
13 flight_mode: String<MAX_FLIGHT_MODE_LEN>,
15}
16
17impl FlightMode {
18 pub fn new(flight_mode: &str) -> Result<Self, CrsfParsingError> {
22 if flight_mode.len() > MAX_FLIGHT_MODE_LEN {
23 return Err(CrsfParsingError::InvalidPayloadLength);
24 }
25 let mut s = String::new();
26 s.push_str(flight_mode)
27 .map_err(|_| CrsfParsingError::InvalidPayloadLength)?;
28 Ok(Self { flight_mode: s })
29 }
30
31 pub fn flight_mode(&self) -> &str {
33 self.flight_mode.as_str()
34 }
35}
36
37#[cfg(feature = "defmt")]
38impl defmt::Format for FlightMode {
39 fn format(&self, fmt: defmt::Formatter) {
40 defmt::write!(fmt, "FlightMode {{ flight_mode: {} }}", self.flight_mode())
41 }
42}
43
44impl CrsfPacket for FlightMode {
45 const PACKET_TYPE: PacketType = PacketType::FlightMode;
46 const MIN_PAYLOAD_SIZE: usize = 1;
48
49 fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, CrsfParsingError> {
50 let bytes = self.flight_mode().as_bytes();
51 let len_with_null = bytes.len() + 1;
52 if buffer.len() < len_with_null {
53 return Err(CrsfParsingError::BufferOverflow);
54 }
55 buffer[..bytes.len()].copy_from_slice(bytes);
56 buffer[bytes.len()] = 0; Ok(len_with_null)
58 }
59
60 fn from_bytes(data: &[u8]) -> Result<Self, CrsfParsingError> {
61 let null_pos = data.iter().position(|&b| b == 0).unwrap_or(data.len());
62 let s = core::str::from_utf8(&data[..null_pos])
63 .map_err(|_| CrsfParsingError::InvalidPayload)?;
64 let mut flight_mode = String::new();
65 flight_mode
66 .push_str(s)
67 .map_err(|_e| CrsfParsingError::InvalidPayloadLength)?;
68 Ok(Self { flight_mode })
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_flight_mode_to_bytes() {
78 let flight_mode = FlightMode::new("ACRO").unwrap();
79
80 let mut buffer = [0u8; 60];
81 let len = flight_mode.to_bytes(&mut buffer).unwrap();
82
83 let expected_bytes: [u8; 5] = [b'A', b'C', b'R', b'O', 0];
84
85 assert_eq!(len, 5);
86 assert_eq!(&buffer[..len], &expected_bytes);
87 }
88
89 #[test]
90 fn test_flight_mode_to_bytes_buffer_too_small() {
91 let flight_mode = FlightMode::new("LONG FLIGHT MODE").unwrap();
92
93 let mut buffer = [0u8; 10];
94 let result = flight_mode.to_bytes(&mut buffer);
95 assert!(matches!(result, Err(CrsfParsingError::BufferOverflow)));
96 }
97
98 #[test]
99 fn test_flight_node_from_bytes_too_small() {
100 let data: [u8; 0] = [];
101 let result = FlightMode::from_bytes(&data);
102 assert_eq!(
103 result.unwrap().flight_mode,
104 String::<MAX_FLIGHT_MODE_LEN>::new()
105 );
106 }
107
108 #[test]
109 fn test_flight_mode_from_bytes() {
110 let data: [u8; 5] = [b'A', b'C', b'R', b'O', 0];
111 let flight_mode = FlightMode::from_bytes(&data).unwrap();
112
113 assert_eq!(flight_mode.flight_mode(), "ACRO");
114 }
115
116 #[test]
117 fn test_flight_mode_from_bytes_no_null() {
118 let data: [u8; 4] = [b'A', b'C', b'R', b'O'];
119 let flight_mode = FlightMode::from_bytes(&data).unwrap();
120
121 assert_eq!(flight_mode.flight_mode(), "ACRO");
122 }
123
124 #[test]
125 fn test_flight_mode_round_trip() {
126 let flight_mode = FlightMode::new("STABILIZE").unwrap();
127
128 let mut buffer = [0u8; 60];
129 let len = flight_mode.to_bytes(&mut buffer).unwrap();
130
131 let round_trip_flight_mode = FlightMode::from_bytes(&buffer[..len]).unwrap();
132
133 assert_eq!(flight_mode, round_trip_flight_mode);
134 }
135
136 #[test]
137 fn test_empty_flight_mode() {
138 let flight_mode = FlightMode::new("").unwrap();
139
140 let mut buffer = [0u8; 60];
141 let len = flight_mode.to_bytes(&mut buffer).unwrap();
142 let round_trip_flight_mode = FlightMode::from_bytes(&buffer[..len]).unwrap();
143 assert_eq!(flight_mode, round_trip_flight_mode);
144 assert_eq!(len, 1);
145 assert_eq!(buffer[0], 0);
146 }
147}