1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![forbid(unsafe_code)]
4use thiserror::Error;
15use zerocopy::byteorder::network_endian;
16use zerocopy::{
17 ByteEq, ByteHash, CastError, FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned,
18};
19
20#[repr(C, packed)]
35#[derive(ByteEq, FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
36pub struct SpacePacket {
37 primary_header: SpacePacketPrimaryHeader,
38 data_field: [u8],
39}
40
41impl SpacePacket {
42 pub fn parse(bytes: &[u8]) -> Result<&Self, InvalidSpacePacket> {
52 let primary_header = match Self::ref_from_bytes(bytes) {
55 Ok(primary_header) => primary_header,
56 Err(CastError::Size(_)) => {
57 return Err(InvalidSpacePacket::SliceTooSmallForSpacePacketHeader {
58 length: bytes.len(),
59 });
60 }
61 Err(CastError::Alignment(_)) => unreachable!(),
62 };
63
64 primary_header.validate()?;
67
68 let packet_size = primary_header.packet_data_length() + Self::primary_header_size();
71 let packet_bytes = &bytes[..packet_size];
72 let Ok(packet) = Self::ref_from_bytes(packet_bytes) else {
73 unreachable!()
74 };
75
76 Ok(packet)
77 }
78
79 pub fn construct(
91 buffer: &mut [u8],
92 packet_type: PacketType,
93 secondary_header_flag: SecondaryHeaderFlag,
94 apid: Apid,
95 sequence_flag: SequenceFlag,
96 sequence_count: PacketSequenceCount,
97 ) -> Result<&mut Self, InvalidPacketDataLength> {
98 if buffer.len() < 7 {
99 return Err(InvalidPacketDataLength::LargerThanBuffer {
100 buffer_length: buffer.len(),
101 packet_data_length: 1,
102 });
103 }
104
105 let packet_data_length = buffer.len() - 6;
106 if packet_data_length == 0 {
109 return Err(InvalidPacketDataLength::EmptyDataField);
110 }
111
112 let Some(packet_length) = Self::primary_header_size().checked_add(packet_data_length)
114 else {
115 return Err(InvalidPacketDataLength::TooLarge { packet_data_length });
116 };
117 let buffer_length = buffer.len();
118 if packet_length > buffer_length {
119 return Err(InvalidPacketDataLength::LargerThanBuffer {
120 buffer_length,
121 packet_data_length,
122 });
123 }
124
125 let packet_bytes = &mut buffer[..packet_length];
129 #[allow(clippy::missing_panics_doc)]
130 let packet = Self::mut_from_bytes(packet_bytes).unwrap();
131
132 packet.primary_header.set_apid(apid);
134 packet.primary_header.initialize_packet_version();
135 packet.primary_header.set_packet_type(packet_type);
136 packet
137 .primary_header
138 .set_secondary_header_flag(secondary_header_flag);
139 packet.primary_header.set_sequence_flag(sequence_flag);
140 packet
141 .primary_header
142 .set_packet_sequence_count(sequence_count);
143 packet
144 .primary_header
145 .set_packet_data_length(packet_data_length)?;
146
147 Ok(packet)
148 }
149
150 fn validate(&self) -> Result<(), InvalidSpacePacket> {
158 self.primary_header.validate()?;
160
161 let packet_size = self.packet_data_length() + Self::primary_header_size();
165 let buffer_size = self.packet_length();
166 if packet_size > buffer_size {
167 return Err(InvalidSpacePacket::PartialPacket {
168 packet_size,
169 buffer_size,
170 });
171 }
172
173 Ok(())
174 }
175
176 #[must_use]
179 pub const fn primary_header_size() -> usize {
180 core::mem::size_of::<SpacePacketPrimaryHeader>()
181 }
182
183 pub fn set_packet_data_length(
191 &mut self,
192 packet_data_length: usize,
193 ) -> Result<(), InvalidPacketDataLength> {
194 if packet_data_length == 0 {
195 return Err(InvalidPacketDataLength::EmptyDataField);
196 }
197
198 let buffer_length = self.data_field.len();
199 if packet_data_length > buffer_length {
200 return Err(InvalidPacketDataLength::LargerThanBuffer {
201 packet_data_length,
202 buffer_length,
203 });
204 }
205
206 let Ok(stored_data_field_length) = u16::try_from(packet_data_length - 1) else {
207 return Err(InvalidPacketDataLength::TooLarge { packet_data_length });
208 };
209 self.primary_header
210 .data_length
211 .set(stored_data_field_length);
212 Ok(())
213 }
214
215 #[must_use]
218 pub const fn packet_length(&self) -> usize {
219 self.data_field.len() + core::mem::size_of::<SpacePacketPrimaryHeader>()
220 }
221
222 #[must_use]
224 pub const fn packet_data_field(&self) -> &[u8] {
225 &self.data_field
226 }
227
228 #[must_use]
230 pub const fn packet_data_field_mut(&mut self) -> &mut [u8] {
231 &mut self.data_field
232 }
233}
234
235impl core::hash::Hash for SpacePacket {
236 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
237 self.primary_header.hash(state);
238 self.data_field.hash(state);
239 }
240}
241
242impl core::fmt::Debug for SpacePacket {
243 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
244 f.debug_struct("SpacePacket")
245 .field("primary_header", &self.primary_header)
246 .field("data_field", &&self.data_field)
247 .finish()
248 }
249}
250
251impl core::ops::Deref for SpacePacket {
252 type Target = SpacePacketPrimaryHeader;
253
254 fn deref(&self) -> &Self::Target {
255 &self.primary_header
256 }
257}
258
259impl core::ops::DerefMut for SpacePacket {
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 &mut self.primary_header
262 }
263}
264
265#[repr(C)]
272#[derive(
273 Copy, Clone, Debug, ByteEq, FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned, ByteHash,
274)]
275pub struct SpacePacketPrimaryHeader {
276 packet_identification: network_endian::U16,
277 packet_sequence_control: network_endian::U16,
278 data_length: network_endian::U16,
279}
280
281impl SpacePacketPrimaryHeader {
282 fn validate(self) -> Result<(), InvalidSpacePacket> {
288 let version = self.packet_version();
291 if !version.is_supported() {
292 return Err(InvalidSpacePacket::UnsupportedPacketVersion { version });
293 }
294
295 if self.apid().is_idle() && self.secondary_header_flag() == SecondaryHeaderFlag::Present {
298 return Err(InvalidSpacePacket::IdlePacketWithSecondaryHeader);
299 }
300
301 Ok(())
302 }
303
304 #[must_use]
307 pub const fn primary_header_size() -> usize {
308 6
309 }
310
311 #[must_use]
314 pub const fn packet_version(&self) -> PacketVersionNumber {
315 PacketVersionNumber(self.packet_identification.to_bytes()[0] >> 5)
316 }
317
318 pub fn initialize_packet_version(&mut self) {
321 self.packet_identification.as_mut_bytes()[0] &= 0b0001_1111;
322 self.packet_identification.as_mut_bytes()[0] |=
323 PacketVersionNumber::version1_ccsds_packet().0 << 5;
324 }
325
326 #[must_use]
330 pub const fn packet_type(&self) -> PacketType {
331 if (self.packet_identification.to_bytes()[0] & 0x10) == 0x10 {
332 PacketType::Telecommand
333 } else {
334 PacketType::Telemetry
335 }
336 }
337
338 pub fn set_packet_type(&mut self, packet_type: PacketType) {
340 self.packet_identification.as_mut_bytes()[0] &= 0b1110_1111;
341 self.packet_identification.as_mut_bytes()[0] |= (packet_type as u8) << 4;
342 }
343
344 #[must_use]
348 pub const fn secondary_header_flag(&self) -> SecondaryHeaderFlag {
349 if (self.packet_identification.to_bytes()[0] & 0x08) == 0x08 {
350 SecondaryHeaderFlag::Present
351 } else {
352 SecondaryHeaderFlag::Absent
353 }
354 }
355
356 pub fn set_secondary_header_flag(&mut self, secondary_header_flag: SecondaryHeaderFlag) {
358 self.packet_identification.as_mut_bytes()[0] &= 0b1111_0111;
359 self.packet_identification.as_mut_bytes()[0] |= (secondary_header_flag as u8) << 3;
360 }
361
362 #[must_use]
367 pub const fn apid(&self) -> Apid {
368 Apid(self.packet_identification.get() & 0b0000_0111_1111_1111)
369 }
370
371 pub fn set_apid(&mut self, apid: Apid) {
373 let apid = apid.0.to_be_bytes();
374 self.packet_identification.as_mut_bytes()[0] &= 0b1111_1000;
375 self.packet_identification.as_mut_bytes()[0] |= apid[0] & 0b0000_0111;
376 self.packet_identification.as_mut_bytes()[1] = apid[1];
377 }
378
379 #[must_use]
382 pub const fn sequence_flag(&self) -> SequenceFlag {
383 match self.packet_sequence_control.to_bytes()[0] >> 6i32 {
384 0b00 => SequenceFlag::Continuation,
385 0b01 => SequenceFlag::First,
386 0b10 => SequenceFlag::Last,
387 0b11 => SequenceFlag::Unsegmented,
388 _ => unreachable!(), }
390 }
391
392 pub fn set_sequence_flag(&mut self, sequence_flag: SequenceFlag) {
394 self.packet_sequence_control.as_mut_bytes()[0] &= 0b0011_1111;
395 self.packet_sequence_control.as_mut_bytes()[0] |= (sequence_flag as u8) << 6;
396 }
397
398 #[must_use]
403 pub const fn packet_sequence_count(&self) -> PacketSequenceCount {
404 PacketSequenceCount(self.packet_sequence_control.get() & 0b0011_1111_1111_1111)
405 }
406
407 pub fn set_packet_sequence_count(&mut self, sequence_count: PacketSequenceCount) {
411 self.packet_sequence_control.as_mut_bytes()[0] &= 0b1100_0000;
412 self.packet_sequence_control.as_mut_bytes()[0] |=
413 sequence_count.0.to_be_bytes()[0] & 0b0011_1111;
414 self.packet_sequence_control.as_mut_bytes()[1] = sequence_count.0.to_be_bytes()[1];
415 }
416
417 #[must_use]
421 pub const fn packet_data_length(&self) -> usize {
422 self.data_length.get() as usize + 1
423 }
424
425 pub fn set_packet_data_length(
432 &mut self,
433 packet_data_length: usize,
434 ) -> Result<(), InvalidPacketDataLength> {
435 if packet_data_length == 0 {
436 return Err(InvalidPacketDataLength::EmptyDataField);
437 }
438
439 let Ok(stored_data_field_length) = u16::try_from(packet_data_length - 1) else {
440 return Err(InvalidPacketDataLength::TooLarge { packet_data_length });
441 };
442 self.data_length.set(stored_data_field_length);
443 Ok(())
444 }
445}
446
447#[non_exhaustive]
453#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)]
454pub enum InvalidSpacePacket {
455 #[error(
458 "buffer too small for space packet header (has {length} bytes, at least 6 are required)"
459 )]
460 SliceTooSmallForSpacePacketHeader { length: usize },
461 #[error("unsupported CCSDS Space Packet version: {version:?}")]
465 UnsupportedPacketVersion { version: PacketVersionNumber },
466 #[error("detected partial packet (buffer is {buffer_size} bytes, packet {packet_size})")]
468 PartialPacket {
469 packet_size: usize,
470 buffer_size: usize,
471 },
472 #[error("idle packet contains a secondary header, this is forbidden")]
475 IdlePacketWithSecondaryHeader,
476}
477
478#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)]
485pub enum InvalidPacketDataLength {
486 #[error("empty data field requested, this is forbidden")]
487 EmptyDataField,
488 #[error(
489 "requested packet data length ({packet_data_length} bytes) is too large for buffer ({buffer_length} bytes)"
490 )]
491 LargerThanBuffer {
492 packet_data_length: usize,
493 buffer_length: usize,
494 },
495 #[error(
496 "requested packet data length too large ({packet_data_length} bytes, may be at most `u16::MAX + 1` bytes)"
497 )]
498 TooLarge { packet_data_length: usize },
499}
500
501#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
504#[repr(transparent)]
505pub struct PacketVersionNumber(u8);
506
507impl PacketVersionNumber {
508 #[must_use]
512 pub const fn is_supported(&self) -> bool {
513 matches!(self.0, 0b0000_0000u8)
514 }
515
516 #[must_use]
518 pub const fn version1_ccsds_packet() -> Self {
519 Self(0)
520 }
521}
522
523#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
529#[cfg_attr(kani, derive(kani::Arbitrary))]
530#[repr(u8)]
531pub enum PacketType {
532 Telemetry = 0,
533 Telecommand = 1,
534}
535
536#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
542#[cfg_attr(kani, derive(kani::Arbitrary))]
543#[repr(u8)]
544pub enum SecondaryHeaderFlag {
545 Absent = 0,
546 Present = 1,
547}
548
549#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
556#[cfg_attr(kani, derive(kani::Arbitrary))]
557#[repr(transparent)]
558pub struct Apid(u16);
559
560impl Apid {
561 const MAX: u16 = 0b0000_0111_1111_1111u16;
562
563 #[must_use]
568 pub const fn new(id: u16) -> Self {
569 assert!(
570 id <= Self::MAX,
571 "APIDs may not exceed 2047 (due to maximum of 13 bits in representation)"
572 );
573 Self(id)
574 }
575
576 #[cfg(kani)]
579 fn any_apid() -> Self {
580 match kani::any() {
581 any @ 0..=Self::MAX => Self(any),
582 _ => Self(42),
583 }
584 }
585
586 #[must_use]
589 pub const fn is_idle(&self) -> bool {
590 self.0 == 0x7ff
591 }
592
593 #[must_use]
595 pub const fn as_u16(&self) -> u16 {
596 self.0
597 }
598}
599
600impl From<Apid> for u16 {
601 fn from(value: Apid) -> Self {
602 value.0
603 }
604}
605
606#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
609#[cfg_attr(kani, derive(kani::Arbitrary))]
610#[repr(u8)]
611pub enum SequenceFlag {
612 Continuation = 0b00,
613 First = 0b01,
614 Last = 0b10,
615 #[default]
616 Unsegmented = 0b11,
617}
618
619#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug, Default)]
626#[cfg_attr(kani, derive(kani::Arbitrary))]
627pub struct PacketSequenceCount(u16);
628
629impl PacketSequenceCount {
630 const MAX: u16 = 0b0011_1111_1111_1111u16;
631
632 #[must_use]
634 pub const fn new() -> Self {
635 Self(0)
636 }
637
638 #[cfg(kani)]
642 fn any_packet_sequence_count() -> Self {
643 match kani::any() {
644 any @ 0..=Self::MAX => Self(any),
645 _ => Self(42),
646 }
647 }
648
649 pub const fn increment(&mut self) {
653 self.0 += 1;
654 if self.0 > Self::MAX {
655 self.0 = 0;
656 }
657 }
658}
659
660#[cfg(kani)]
662mod kani_harness {
663 use super::*;
664 use ::kani;
665
666 #[kani::proof]
671 fn header_parsing() {
672 let mut bytes = [0u8; u16::MAX as usize];
673 bytes[0] = kani::any();
674 bytes[1] = kani::any();
675 bytes[2] = kani::any();
676 bytes[3] = kani::any();
677 bytes[4] = kani::any();
678 bytes[5] = kani::any();
679 bytes[6] = kani::any();
680
681 let packet = SpacePacket::parse(&bytes);
682 if let Ok(packet) = packet {
683 assert!(packet.packet_length() <= bytes.len());
684 assert_eq!(
685 packet.packet_data_field().len(),
686 packet.packet_data_length()
687 );
688 assert!(packet.apid().0 <= 0b0000_0111_1111_1111);
689 }
690 }
691
692 #[kani::proof]
703 fn packet_construction() {
704 let mut bytes = [kani::any(); 1024];
705 let maximum_packet_length = bytes.len();
706 let packet_type = kani::any();
707 let secondary_header_flag = kani::any();
708 let apid = Apid::any_apid();
709 let sequence_flag = kani::any();
710 let sequence_count = PacketSequenceCount::any_packet_sequence_count();
711 let packet_data_length: u16 = kani::any();
712 let packet_length = packet_data_length as usize + 6;
713
714 if packet_length <= maximum_packet_length {
715 let packet = SpacePacket::construct(
716 &mut bytes[..packet_length],
717 packet_type,
718 secondary_header_flag,
719 apid,
720 sequence_flag,
721 sequence_count,
722 );
723
724 let valid_request = packet_data_length != 0;
726 if valid_request {
727 assert!(packet.is_ok());
728 }
729
730 if !valid_request {
732 assert!(!packet.is_ok());
733 }
734
735 if let Ok(packet) = packet {
738 assert!(packet.packet_length() <= maximum_packet_length);
739 assert_eq!(
740 packet.packet_data_field().len(),
741 packet.packet_data_length()
742 );
743
744 assert_eq!(packet.packet_type(), packet_type);
745 assert_eq!(packet.secondary_header_flag(), secondary_header_flag);
746 assert_eq!(packet.apid(), apid);
747 assert_eq!(packet.sequence_flag(), sequence_flag);
748 assert_eq!(packet.packet_sequence_count(), sequence_count);
749 assert_eq!(packet.packet_data_length(), packet_data_length as usize);
750 }
751 }
752 }
753}
754
755#[test]
758fn deserialize_trivial_packet() {
759 let bytes = &[
760 0b0000_1000u8,
761 0b0000_0000u8,
762 0b1100_0000u8,
763 0b0000_0000u8,
764 0b0000_0000u8,
765 0b0000_0000u8,
766 0b0000_0000u8,
767 ];
768 let packet = SpacePacket::parse(bytes).unwrap();
769
770 assert_eq!(packet.packet_length(), 7);
771 assert_eq!(
772 packet.packet_version(),
773 PacketVersionNumber::version1_ccsds_packet()
774 );
775 assert_eq!(packet.packet_type(), PacketType::Telemetry);
776 assert_eq!(packet.secondary_header_flag(), SecondaryHeaderFlag::Present);
777 assert_eq!(packet.apid(), Apid::new(0));
778 assert_eq!(packet.sequence_flag(), SequenceFlag::Unsegmented);
779 assert_eq!(packet.packet_sequence_count(), PacketSequenceCount(0));
780 assert_eq!(packet.packet_data_length(), 1);
781 assert_eq!(packet.packet_data_field(), &bytes[6..]);
782}
783
784#[test]
787fn serialize_trivial_packet() {
788 let mut bytes = [0u8; 7];
789 let packet = SpacePacket::construct(
790 &mut bytes,
791 PacketType::Telemetry,
792 SecondaryHeaderFlag::Present,
793 Apid::new(0),
794 SequenceFlag::Unsegmented,
795 PacketSequenceCount(0),
796 )
797 .unwrap();
798
799 assert_eq!(packet.packet_length(), 7);
800 assert_eq!(
801 packet.packet_version(),
802 PacketVersionNumber::version1_ccsds_packet()
803 );
804 assert_eq!(packet.packet_type(), PacketType::Telemetry);
805 assert_eq!(packet.secondary_header_flag(), SecondaryHeaderFlag::Present);
806 assert_eq!(packet.apid(), Apid::new(0));
807 assert_eq!(packet.sequence_flag(), SequenceFlag::Unsegmented);
808 assert_eq!(packet.packet_sequence_count(), PacketSequenceCount(0));
809 assert_eq!(packet.packet_data_length(), 1);
810 assert_eq!(
811 packet.packet_data_field(),
812 &[
813 0b0000_1000u8,
814 0b0000_0000u8,
815 0b1100_0000u8,
816 0b0000_0000u8,
817 0b0000_0000u8,
818 0b0000_0000u8,
819 0b0000_0000u8,
820 ][6..]
821 );
822}
823
824#[test]
831fn roundtrip() {
832 use rand::{RngCore, SeedableRng};
833 let mut rng = rand::rngs::SmallRng::seed_from_u64(42);
835 let mut buffer = [0u8; 16000];
836 for _ in 0..10_000 {
837 let packet_type = match rng.next_u32() & 1 {
838 0 => PacketType::Telemetry,
839 1 => PacketType::Telecommand,
840 _ => unreachable!(),
841 };
842 let secondary_header_flag = match rng.next_u32() & 1 {
843 0 => SecondaryHeaderFlag::Absent,
844 1 => SecondaryHeaderFlag::Present,
845 _ => unreachable!(),
846 };
847 #[allow(clippy::cast_possible_truncation, reason = "Truncation intended")]
848 let apid = Apid::new((rng.next_u32() & u32::from(Apid::MAX)) as u16);
849 let sequence_flag = match rng.next_u32() & 3 {
850 0b00 => SequenceFlag::Continuation,
851 0b01 => SequenceFlag::First,
852 0b10 => SequenceFlag::Last,
853 0b11 => SequenceFlag::Unsegmented,
854 _ => unreachable!(),
855 };
856 #[allow(clippy::cast_possible_truncation, reason = "Truncation intended")]
857 let sequence_count =
858 PacketSequenceCount((rng.next_u32() & u32::from(PacketSequenceCount::MAX)) as u16);
859
860 #[allow(clippy::cast_possible_truncation, reason = "Truncation intended")]
861 let packet_data_length = (rng.next_u32() % (buffer.len() as u32 - 7)) as u16 + 1;
862 let packet_length = packet_data_length as usize + 6;
863
864 let space_packet = SpacePacket::construct(
865 &mut buffer[..packet_length],
866 packet_type,
867 secondary_header_flag,
868 apid,
869 sequence_flag,
870 sequence_count,
871 )
872 .unwrap();
873
874 assert_eq!(
875 packet_type,
876 space_packet.packet_type(),
877 "Serialized packet type ({:?}) does not match with final deserialized packet type ({:?}) for packet ({:?})",
878 packet_type,
879 space_packet.packet_type(),
880 space_packet
881 );
882
883 assert_eq!(
884 secondary_header_flag,
885 space_packet.secondary_header_flag(),
886 "Serialized secondary header flag ({:?}) does not match with final deserialized secondary header flag ({:?}) for packet ({:?})",
887 secondary_header_flag,
888 space_packet.secondary_header_flag(),
889 space_packet
890 );
891
892 assert_eq!(
893 apid,
894 space_packet.apid(),
895 "Serialized APID ({:?}) does not match with final deserialized APID ({:?}) for packet ({:?})",
896 apid,
897 space_packet.apid(),
898 space_packet
899 );
900
901 assert_eq!(
902 sequence_flag,
903 space_packet.sequence_flag(),
904 "Serialized sequence flag ({:?}) does not match with final deserialized sequence flag ({:?}) for packet ({:?})",
905 sequence_flag,
906 space_packet.sequence_flag(),
907 space_packet
908 );
909
910 assert_eq!(
911 sequence_count,
912 space_packet.packet_sequence_count(),
913 "Serialized sequence count ({:?}) does not match with final deserialized sequence count ({:?}) for packet ({:?})",
914 sequence_count,
915 space_packet.packet_sequence_count(),
916 space_packet
917 );
918
919 assert_eq!(
920 packet_data_length as usize,
921 space_packet.packet_data_length(),
922 "Serialized packet type ({:?}) does not match with final deserialized packet type ({:?}) for packet ({:?})",
923 packet_data_length,
924 space_packet.packet_data_length(),
925 space_packet
926 );
927 }
928}
929
930#[test]
933fn empty_packet_data_field() {
934 let mut bytes = [0u8; 6];
935 let result = SpacePacket::construct(
936 &mut bytes,
937 PacketType::Telemetry,
938 SecondaryHeaderFlag::Present,
939 Apid::new(0),
940 SequenceFlag::Unsegmented,
941 PacketSequenceCount(0),
942 );
943 assert_eq!(
944 result,
945 Err(InvalidPacketDataLength::LargerThanBuffer {
946 buffer_length: 6,
947 packet_data_length: 1
948 })
949 );
950}
951
952#[test]
955fn buffer_too_small_for_header_construction() {
956 let mut buffer = [0u8; 5];
957 let buffer_length = buffer.len();
958 let result = SpacePacket::construct(
959 &mut buffer,
960 PacketType::Telemetry,
961 SecondaryHeaderFlag::Present,
962 Apid::new(0),
963 SequenceFlag::Unsegmented,
964 PacketSequenceCount(0),
965 );
966 assert_eq!(
967 result,
968 Err(InvalidPacketDataLength::LargerThanBuffer {
969 buffer_length,
970 packet_data_length: 1
971 })
972 );
973}
974
975#[test]
978fn buffer_too_small_for_parsed_packet() {
979 use rand::{RngCore, SeedableRng};
980 let mut rng = rand::rngs::SmallRng::seed_from_u64(42);
982 let mut buffer = [0u8; 256];
983
984 for _ in 0..1000 {
985 let packet_data_length = (rng.next_u32() % 128) as u16 + 122;
988 let packet_length = packet_data_length as usize + 6;
989
990 let packet = SpacePacket::construct(
992 &mut buffer[..packet_length],
993 PacketType::Telemetry,
994 SecondaryHeaderFlag::Present,
995 Apid::new(0),
996 SequenceFlag::Unsegmented,
997 PacketSequenceCount(0),
998 )
999 .unwrap();
1000
1001 let bytes = &packet.as_bytes()[..127];
1005 let result = SpacePacket::parse(bytes);
1006 assert_eq!(
1007 result,
1008 Err(InvalidSpacePacket::PartialPacket {
1009 packet_size: packet_data_length as usize + SpacePacket::primary_header_size(),
1010 buffer_size: bytes.len()
1011 })
1012 );
1013 }
1014}