leodos_protocols/coding/
crc.rs1use crate::network::spp::Apid;
6use crate::network::spp::BuildError;
7use crate::network::spp::PacketType;
8use crate::network::spp::PacketVersion;
9use crate::network::spp::PrimaryHeader;
10use crate::network::spp::SequenceCount;
11use crate::network::spp::SpacePacket;
12use crate::network::spp::SpacePacketData;
13
14use core::fmt::Display;
15use core::mem::size_of;
16use core::ops::Deref;
17use core::ops::DerefMut;
18use zerocopy::FromBytes;
19use zerocopy::IntoBytes;
20use zerocopy::byteorder::network_endian::U16;
21
22pub struct CrcSpacePacket<'a, 'b> {
25 packet: &'a mut SpacePacket,
26 crc_bytes: &'a mut [u8],
27 crc_alg: &'b crc::Crc<u16>,
28}
29
30#[derive(Debug, Copy, Clone, Eq, PartialEq)]
32pub enum BuilderError {
33 Spec(BuildError),
35 BufferTooSmall {
37 required: usize,
39 provided: usize,
41 },
42}
43
44impl Display for BuilderError {
45 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46 match self {
47 BuilderError::Spec(e) => write!(f, "Specification error: {e}"),
48 BuilderError::BufferTooSmall { required, provided } => {
49 write!(
50 f,
51 "Buffer too small for CRC packet: required {required}, provided {provided}"
52 )
53 }
54 }
55 }
56}
57
58#[derive(Copy, Clone, Eq, PartialEq, Debug)]
60pub enum CrcError {
61 Build(BuilderError),
63 BufferTooSmall {
65 required: usize,
67 provided: usize,
69 },
70 ValidationFailed {
72 expected: u16,
74 calculated: u16,
76 },
77 DataField(crate::network::spp::DataFieldError),
79}
80
81impl core::fmt::Display for CrcError {
82 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83 match self {
84 CrcError::Build(e) => write!(f, "Build error: {e}"),
85 CrcError::BufferTooSmall { required, provided } => {
86 write!(
87 f,
88 "Buffer too small for CRC packet: required {required}, provided {provided}"
89 )
90 }
91 CrcError::ValidationFailed {
92 expected,
93 calculated,
94 } => {
95 write!(
96 f,
97 "CRC validation failed: expected {expected:#06X}, calculated {calculated:#06X}"
98 )
99 }
100 CrcError::DataField(e) => write!(f, "Data field error: {e}"),
101 }
102 }
103}
104
105impl From<BuilderError> for CrcError {
106 fn from(e: BuilderError) -> Self {
107 CrcError::Build(e)
108 }
109}
110impl From<crate::network::spp::DataFieldError> for CrcError {
111 fn from(e: crate::network::spp::DataFieldError) -> Self {
112 CrcError::DataField(e)
113 }
114}
115
116impl<'a, 'b> CrcSpacePacket<'a, 'b> {
117 pub fn new(
119 buffer: &'a mut [u8],
120 apid: Apid,
121 packet_type: PacketType,
122 sequence_count: SequenceCount,
123 secondary_header_flag: crate::network::spp::SecondaryHeaderFlag,
124 sequence_flag: crate::network::spp::SequenceFlag,
125 data_field_len: u16,
126 crc_alg: &'b crc::Crc<u16>,
127 ) -> Result<CrcSpacePacket<'a, 'b>, CrcError> {
128 let required_len = size_of::<PrimaryHeader>() + data_field_len as usize;
129 if required_len + 2 > buffer.len() {
130 return Err(CrcError::BufferTooSmall {
131 required: required_len + 2,
132 provided: buffer.len(),
133 });
134 }
135
136 let (packet_buf, crc_buf) = buffer[..required_len + 2].split_at_mut(required_len);
137 let packet = SpacePacket::mut_from_bytes(packet_buf).unwrap();
138
139 packet.set_version(PacketVersion::VERSION_1);
141 packet.set_packet_type(packet_type);
142 packet.set_apid(apid);
143 packet.set_sequence_count(sequence_count);
144 packet.set_data_field_len(data_field_len);
145 packet.set_secondary_header_flag(secondary_header_flag);
146 packet.set_sequence_flag(sequence_flag);
147
148 let mut crc_packet = CrcSpacePacket {
150 packet,
151 crc_bytes: crc_buf,
152 crc_alg: crc_alg,
153 };
154
155 crc_packet.update_crc();
157
158 Ok(crc_packet)
159 }
160 pub fn set_data<T: SpacePacketData>(
164 &mut self,
165 data: &T,
166 ) -> Result<(), crate::network::spp::DataFieldError> {
167 self.packet.set_data_field(data)?;
168 self.update_crc();
169 Ok(())
170 }
171
172 pub fn data_as<T: SpacePacketData>(&self) -> Result<&T, CrcError> {
174 self.validate()?;
175 Ok(self.packet.data_as::<T>()?)
176 }
177
178 pub fn data(&self) -> Result<&[u8], CrcError> {
180 self.validate()?;
181 Ok(self.packet.data_field())
182 }
183
184 pub fn validate(&self) -> Result<(), CrcError> {
186 let expected = U16::read_from_bytes(self.crc_bytes).unwrap().get();
187 let calculated = self.crc_alg.checksum(self.packet.as_bytes());
188 if expected == calculated {
189 Ok(())
190 } else {
191 Err(CrcError::ValidationFailed {
192 expected,
193 calculated,
194 })
195 }
196 }
197
198 pub fn update_crc(&mut self) {
201 let calculated = self.crc_alg.checksum(self.packet.as_bytes());
202 U16::new(calculated)
203 .write_to_prefix(self.crc_bytes)
204 .unwrap();
205 }
206}
207
208impl<'a, 'b> Deref for CrcSpacePacket<'a, 'b> {
210 type Target = SpacePacket;
211 fn deref(&self) -> &Self::Target {
212 self.packet
213 }
214}
215impl<'a, 'b> DerefMut for CrcSpacePacket<'a, 'b> {
216 fn deref_mut(&mut self) -> &mut Self::Target {
217 self.packet
218 }
219}