1#![no_std]
63#![cfg_attr(docsrs, feature(doc_cfg))]
64#![warn(missing_docs)]
65#[cfg(feature = "alloc")]
66extern crate alloc;
67#[cfg(any(feature = "std", test))]
68extern crate std;
69
70use arbitrary_int::{prelude::*, u11, u14};
71use core::{fmt::Debug, hash::Hash};
72use delegate::delegate;
73use zerocopy::{FromBytes, IntoBytes};
74
75#[cfg(feature = "serde")]
76use serde::{Deserialize, Serialize};
77
78use crate::crc::CRC_CCITT_FALSE;
79
80pub mod cfdp;
81pub mod crc;
82pub mod ecss;
83pub mod seq_count;
84pub mod time;
85pub mod uslp;
86pub mod util;
87
88mod private {
89 pub trait Sealed {}
90}
91
92pub const CCSDS_HEADER_LEN: usize = core::mem::size_of::<crate::zc::SpHeader>();
94
95pub const MAX_APID: u11 = u11::MAX;
97pub const MAX_SEQ_COUNT: u14 = u14::MAX;
99
100#[derive(Debug, Copy, Clone, PartialEq, Eq)]
102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104#[non_exhaustive]
105pub enum ChecksumType {
106 WithCrc16,
108 WithCrc16ButIgnored,
112}
113
114#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
117#[cfg_attr(feature = "defmt", derive(defmt::Format))]
118pub enum ByteConversionError {
119 #[error("target slice with size {found} is too small, expected size of at least {expected}")]
121 ToSliceTooSmall {
122 found: usize,
124 expected: usize,
126 },
127 #[error("source slice with size {found} too small, expected at least {expected} bytes")]
129 FromSliceTooSmall {
130 found: usize,
132 expected: usize,
134 },
135}
136
137#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
140#[cfg_attr(feature = "defmt", derive(defmt::Format))]
141pub enum ZeroCopyError {
142 #[error("zerocopy serialization error")]
144 ZeroCopyToError,
145 #[error("zerocopy deserialization error")]
147 ZeroCopyFromError,
148}
149
150#[derive(thiserror::Error, Debug)]
152#[cfg_attr(feature = "defmt", derive(defmt::Format))]
153#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
154#[error("invalid payload length: {0}")]
155pub struct InvalidPayloadLengthError(usize);
156
157#[derive(thiserror::Error, Debug)]
159#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
161pub enum CcsdsPacketCreationError {
162 #[error("byte conversion: {0}")]
164 ByteConversion(#[from] ByteConversionError),
165 #[error("invalid payload length: {0}")]
167 InvalidPayloadLength(#[from] InvalidPayloadLengthError),
168}
169
170#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173#[cfg_attr(feature = "defmt", derive(defmt::Format))]
174#[bitbybit::bitenum(u1, exhaustive = true)]
175#[repr(u8)]
176pub enum PacketType {
177 Tm = 0,
179 Tc = 1,
181}
182
183#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187#[bitbybit::bitenum(u2, exhaustive = true)]
188#[repr(u8)]
189pub enum SequenceFlags {
190 ContinuationSegment = 0b00,
192 FirstSegment = 0b01,
194 LastSegment = 0b10,
196 Unsegmented = 0b11,
198}
199
200#[inline]
202pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
203 PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
204}
205
206#[inline]
210pub const fn ccsds_packet_len_for_user_data_len(
211 data_len: usize,
212 checksum: Option<ChecksumType>,
213) -> Option<usize> {
214 if data_len == 0 {
216 return Some(7);
217 }
218 let checksum_len = match checksum {
219 Some(ChecksumType::WithCrc16) => 2,
220 Some(ChecksumType::WithCrc16ButIgnored) => 2,
221 None => 0,
222 };
223 let len = data_len
224 .saturating_add(CCSDS_HEADER_LEN)
225 .saturating_add(checksum_len);
226 if len - CCSDS_HEADER_LEN - 1 > u16::MAX as usize {
227 return None;
228 }
229 Some(len)
230}
231
232#[inline]
236pub fn ccsds_packet_len_for_user_data_len_with_checksum(data_len: usize) -> Option<usize> {
237 ccsds_packet_len_for_user_data_len(data_len, Some(ChecksumType::WithCrc16))
238}
239
240#[derive(Debug, Eq, Copy, Clone)]
243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
244#[cfg_attr(feature = "defmt", derive(defmt::Format))]
245pub struct PacketId {
246 pub packet_type: PacketType,
248 pub sec_header_flag: bool,
250 pub apid: u11,
252}
253
254impl PartialEq for PacketId {
255 #[inline]
256 fn eq(&self, other: &Self) -> bool {
257 self.raw().eq(&other.raw())
258 }
259}
260
261impl PartialOrd for PacketId {
262 #[inline]
263 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
264 Some(self.cmp(other))
265 }
266}
267
268impl Ord for PacketId {
269 #[inline]
270 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
271 self.raw().cmp(&other.raw())
272 }
273}
274
275impl Hash for PacketId {
276 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
277 let raw = self.raw();
278 raw.hash(state);
279 }
280}
281
282impl Default for PacketId {
283 #[inline]
284 fn default() -> Self {
285 PacketId {
286 packet_type: PacketType::Tm,
287 sec_header_flag: false,
288 apid: u11::new(0),
289 }
290 }
291}
292
293impl PacketId {
294 #[inline]
296 pub const fn new_for_tc(sec_header: bool, apid: u11) -> Self {
297 Self::new(PacketType::Tc, sec_header, apid)
298 }
299
300 #[inline]
302 pub const fn new_for_tm(sec_header: bool, apid: u11) -> Self {
303 Self::new(PacketType::Tm, sec_header, apid)
304 }
305
306 #[inline]
308 pub const fn new(packet_type: PacketType, sec_header_flag: bool, apid: u11) -> Self {
309 PacketId {
310 packet_type,
311 sec_header_flag,
312 apid,
313 }
314 }
315
316 #[inline]
320 pub fn set_apid(&mut self, apid: u11) {
321 self.apid = apid;
322 }
323
324 #[inline]
326 pub const fn apid(&self) -> u11 {
327 self.apid
328 }
329
330 #[inline]
332 pub const fn raw(&self) -> u16 {
333 ((self.packet_type as u16) << 12)
334 | ((self.sec_header_flag as u16) << 11)
335 | self.apid.value()
336 }
337}
338
339impl From<u16> for PacketId {
340 fn from(raw_id: u16) -> Self {
341 PacketId {
342 packet_type: PacketType::try_from(((raw_id >> 12) & 0b1) as u8).unwrap(),
343 sec_header_flag: ((raw_id >> 11) & 0b1) != 0,
344 apid: u11::new(raw_id & 0x7FF),
345 }
346 }
347}
348
349#[deprecated(since = "0.16.0", note = "use PacketSequenceControl instead")]
351pub type PacketSequenceCtrl = PacketSequenceControl;
352
353#[derive(Debug, PartialEq, Eq, Copy, Clone)]
356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358pub struct PacketSequenceControl {
359 pub seq_flags: SequenceFlags,
361 pub seq_count: u14,
363}
364
365impl PacketSequenceControl {
366 #[inline]
368 pub const fn new(seq_flags: SequenceFlags, seq_count: u14) -> PacketSequenceControl {
369 PacketSequenceControl {
370 seq_flags,
371 seq_count,
372 }
373 }
374
375 #[inline]
377 pub const fn raw(&self) -> u16 {
378 ((self.seq_flags as u16) << 14) | self.seq_count.value()
379 }
380}
381
382impl From<u16> for PacketSequenceControl {
383 fn from(raw_id: u16) -> Self {
384 PacketSequenceControl {
385 seq_flags: SequenceFlags::try_from(((raw_id >> 14) & 0b11) as u8).unwrap(),
386 seq_count: u14::new(raw_id & SSC_MASK),
387 }
388 }
389}
390
391macro_rules! sph_from_other {
392 ($Self: path, $other: path) => {
393 impl From<$other> for $Self {
394 fn from(other: $other) -> Self {
395 Self::new_from_composite_fields(
396 other.packet_id(),
397 other.psc(),
398 other.data_len(),
399 Some(other.ccsds_version()),
400 )
401 }
402 }
403 };
404}
405
406const SSC_MASK: u16 = 0x3FFF;
407const VERSION_MASK: u16 = 0xE000;
408
409pub trait CcsdsPacket {
411 fn ccsds_version(&self) -> u3;
413
414 fn packet_id(&self) -> PacketId;
418
419 fn psc(&self) -> PacketSequenceControl;
423
424 fn data_len(&self) -> u16;
430
431 #[inline]
433 fn packet_len(&self) -> usize {
434 usize::from(self.data_len()) + CCSDS_HEADER_LEN + 1
435 }
436
437 #[deprecated(since = "0.16.0", note = "use packet_len instead")]
439 #[inline]
440 fn total_len(&self) -> usize {
441 self.packet_len()
442 }
443
444 #[inline]
447 fn packet_id_raw(&self) -> u16 {
448 self.packet_id().raw()
449 }
450 #[inline]
452 fn psc_raw(&self) -> u16 {
453 self.psc().raw()
454 }
455
456 #[inline]
458 fn packet_type(&self) -> PacketType {
459 self.packet_id().packet_type
461 }
462
463 #[inline]
465 fn is_tm(&self) -> bool {
466 self.packet_type() == PacketType::Tm
467 }
468
469 #[inline]
471 fn is_tc(&self) -> bool {
472 self.packet_type() == PacketType::Tc
473 }
474
475 #[inline]
478 fn sec_header_flag(&self) -> bool {
479 self.packet_id().sec_header_flag
480 }
481
482 #[inline]
484 fn apid(&self) -> u11 {
485 self.packet_id().apid
486 }
487
488 #[inline]
490 fn seq_count(&self) -> u14 {
491 self.psc().seq_count
492 }
493
494 #[inline]
496 fn sequence_flags(&self) -> SequenceFlags {
497 self.psc().seq_flags
500 }
501}
502
503pub trait CcsdsPrimaryHeader {
505 fn new_from_composite_fields(
507 packet_id: PacketId,
508 psc: PacketSequenceControl,
509 data_len: u16,
510 version: Option<u3>,
511 ) -> Self;
512}
513
514#[derive(Debug, PartialEq, Eq, Copy, Clone)]
516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
517#[cfg_attr(feature = "defmt", derive(defmt::Format))]
518pub struct SpacePacketHeader {
519 pub version: u3,
522 pub packet_id: PacketId,
525 pub psc: PacketSequenceControl,
527 pub data_len: u16,
529}
530
531pub type SpHeader = SpacePacketHeader;
533
534impl Default for SpacePacketHeader {
535 #[inline]
538 fn default() -> Self {
539 SpHeader {
540 version: u3::new(0),
541 packet_id: PacketId::default(),
542 psc: PacketSequenceControl {
543 seq_flags: SequenceFlags::Unsegmented,
544 seq_count: u14::new(0),
545 },
546 data_len: 0,
547 }
548 }
549}
550
551impl SpacePacketHeader {
552 pub const LENGTH: usize = CCSDS_HEADER_LEN;
554
555 #[inline]
557 pub const fn new(packet_id: PacketId, psc: PacketSequenceControl, data_len: u16) -> Self {
558 Self {
559 version: u3::new(0),
560 packet_id,
561 psc,
562 data_len,
563 }
564 }
565
566 #[inline]
569 pub const fn new_from_apid(apid: u11) -> Self {
570 Self {
571 version: u3::new(0b000),
572 packet_id: PacketId::new(PacketType::Tm, false, apid),
573 psc: PacketSequenceControl {
574 seq_flags: SequenceFlags::Unsegmented,
575 seq_count: u14::new(0),
576 },
577 data_len: 0,
578 }
579 }
580
581 #[inline]
583 pub const fn new_from_fields(
584 ptype: PacketType,
585 sec_header: bool,
586 apid: u11,
587 seq_flags: SequenceFlags,
588 seq_count: u14,
589 data_len: u16,
590 ) -> Self {
591 Self {
592 psc: PacketSequenceControl::new(seq_flags, seq_count),
593 packet_id: PacketId::new(ptype, sec_header, apid),
594 data_len,
595 version: u3::new(0b000),
596 }
597 }
598
599 #[inline]
601 pub const fn new_for_tm(
602 apid: u11,
603 seq_flags: SequenceFlags,
604 seq_count: u14,
605 data_len: u16,
606 ) -> Self {
607 Self::new_from_fields(PacketType::Tm, false, apid, seq_flags, seq_count, data_len)
608 }
609
610 #[inline]
612 pub const fn new_for_tc(
613 apid: u11,
614 seq_flags: SequenceFlags,
615 seq_count: u14,
616 data_len: u16,
617 ) -> Self {
618 Self::new_from_fields(PacketType::Tc, false, apid, seq_flags, seq_count, data_len)
619 }
620
621 #[inline]
623 pub const fn new_for_unseg_tc(apid: u11, seq_count: u14, data_len: u16) -> Self {
624 Self::new_for_tc(apid, SequenceFlags::Unsegmented, seq_count, data_len)
625 }
626
627 #[inline]
629 pub const fn new_for_unseg_tm(apid: u11, seq_count: u14, data_len: u16) -> Self {
630 Self::new_for_tm(apid, SequenceFlags::Unsegmented, seq_count, data_len)
631 }
632
633 delegate! {
634 to self.packet_id {
635 #[inline]
637 pub fn set_apid(&mut self, apid: u11);
638 }
639 }
640
641 #[inline]
643 pub fn packet_len(&self) -> usize {
644 usize::from(self.data_len()) + Self::LENGTH + 1
645 }
646
647 #[inline]
649 pub fn set_seq_count(&mut self, seq_count: u14) {
650 self.psc.seq_count = seq_count;
651 }
652
653 #[inline]
655 pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
656 self.psc.seq_flags = seq_flags;
657 }
658
659 #[inline]
661 pub fn set_sec_header_flag(&mut self) {
662 self.packet_id.sec_header_flag = true;
663 }
664
665 #[inline]
667 pub fn clear_sec_header_flag(&mut self) {
668 self.packet_id.sec_header_flag = false;
669 }
670
671 #[inline]
673 pub fn set_packet_type(&mut self, packet_type: PacketType) {
674 self.packet_id.packet_type = packet_type;
675 }
676
677 #[inline]
679 pub fn apid(&self) -> u11 {
680 self.packet_id.apid
681 }
682
683 pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, &[u8]), ByteConversionError> {
687 if buf.len() < Self::LENGTH {
688 return Err(ByteConversionError::FromSliceTooSmall {
689 found: buf.len(),
690 expected: CCSDS_HEADER_LEN,
691 });
692 }
693 let zc_header = zc::SpHeader::read_from_bytes(&buf[0..Self::LENGTH]).unwrap();
695 Ok((Self::from(zc_header), &buf[Self::LENGTH..]))
696 }
697
698 pub fn write_to_be_bytes<'a>(
701 &self,
702 buf: &'a mut [u8],
703 ) -> Result<&'a mut [u8], ByteConversionError> {
704 if buf.len() < Self::LENGTH {
705 return Err(ByteConversionError::ToSliceTooSmall {
706 found: buf.len(),
707 expected: CCSDS_HEADER_LEN,
708 });
709 }
710 let zc_header: zc::SpHeader = zc::SpHeader::from(*self);
711 zc_header.write_to(&mut buf[0..Self::LENGTH]).unwrap();
713 Ok(&mut buf[Self::LENGTH..])
714 }
715
716 #[cfg(feature = "alloc")]
718 pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
719 let mut vec = alloc::vec![0; Self::LENGTH];
720 self.write_to_be_bytes(&mut vec[..]).unwrap();
722 vec
723 }
724}
725
726impl CcsdsPacket for SpacePacketHeader {
727 #[inline]
729 fn ccsds_version(&self) -> u3 {
730 self.version
731 }
732
733 #[inline]
735 fn packet_len(&self) -> usize {
736 self.packet_len()
737 }
738
739 #[inline]
741 fn packet_id(&self) -> PacketId {
742 self.packet_id
743 }
744
745 #[inline]
747 fn psc(&self) -> PacketSequenceControl {
748 self.psc
749 }
750
751 #[inline]
753 fn data_len(&self) -> u16 {
754 self.data_len
755 }
756}
757
758impl CcsdsPrimaryHeader for SpacePacketHeader {
759 #[inline]
760 fn new_from_composite_fields(
761 packet_id: PacketId,
762 psc: PacketSequenceControl,
763 data_len: u16,
764 version: Option<u3>,
765 ) -> Self {
766 let mut version_to_set = u3::new(0b000);
767 if let Some(version) = version {
768 version_to_set = version;
769 }
770 SpHeader {
771 version: version_to_set,
772 packet_id,
773 psc,
774 data_len,
775 }
776 }
777}
778
779sph_from_other!(SpHeader, crate::zc::SpHeader);
780
781pub mod zc {
783 use crate::{CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceControl, VERSION_MASK};
784 use arbitrary_int::traits::Integer;
785 use arbitrary_int::u3;
786 use zerocopy::byteorder::NetworkEndian;
787 use zerocopy::{FromBytes, Immutable, IntoBytes, Unaligned, U16};
788
789 #[derive(FromBytes, IntoBytes, Immutable, Unaligned, Debug)]
791 #[repr(C)]
792 pub struct SpHeader {
793 version_packet_id: U16<NetworkEndian>,
794 psc: U16<NetworkEndian>,
795 data_len: U16<NetworkEndian>,
796 }
797
798 impl SpHeader {
799 pub fn new(
801 packet_id: PacketId,
802 psc: PacketSequenceControl,
803 data_len: u16,
804 version: Option<u3>,
805 ) -> Self {
806 let mut version_packet_id = packet_id.raw();
807 if let Some(version) = version {
808 version_packet_id = (version.as_u16() << 13) | packet_id.raw()
809 }
810 SpHeader {
811 version_packet_id: U16::from(version_packet_id),
812 psc: U16::from(psc.raw()),
813 data_len: U16::from(data_len),
814 }
815 }
816 }
817
818 impl CcsdsPacket for SpHeader {
819 #[inline]
821 fn ccsds_version(&self) -> u3 {
822 u3::new(((self.version_packet_id.get() >> 13) as u8) & 0b111)
823 }
824
825 #[inline]
827 fn packet_id(&self) -> PacketId {
828 PacketId::from(self.packet_id_raw())
829 }
830
831 #[inline]
833 fn psc(&self) -> PacketSequenceControl {
834 PacketSequenceControl::from(self.psc_raw())
835 }
836
837 #[inline]
839 fn data_len(&self) -> u16 {
840 self.data_len.get()
841 }
842
843 #[inline]
844 fn packet_id_raw(&self) -> u16 {
845 self.version_packet_id.get() & (!VERSION_MASK)
846 }
847
848 #[inline]
849 fn psc_raw(&self) -> u16 {
850 self.psc.get()
851 }
852 }
853
854 impl CcsdsPrimaryHeader for SpHeader {
855 fn new_from_composite_fields(
856 packet_id: PacketId,
857 psc: PacketSequenceControl,
858 data_len: u16,
859 version: Option<u3>,
860 ) -> Self {
861 SpHeader::new(packet_id, psc, data_len, version)
862 }
863 }
864
865 sph_from_other!(SpHeader, crate::SpHeader);
866}
867
868#[derive(Debug)]
878pub struct CcsdsPacketCreatorWithReservedData<'buf> {
879 sp_header: SpHeader,
880 buf: &'buf mut [u8],
881 checksum: Option<ChecksumType>,
882}
883
884impl<'buf> CcsdsPacketCreatorWithReservedData<'buf> {
885 pub const HEADER_LEN: usize = CCSDS_HEADER_LEN;
887
888 #[inline]
891 pub fn packet_len_for_user_data_with_checksum(user_data_len: usize) -> Option<usize> {
892 ccsds_packet_len_for_user_data_len(user_data_len, Some(ChecksumType::WithCrc16))
893 }
894
895 pub fn new(
897 mut sp_header: SpacePacketHeader,
898 packet_type: PacketType,
899 packet_data_len: usize,
900 buf: &'buf mut [u8],
901 checksum: Option<ChecksumType>,
902 ) -> Result<Self, CcsdsPacketCreationError> {
903 let full_packet_len = match checksum {
904 Some(crc_type) => match crc_type {
905 ChecksumType::WithCrc16 | ChecksumType::WithCrc16ButIgnored => {
906 CCSDS_HEADER_LEN + packet_data_len + 2
907 }
908 },
909 None => {
910 if packet_data_len == 0 {
912 CCSDS_HEADER_LEN + 1
913 } else {
914 CCSDS_HEADER_LEN + packet_data_len
915 }
916 }
917 };
918 if full_packet_len > buf.len() {
919 return Err(ByteConversionError::ToSliceTooSmall {
920 found: buf.len(),
921 expected: full_packet_len,
922 }
923 .into());
924 }
925 if full_packet_len - CCSDS_HEADER_LEN - 1 > u16::MAX as usize {
926 return Err(InvalidPayloadLengthError(packet_data_len).into());
927 }
928 sp_header.data_len = (full_packet_len - CCSDS_HEADER_LEN - 1) as u16;
929 sp_header.packet_id.packet_type = packet_type;
930
931 Ok(Self {
932 sp_header,
933 buf: buf[0..full_packet_len].as_mut(),
934 checksum,
935 })
936 }
937
938 pub fn new_with_checksum(
940 sp_header: SpHeader,
941 packet_type: PacketType,
942 payload_len: usize,
943 buf: &'buf mut [u8],
944 ) -> Result<Self, CcsdsPacketCreationError> {
945 Self::new(
946 sp_header,
947 packet_type,
948 payload_len,
949 buf,
950 Some(ChecksumType::WithCrc16),
951 )
952 }
953
954 pub fn new_tm_with_checksum(
956 sp_header: SpHeader,
957 payload_len: usize,
958 buf: &'buf mut [u8],
959 ) -> Result<Self, CcsdsPacketCreationError> {
960 Self::new(
961 sp_header,
962 PacketType::Tm,
963 payload_len,
964 buf,
965 Some(ChecksumType::WithCrc16),
966 )
967 }
968
969 pub fn new_tc_with_checksum(
972 sp_header: SpHeader,
973 payload_len: usize,
974 buf: &'buf mut [u8],
975 ) -> Result<Self, CcsdsPacketCreationError> {
976 Self::new(
977 sp_header,
978 PacketType::Tc,
979 payload_len,
980 buf,
981 Some(ChecksumType::WithCrc16),
982 )
983 }
984}
985
986impl CcsdsPacketCreatorWithReservedData<'_> {
987 #[inline]
989 pub fn raw_buffer(&self) -> &[u8] {
990 self.buf
991 }
992
993 #[inline]
995 pub fn packet_len(&self) -> usize {
996 <Self as CcsdsPacket>::packet_len(self)
997 }
998
999 #[inline]
1001 pub fn sp_header(&self) -> &SpHeader {
1002 &self.sp_header
1003 }
1004
1005 #[inline]
1007 pub fn ccsds_packet_id_and_psc(&self) -> CcsdsPacketIdAndPsc {
1008 CcsdsPacketIdAndPsc::new_from_ccsds_packet(self)
1009 }
1010
1011 #[inline]
1013 pub fn packet_data_mut(&mut self) -> &mut [u8] {
1014 let len = self.packet_len();
1015 match self.checksum {
1016 Some(ChecksumType::WithCrc16) | Some(ChecksumType::WithCrc16ButIgnored) => {
1017 &mut self.buf[CCSDS_HEADER_LEN..len - 2]
1018 }
1019 None => &mut self.buf[CCSDS_HEADER_LEN..len],
1020 }
1021 }
1022
1023 #[inline]
1025 pub fn packet_data(&mut self) -> &[u8] {
1026 let len = self.packet_len();
1027 match self.checksum {
1028 Some(ChecksumType::WithCrc16) | Some(ChecksumType::WithCrc16ButIgnored) => {
1029 &self.buf[CCSDS_HEADER_LEN..len - 2]
1030 }
1031 None => &self.buf[CCSDS_HEADER_LEN..len],
1032 }
1033 }
1034
1035 pub fn finish(self) -> usize {
1040 self.sp_header
1041 .write_to_be_bytes(&mut self.buf[0..CCSDS_HEADER_LEN])
1042 .unwrap();
1043 let len = self.packet_len();
1044 match self.checksum {
1045 Some(ChecksumType::WithCrc16) => {
1046 let crc16 = CRC_CCITT_FALSE.checksum(&self.buf[0..len - 2]);
1047 self.buf[len - 2..len].copy_from_slice(&crc16.to_be_bytes());
1048 }
1049 None | Some(ChecksumType::WithCrc16ButIgnored) => (),
1050 };
1051 len
1052 }
1053}
1054
1055impl CcsdsPacket for CcsdsPacketCreatorWithReservedData<'_> {
1056 #[inline]
1058 fn ccsds_version(&self) -> arbitrary_int::u3 {
1059 self.sp_header.ccsds_version()
1060 }
1061
1062 #[inline]
1064 fn packet_id(&self) -> PacketId {
1065 self.sp_header.packet_id()
1066 }
1067
1068 #[inline]
1070 fn psc(&self) -> PacketSequenceControl {
1071 self.sp_header.psc()
1072 }
1073
1074 #[inline]
1076 fn data_len(&self) -> u16 {
1077 self.sp_header.data_len()
1078 }
1079}
1080
1081#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1087#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1088#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1089pub struct CcsdsPacketIdAndPsc {
1090 pub packet_id: PacketId,
1092 pub psc: PacketSequenceControl,
1094}
1095
1096impl Hash for CcsdsPacketIdAndPsc {
1097 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1098 self.packet_id.hash(state);
1099 self.psc.raw().hash(state);
1100 }
1101}
1102
1103impl CcsdsPacketIdAndPsc {
1104 #[inline]
1106 pub const fn new(packet_id: PacketId, psc: PacketSequenceControl) -> Self {
1107 Self { packet_id, psc }
1108 }
1109
1110 #[inline]
1112 pub fn new_from_ccsds_packet<P: CcsdsPacket>(packet: &P) -> Self {
1113 Self {
1114 packet_id: packet.packet_id(),
1115 psc: packet.psc(),
1116 }
1117 }
1118
1119 #[inline]
1121 pub const fn raw(&self) -> u32 {
1122 ((self.packet_id.raw() as u32) << 16) | self.psc.raw() as u32
1123 }
1124}
1125
1126impl From<SpacePacketHeader> for CcsdsPacketIdAndPsc {
1127 #[inline]
1128 fn from(header: SpacePacketHeader) -> Self {
1129 Self {
1130 packet_id: header.packet_id,
1131 psc: header.psc,
1132 }
1133 }
1134}
1135
1136impl From<&SpacePacketHeader> for CcsdsPacketIdAndPsc {
1137 #[inline]
1138 fn from(header: &SpacePacketHeader) -> Self {
1139 Self {
1140 packet_id: header.packet_id,
1141 psc: header.psc,
1142 }
1143 }
1144}
1145
1146#[derive(Debug)]
1147#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1149struct CcsdsPacketCreatorCommon {
1150 sp_header: SpHeader,
1151 checksum: Option<ChecksumType>,
1152}
1153
1154impl CcsdsPacketCreatorCommon {
1155 #[inline]
1156 pub fn len_written(&self, packet_data_len: usize) -> usize {
1157 ccsds_packet_len_for_user_data_len(packet_data_len, self.checksum).unwrap()
1158 }
1159
1160 #[inline]
1162 pub fn ccsds_packet_id_and_psc(&self) -> CcsdsPacketIdAndPsc {
1163 CcsdsPacketIdAndPsc::from(self.sp_header)
1164 }
1165
1166 pub fn calculate_data_len_field(
1167 packet_data_len: usize,
1168 checksum: Option<ChecksumType>,
1169 ) -> Result<usize, InvalidPayloadLengthError> {
1170 let sp_data_len = (packet_data_len
1171 + match checksum {
1172 Some(ChecksumType::WithCrc16) | Some(ChecksumType::WithCrc16ButIgnored) => 2,
1173 None => 0,
1174 }
1175 - 1) as u16;
1176 let full_packet_len = match checksum {
1177 Some(crc_type) => match crc_type {
1178 ChecksumType::WithCrc16 | ChecksumType::WithCrc16ButIgnored => {
1179 CCSDS_HEADER_LEN + packet_data_len + 2
1180 }
1181 },
1182 None => {
1183 if packet_data_len == 0 {
1185 CCSDS_HEADER_LEN + 1
1186 } else {
1187 CCSDS_HEADER_LEN + packet_data_len
1188 }
1189 }
1190 };
1191 if full_packet_len - CCSDS_HEADER_LEN - 1 > u16::MAX as usize {
1192 return Err(InvalidPayloadLengthError(packet_data_len));
1193 }
1194 Ok(sp_data_len as usize)
1195 }
1196
1197 pub fn new(
1198 mut sp_header: SpHeader,
1199 packet_type: PacketType,
1200 packet_data_len: usize,
1201 checksum: Option<ChecksumType>,
1202 ) -> Result<Self, InvalidPayloadLengthError> {
1203 sp_header.data_len = Self::calculate_data_len_field(packet_data_len, checksum)? as u16;
1204 sp_header.packet_id.packet_type = packet_type;
1205 Ok(Self {
1206 sp_header,
1207 checksum,
1208 })
1209 }
1210
1211 pub fn write_to_bytes(
1213 &self,
1214 buf: &mut [u8],
1215 len_written: usize,
1216 packet_data: &[u8],
1217 ) -> Result<usize, ByteConversionError> {
1218 if len_written > buf.len() {
1219 return Err(ByteConversionError::ToSliceTooSmall {
1220 found: buf.len(),
1221 expected: len_written,
1222 });
1223 }
1224 self.sp_header
1225 .write_to_be_bytes(&mut buf[0..CCSDS_HEADER_LEN])?;
1226 buf[CCSDS_HEADER_LEN..CCSDS_HEADER_LEN + packet_data.len()].copy_from_slice(packet_data);
1227 match self.checksum {
1228 Some(ChecksumType::WithCrc16) => {
1229 let crc16 = CRC_CCITT_FALSE.checksum(&buf[0..len_written - 2]);
1230 buf[len_written - 2..len_written].copy_from_slice(&crc16.to_be_bytes());
1231 }
1232 None | Some(ChecksumType::WithCrc16ButIgnored) => (),
1233 };
1234 Ok(len_written)
1235 }
1236
1237 #[cfg(feature = "alloc")]
1239 pub fn to_vec(&self, len_written: usize, packet_data: &[u8]) -> alloc::vec::Vec<u8> {
1240 let mut vec = alloc::vec![0u8; len_written];
1241 self.write_to_bytes(&mut vec, len_written, packet_data)
1243 .unwrap();
1244 vec
1245 }
1246}
1247
1248#[derive(Debug)]
1251#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1252#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1253pub struct CcsdsPacketCreator<'app_data> {
1254 common: CcsdsPacketCreatorCommon,
1255 packet_data: &'app_data [u8],
1256}
1257
1258impl<'app_data> CcsdsPacketCreator<'app_data> {
1259 pub const HEADER_LEN: usize = CCSDS_HEADER_LEN;
1261
1262 #[inline]
1265 pub fn packet_len_for_user_data_with_checksum(user_data_len: usize) -> Option<usize> {
1266 ccsds_packet_len_for_user_data_len(user_data_len, Some(ChecksumType::WithCrc16))
1267 }
1268
1269 pub fn new(
1271 sp_header: SpHeader,
1272 packet_type: PacketType,
1273 packet_data: &'app_data [u8],
1274 checksum: Option<ChecksumType>,
1275 ) -> Result<Self, CcsdsPacketCreationError> {
1276 let common =
1277 CcsdsPacketCreatorCommon::new(sp_header, packet_type, packet_data.len(), checksum)?;
1278 Ok(Self {
1279 packet_data,
1280 common,
1281 })
1282 }
1283
1284 pub fn new_with_checksum(
1286 sp_header: SpHeader,
1287 packet_type: PacketType,
1288 app_data: &'app_data [u8],
1289 ) -> Result<Self, CcsdsPacketCreationError> {
1290 Self::new(
1291 sp_header,
1292 packet_type,
1293 app_data,
1294 Some(ChecksumType::WithCrc16),
1295 )
1296 }
1297
1298 pub fn new_tm_with_checksum(
1300 sp_header: SpHeader,
1301 app_data: &'app_data [u8],
1302 ) -> Result<Self, CcsdsPacketCreationError> {
1303 Self::new(
1304 sp_header,
1305 PacketType::Tm,
1306 app_data,
1307 Some(ChecksumType::WithCrc16),
1308 )
1309 }
1310
1311 pub fn new_tc_with_checksum(
1313 sp_header: SpHeader,
1314 app_data: &'app_data [u8],
1315 ) -> Result<Self, CcsdsPacketCreationError> {
1316 Self::new(
1317 sp_header,
1318 PacketType::Tc,
1319 app_data,
1320 Some(ChecksumType::WithCrc16),
1321 )
1322 }
1323}
1324
1325impl CcsdsPacketCreator<'_> {
1326 #[inline]
1328 pub fn len_written(&self) -> usize {
1329 self.common.len_written(self.packet_data.len())
1330 }
1331
1332 pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
1334 self.common
1335 .write_to_bytes(buf, self.len_written(), self.packet_data)
1336 }
1337
1338 #[inline]
1340 pub fn sp_header(&self) -> &SpHeader {
1341 &self.common.sp_header
1342 }
1343
1344 #[inline]
1346 pub fn ccsds_packet_id_and_psc(&self) -> CcsdsPacketIdAndPsc {
1347 self.common.ccsds_packet_id_and_psc()
1348 }
1349
1350 #[cfg(feature = "alloc")]
1352 pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
1353 self.common.to_vec(self.len_written(), self.packet_data)
1354 }
1355}
1356
1357impl CcsdsPacket for CcsdsPacketCreator<'_> {
1358 #[inline]
1360 fn ccsds_version(&self) -> arbitrary_int::u3 {
1361 self.common.sp_header.ccsds_version()
1362 }
1363
1364 #[inline]
1366 fn packet_id(&self) -> PacketId {
1367 self.common.sp_header.packet_id()
1368 }
1369
1370 #[inline]
1372 fn psc(&self) -> PacketSequenceControl {
1373 self.common.sp_header.psc()
1374 }
1375
1376 #[inline]
1378 fn data_len(&self) -> u16 {
1379 self.common.sp_header.data_len()
1380 }
1381}
1382
1383#[cfg(feature = "alloc")]
1385#[derive(Debug)]
1386#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1387#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1388pub struct CcsdsPacketCreatorOwned {
1389 common: CcsdsPacketCreatorCommon,
1390 packet_data: alloc::vec::Vec<u8>,
1391}
1392
1393#[cfg(feature = "alloc")]
1394impl CcsdsPacketCreatorOwned {
1395 pub const HEADER_LEN: usize = CCSDS_HEADER_LEN;
1397
1398 #[inline]
1401 pub fn packet_len_for_user_data_with_checksum(user_data_len: usize) -> Option<usize> {
1402 ccsds_packet_len_for_user_data_len(user_data_len, Some(ChecksumType::WithCrc16))
1403 }
1404
1405 pub fn new(
1407 sp_header: SpHeader,
1408 packet_type: PacketType,
1409 packet_data: &[u8],
1410 checksum: Option<ChecksumType>,
1411 ) -> Result<Self, CcsdsPacketCreationError> {
1412 let common =
1413 CcsdsPacketCreatorCommon::new(sp_header, packet_type, packet_data.len(), checksum)?;
1414 Ok(Self {
1415 common,
1416 packet_data: packet_data.to_vec(),
1417 })
1418 }
1419
1420 pub fn new_with_checksum(
1422 sp_header: SpHeader,
1423 packet_type: PacketType,
1424 packet_data: &[u8],
1425 ) -> Result<Self, CcsdsPacketCreationError> {
1426 Self::new(
1427 sp_header,
1428 packet_type,
1429 packet_data,
1430 Some(ChecksumType::WithCrc16),
1431 )
1432 }
1433
1434 pub fn new_tm_with_checksum(
1436 sp_header: SpHeader,
1437 packet_data: &[u8],
1438 ) -> Result<Self, CcsdsPacketCreationError> {
1439 Self::new(
1440 sp_header,
1441 PacketType::Tm,
1442 packet_data,
1443 Some(ChecksumType::WithCrc16),
1444 )
1445 }
1446
1447 pub fn new_tc_with_checksum(
1449 sp_header: SpHeader,
1450 packet_data: &[u8],
1451 ) -> Result<Self, CcsdsPacketCreationError> {
1452 Self::new(
1453 sp_header,
1454 PacketType::Tc,
1455 packet_data,
1456 Some(ChecksumType::WithCrc16),
1457 )
1458 }
1459
1460 pub fn len_written(&self) -> usize {
1462 self.common.len_written(self.packet_data.len())
1463 }
1464
1465 pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
1467 self.common
1468 .write_to_bytes(buf, self.len_written(), &self.packet_data)
1469 }
1470
1471 #[inline]
1473 pub fn sp_header(&self) -> &SpHeader {
1474 &self.common.sp_header
1475 }
1476
1477 #[inline]
1479 pub fn ccsds_packet_id_and_psc(&self) -> CcsdsPacketIdAndPsc {
1480 self.common.ccsds_packet_id_and_psc()
1481 }
1482
1483 #[cfg(feature = "alloc")]
1485 pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
1486 self.common.to_vec(self.len_written(), &self.packet_data)
1487 }
1488}
1489
1490#[cfg(feature = "alloc")]
1491impl CcsdsPacket for CcsdsPacketCreatorOwned {
1492 #[inline]
1494 fn ccsds_version(&self) -> arbitrary_int::u3 {
1495 self.common.sp_header.ccsds_version()
1496 }
1497
1498 #[inline]
1500 fn packet_id(&self) -> PacketId {
1501 self.common.sp_header.packet_id()
1502 }
1503
1504 #[inline]
1506 fn psc(&self) -> PacketSequenceControl {
1507 self.common.sp_header.psc()
1508 }
1509
1510 #[inline]
1512 fn data_len(&self) -> u16 {
1513 self.common.sp_header.data_len()
1514 }
1515}
1516
1517#[derive(thiserror::Error, Debug, PartialEq, Eq)]
1519#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1520#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1521pub enum CcsdsPacketReadError {
1522 #[error("byte conversion: {0}")]
1524 ByteConversion(#[from] ByteConversionError),
1525 #[error("CRC error")]
1527 CrcError,
1528}
1529
1530#[derive(Debug)]
1532#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1533#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1534pub struct CcsdsPacketReader<'buf> {
1535 sp_header: SpHeader,
1536 packet_data: &'buf [u8],
1537}
1538
1539impl<'buf> CcsdsPacketReader<'buf> {
1540 pub const HEADER_LEN: usize = CCSDS_HEADER_LEN;
1542
1543 pub fn new_with_checksum(
1545 buf: &'buf [u8],
1546 ) -> Result<CcsdsPacketReader<'buf>, CcsdsPacketReadError> {
1547 Self::new(buf, Some(ChecksumType::WithCrc16))
1548 }
1549
1550 pub fn new(
1552 buf: &'buf [u8],
1553 checksum: Option<ChecksumType>,
1554 ) -> Result<Self, CcsdsPacketReadError> {
1555 let sp_header = SpHeader::from_be_bytes(&buf[0..CCSDS_HEADER_LEN])?.0;
1556 if sp_header.packet_len() > buf.len() {
1557 return Err(ByteConversionError::FromSliceTooSmall {
1558 found: buf.len(),
1559 expected: sp_header.packet_len(),
1560 }
1561 .into());
1562 }
1563 let user_data = match checksum {
1564 Some(ChecksumType::WithCrc16) => {
1565 if CRC_CCITT_FALSE.checksum(&buf[0..sp_header.packet_len()]) != 0 {
1566 return Err(CcsdsPacketReadError::CrcError);
1567 }
1568 &buf[CCSDS_HEADER_LEN..sp_header.packet_len() - 2]
1569 }
1570 Some(ChecksumType::WithCrc16ButIgnored) => {
1571 &buf[CCSDS_HEADER_LEN..sp_header.packet_len() - 2]
1572 }
1573 None => &buf[CCSDS_HEADER_LEN..sp_header.packet_len()],
1574 };
1575 Ok(Self {
1576 sp_header,
1577 packet_data: user_data,
1578 })
1579 }
1580}
1581
1582impl CcsdsPacketReader<'_> {
1583 #[inline]
1585 pub fn sp_header(&self) -> &SpHeader {
1586 &self.sp_header
1587 }
1588
1589 #[inline]
1591 pub fn ccsds_packet_id_and_psc(&self) -> CcsdsPacketIdAndPsc {
1592 CcsdsPacketIdAndPsc::new_from_ccsds_packet(self)
1593 }
1594
1595 #[inline]
1597 pub fn packet_type(&self) -> PacketType {
1598 self.sp_header.packet_id.packet_type
1599 }
1600
1601 #[inline]
1603 pub fn packet_data(&self) -> &[u8] {
1604 self.packet_data
1605 }
1606
1607 #[inline]
1609 pub fn apid(&self) -> u11 {
1610 self.sp_header.apid()
1611 }
1612
1613 #[inline]
1615 pub fn packet_id(&self) -> PacketId {
1616 self.sp_header.packet_id()
1617 }
1618
1619 #[inline]
1621 pub fn psc(&self) -> PacketSequenceControl {
1622 self.sp_header.psc()
1623 }
1624
1625 #[inline]
1627 pub fn packet_len(&self) -> usize {
1628 <Self as CcsdsPacket>::packet_len(self)
1629 }
1630
1631 #[inline]
1633 pub fn data_len(&self) -> u16 {
1634 self.sp_header.data_len()
1635 }
1636}
1637
1638impl CcsdsPacket for CcsdsPacketReader<'_> {
1639 #[inline]
1641 fn ccsds_version(&self) -> arbitrary_int::u3 {
1642 self.sp_header.ccsds_version()
1643 }
1644
1645 #[inline]
1647 fn packet_id(&self) -> PacketId {
1648 self.packet_id()
1649 }
1650
1651 #[inline]
1653 fn psc(&self) -> PacketSequenceControl {
1654 self.psc()
1655 }
1656
1657 #[inline]
1659 fn data_len(&self) -> u16 {
1660 self.data_len()
1661 }
1662}
1663
1664#[cfg(all(test, feature = "std"))]
1665pub(crate) mod tests {
1666 use std::collections::HashSet;
1667
1668 use super::*;
1669 use crate::crc::CRC_CCITT_FALSE;
1670 #[allow(unused_imports)]
1671 use crate::ByteConversionError;
1672 #[cfg(feature = "serde")]
1673 use crate::CcsdsPrimaryHeader;
1674 use crate::{SequenceFlags, SpHeader};
1675 use alloc::vec;
1676 use arbitrary_int::{u11, u14};
1677 #[cfg(feature = "serde")]
1678 use core::fmt::Debug;
1679 #[cfg(feature = "serde")]
1680 use postcard::{from_bytes, to_allocvec};
1681 #[cfg(feature = "serde")]
1682 use serde::{de::DeserializeOwned, Serialize};
1683 use zerocopy::FromBytes;
1684
1685 const CONST_SP: SpHeader = SpHeader::new(
1686 PacketId::new_for_tc(true, u11::new(0x36)),
1687 PacketSequenceControl::new(SequenceFlags::ContinuationSegment, u14::new(0x88)),
1688 0x90,
1689 );
1690
1691 const PACKET_ID_TM: PacketId = PacketId::new_for_tm(true, u11::new(0x22));
1692
1693 #[cfg(feature = "serde")]
1694 pub(crate) fn generic_serde_test<T: Serialize + DeserializeOwned + PartialEq + Debug>(
1695 value: T,
1696 ) {
1697 let output: alloc::vec::Vec<u8> = to_allocvec(&value).unwrap();
1698 let output_converted_back: T = from_bytes(&output).unwrap();
1699 assert_eq!(output_converted_back, value);
1700 }
1701
1702 #[test]
1703 #[allow(clippy::assertions_on_constants)]
1704 fn verify_const_packet_id() {
1705 assert_eq!(PACKET_ID_TM.apid().value(), 0x22);
1706 assert!(PACKET_ID_TM.sec_header_flag);
1707 assert_eq!(PACKET_ID_TM.packet_type, PacketType::Tm);
1708 let const_tc_id = PacketId::new_for_tc(true, u11::new(0x23));
1709 assert_eq!(const_tc_id.packet_type, PacketType::Tc);
1710 }
1711
1712 #[test]
1713 fn test_default_packet_id() {
1714 let id_default = PacketId::default();
1715 assert_eq!(id_default.packet_type, PacketType::Tm);
1716 assert_eq!(id_default.apid.value(), 0x000);
1717 assert!(!id_default.sec_header_flag);
1718 }
1719
1720 #[test]
1721 fn test_packet_id_ctors() {
1722 let packet_id = PacketId::new(PacketType::Tc, true, u11::new(0x1ff));
1723 assert_eq!(packet_id.apid().value(), 0x1ff);
1724 assert_eq!(packet_id.packet_type, PacketType::Tc);
1725 assert!(packet_id.sec_header_flag);
1726 let packet_id_tc = PacketId::new_for_tc(true, u11::new(0x1ff));
1727 assert_eq!(packet_id_tc, packet_id);
1728 let packet_id_tm = PacketId::new_for_tm(true, u11::new(0x2ff));
1729 assert!(packet_id_tm.sec_header_flag);
1730 assert_eq!(packet_id_tm.packet_type, PacketType::Tm);
1731 assert_eq!(packet_id_tm.apid, u11::new(0x2ff));
1732 }
1733
1734 #[test]
1735 fn verify_const_sp_header() {
1736 assert!(CONST_SP.sec_header_flag());
1737 assert_eq!(CONST_SP.apid().value(), 0x36);
1738 assert_eq!(
1739 CONST_SP.sequence_flags(),
1740 SequenceFlags::ContinuationSegment
1741 );
1742 assert_eq!(CONST_SP.seq_count().value(), 0x88);
1743 assert_eq!(CONST_SP.data_len, 0x90);
1744 }
1745
1746 #[test]
1747 fn test_seq_flag_helpers() {
1748 assert_eq!(
1749 SequenceFlags::try_from(0b00).expect("SEQ flag creation failed"),
1750 SequenceFlags::ContinuationSegment
1751 );
1752 assert_eq!(
1753 SequenceFlags::try_from(0b01).expect("SEQ flag creation failed"),
1754 SequenceFlags::FirstSegment
1755 );
1756 assert_eq!(
1757 SequenceFlags::try_from(0b10).expect("SEQ flag creation failed"),
1758 SequenceFlags::LastSegment
1759 );
1760 assert_eq!(
1761 SequenceFlags::try_from(0b11).expect("SEQ flag creation failed"),
1762 SequenceFlags::Unsegmented
1763 );
1764 assert!(SequenceFlags::try_from(0b100).is_err());
1765 }
1766
1767 #[test]
1768 fn test_packet_type_helper() {
1769 assert_eq!(PacketType::try_from(0b00).unwrap(), PacketType::Tm);
1770 assert_eq!(PacketType::try_from(0b01).unwrap(), PacketType::Tc);
1771 assert!(PacketType::try_from(0b10).is_err());
1772 }
1773
1774 #[test]
1775 fn test_packet_id() {
1776 let packet_id = PacketId::new(PacketType::Tm, false, u11::new(0x42));
1777 assert_eq!(packet_id.raw(), 0x0042);
1778 let packet_id_from_raw = PacketId::from(packet_id.raw());
1779 assert_eq!(
1780 packet_type_in_raw_packet_id(packet_id.raw()),
1781 PacketType::Tm
1782 );
1783 assert_eq!(packet_id_from_raw, packet_id);
1784 let packet_id_from_new = PacketId::new(PacketType::Tm, false, u11::new(0x42));
1785 assert_eq!(packet_id_from_new, packet_id);
1786 }
1787
1788 #[test]
1789 fn test_packet_seq_ctrl() {
1790 let psc = PacketSequenceControl::new(SequenceFlags::ContinuationSegment, u14::new(77));
1791 assert_eq!(psc.raw(), 77);
1792 let psc_from_raw = PacketSequenceControl::from(psc.raw());
1793 assert_eq!(psc_from_raw, psc);
1794 }
1795
1796 #[test]
1797 #[cfg(feature = "serde")]
1798 fn test_serde_sph() {
1799 let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x42), u14::new(12), 0);
1800 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1801 assert!(sp_header.is_tc());
1802 assert!(!sp_header.sec_header_flag());
1803 assert_eq!(sp_header.packet_type(), PacketType::Tc);
1804 assert_eq!(sp_header.seq_count().value(), 12);
1805 assert_eq!(sp_header.apid().value(), 0x42);
1806 assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
1807 assert_eq!(sp_header.data_len(), 0);
1808 let output = to_allocvec(&sp_header).unwrap();
1809 let sp_header: SpHeader = from_bytes(&output).unwrap();
1810 assert_eq!(sp_header.version.value(), 0b000);
1811 assert!(!sp_header.packet_id.sec_header_flag);
1812 assert_eq!(sp_header.packet_type(), PacketType::Tc);
1813 assert_eq!(sp_header.seq_count().value(), 12);
1814 assert_eq!(sp_header.apid().value(), 0x42);
1815 assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
1816 assert_eq!(sp_header.packet_id_raw(), 0x1042);
1817 assert_eq!(sp_header.psc_raw(), 0xC00C);
1818 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1819 assert_eq!(sp_header.data_len, 0);
1820
1821 let sp_header = SpHeader::new_for_unseg_tm(u11::new(0x7), u14::new(22), 36);
1822 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1823 assert!(sp_header.is_tm());
1824 assert!(!sp_header.sec_header_flag());
1825 assert_eq!(sp_header.packet_type(), PacketType::Tm);
1826 assert_eq!(sp_header.seq_count().value(), 22);
1827 assert_eq!(sp_header.apid().value(), 0x07);
1828 assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
1829 assert_eq!(sp_header.packet_id_raw(), 0x0007);
1830 assert_eq!(sp_header.psc_raw(), 0xC016);
1831 assert_eq!(sp_header.data_len(), 36);
1832 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1833
1834 let from_comp_fields = SpHeader::new_from_composite_fields(
1835 PacketId::new(PacketType::Tc, true, u11::new(0x42)),
1836 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0x7)),
1837 0,
1838 None,
1839 );
1840 assert_eq!(from_comp_fields.packet_type(), PacketType::Tc);
1841 assert_eq!(from_comp_fields.apid().value(), 0x42);
1842 assert!(from_comp_fields.sec_header_flag());
1843 assert_eq!(
1844 from_comp_fields.sequence_flags(),
1845 SequenceFlags::Unsegmented
1846 );
1847 assert_eq!(from_comp_fields.seq_count().value(), 0x7);
1848 assert_eq!(from_comp_fields.data_len(), 0);
1849 }
1850
1851 #[test]
1852 fn test_setters() {
1853 let mut sp_header =
1854 SpHeader::new_for_tc(u11::new(0x42), SequenceFlags::Unsegmented, u14::new(25), 0);
1855 sp_header.set_apid(u11::new(0x12));
1856 assert_eq!(sp_header.apid().as_u16(), 0x12);
1857 sp_header.set_sec_header_flag();
1858 assert!(sp_header.sec_header_flag());
1859 sp_header.clear_sec_header_flag();
1860 assert!(!sp_header.sec_header_flag());
1861 assert_eq!(sp_header.packet_type(), PacketType::Tc);
1862 sp_header.set_packet_type(PacketType::Tm);
1863 assert_eq!(sp_header.packet_type(), PacketType::Tm);
1864 sp_header.set_seq_count(u14::new(0x45));
1865 assert_eq!(sp_header.seq_count().as_u16(), 0x45);
1866 }
1867
1868 #[test]
1869 fn test_tc_ctor() {
1870 let sp_header =
1871 SpHeader::new_for_tc(u11::new(0x42), SequenceFlags::Unsegmented, u14::new(25), 0);
1872 verify_sp_fields(PacketType::Tc, &sp_header);
1873 }
1874
1875 #[test]
1876 fn test_tc_ctor_unseg() {
1877 let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x42), u14::new(25), 0);
1878 verify_sp_fields(PacketType::Tc, &sp_header);
1879 }
1880
1881 #[test]
1882 fn test_tc_ctor_unseg_const() {
1883 let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x42), u14::new(25), 0);
1884 verify_sp_fields(PacketType::Tc, &sp_header);
1885 }
1886
1887 #[test]
1888 fn test_tm_ctor() {
1889 let sp_header =
1890 SpHeader::new_for_tm(u11::new(0x42), SequenceFlags::Unsegmented, u14::new(25), 0);
1891 verify_sp_fields(PacketType::Tm, &sp_header);
1892 }
1893
1894 #[test]
1895 fn test_tm_ctor_const() {
1896 let sp_header =
1897 SpHeader::new_for_tm(u11::new(0x42), SequenceFlags::Unsegmented, u14::new(25), 0);
1898 verify_sp_fields(PacketType::Tm, &sp_header);
1899 }
1900
1901 #[test]
1902 fn test_tm_ctor_unseg() {
1903 let sp_header = SpHeader::new_for_unseg_tm(u11::new(0x42), u14::new(25), 0);
1904 verify_sp_fields(PacketType::Tm, &sp_header);
1905 }
1906
1907 fn verify_sp_fields(ptype: PacketType, sp_header: &SpHeader) {
1908 assert_eq!(sp_header.packet_type(), ptype);
1909 assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
1910 assert_eq!(sp_header.apid().value(), 0x42);
1911 assert_eq!(sp_header.seq_count(), u14::new(25));
1912 assert_eq!(sp_header.data_len(), 0);
1913 }
1914
1915 #[test]
1916 fn test_zc_sph() {
1917 use zerocopy::IntoBytes;
1918
1919 let sp_header = SpHeader::new_for_unseg_tc(u11::MAX, u14::MAX, 0);
1920 assert_eq!(sp_header.packet_type(), PacketType::Tc);
1921 assert_eq!(sp_header.apid().value(), 0x7FF);
1922 assert_eq!(sp_header.data_len(), 0);
1923 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1924 assert!(sp_header.is_tc());
1925 let sp_header_zc = zc::SpHeader::from(sp_header);
1926 let slice = sp_header_zc.as_bytes();
1927 assert_eq!(slice.len(), 6);
1928 assert_eq!(slice[0], 0x17);
1929 assert_eq!(slice[1], 0xFF);
1930 assert_eq!(slice[2], 0xFF);
1931 assert_eq!(slice[3], 0xFF);
1932 assert_eq!(slice[4], 0x00);
1933 assert_eq!(slice[5], 0x00);
1934
1935 let mut slice = [0; 6];
1936 sp_header_zc.write_to(slice.as_mut_slice()).unwrap();
1937 assert_eq!(slice.len(), 6);
1938 assert_eq!(slice[0], 0x17);
1939 assert_eq!(slice[1], 0xFF);
1940 assert_eq!(slice[2], 0xFF);
1941 assert_eq!(slice[3], 0xFF);
1942 assert_eq!(slice[4], 0x00);
1943 assert_eq!(slice[5], 0x00);
1944
1945 let mut test_vec = vec![0_u8; 6];
1946 let slice = test_vec.as_mut_slice();
1947 sp_header_zc.write_to(slice).unwrap();
1948 let slice = test_vec.as_slice();
1949 assert_eq!(slice.len(), 6);
1950 assert_eq!(slice[0], 0x17);
1951 assert_eq!(slice[1], 0xFF);
1952 assert_eq!(slice[2], 0xFF);
1953 assert_eq!(slice[3], 0xFF);
1954 assert_eq!(slice[4], 0x00);
1955 assert_eq!(slice[5], 0x00);
1956
1957 let sp_header = zc::SpHeader::read_from_bytes(slice);
1958 assert!(sp_header.is_ok());
1959 let sp_header = sp_header.unwrap();
1960 assert_eq!(sp_header.ccsds_version().value(), 0b000);
1961 assert_eq!(sp_header.packet_id_raw(), 0x17FF);
1962 assert_eq!(sp_header.apid().value(), 0x7FF);
1963 assert_eq!(sp_header.packet_type(), PacketType::Tc);
1964 assert_eq!(sp_header.data_len(), 0);
1965 }
1966
1967 #[test]
1968 fn packet_id_ord_partial_ord() {
1969 let packet_id_small = PacketId::from(1_u16);
1970 let packet_id_larger = PacketId::from(2_u16);
1971 assert!(packet_id_small < packet_id_larger);
1972 assert!(packet_id_larger > packet_id_small);
1973 assert_eq!(
1974 packet_id_small.cmp(&packet_id_larger),
1975 core::cmp::Ordering::Less
1976 );
1977 }
1978
1979 #[test]
1980 fn packet_id_hashable() {
1981 let mut id_set = HashSet::new();
1982 id_set.insert(PacketId::from(1_u16));
1983 }
1984
1985 #[test]
1986 fn sp_header_from_apid() {
1987 let sp_header = SpHeader::new_from_apid(u11::new(0x03));
1988 assert_eq!(sp_header.apid().value(), 0x03);
1989 assert_eq!(sp_header.data_len(), 0);
1990 }
1991
1992 #[cfg(feature = "defmt")]
1993 fn is_defmt_format<T: defmt::Format>(_t: T) {}
1994
1995 #[test]
1996 #[cfg(feature = "defmt")]
1997 fn test_defmt_format() {
1998 is_defmt_format(ByteConversionError::ToSliceTooSmall {
1999 found: 1,
2000 expected: 2,
2001 });
2002 }
2003
2004 #[test]
2005 fn test_sp_header_as_vec() {
2006 let sp_header = SpHeader::new_for_unseg_tc(u11::new(0x42), u14::new(25), 1);
2007 let sp_header_as_vec = sp_header.to_vec();
2008 let sp_header_read_back = SpHeader::from_be_bytes(&sp_header_as_vec)
2009 .expect("Error reading back SP header")
2010 .0;
2011 assert_eq!(sp_header, sp_header_read_back);
2012 }
2013
2014 #[test]
2015 fn test_ccsds_size_function() {
2016 assert_eq!(ccsds_packet_len_for_user_data_len(1, None).unwrap(), 7);
2017 assert_eq!(ccsds_packet_len_for_user_data_len(0, None).unwrap(), 7);
2019 assert_eq!(
2020 ccsds_packet_len_for_user_data_len(1, Some(ChecksumType::WithCrc16)).unwrap(),
2021 9
2022 );
2023 assert_eq!(
2024 ccsds_packet_len_for_user_data_len_with_checksum(1).unwrap(),
2025 9
2026 );
2027 }
2028
2029 #[test]
2030 fn test_ccsds_size_function_invalid_size_no_checksum() {
2031 assert!(ccsds_packet_len_for_user_data_len(u16::MAX as usize + 1, None).is_some());
2033 assert!(ccsds_packet_len_for_user_data_len(u16::MAX as usize + 2, None).is_none());
2035 }
2036
2037 #[test]
2038 fn test_ccsds_size_function_invalid_size_with_checksum() {
2039 assert!(ccsds_packet_len_for_user_data_len(
2041 u16::MAX as usize - 1,
2042 Some(ChecksumType::WithCrc16)
2043 )
2044 .is_some());
2045 assert!(ccsds_packet_len_for_user_data_len(
2047 u16::MAX as usize,
2048 Some(ChecksumType::WithCrc16)
2049 )
2050 .is_none());
2051 }
2052
2053 #[test]
2054 fn test_ccsds_creator_api() {
2055 let mut buf: [u8; 32] = [0; 32];
2056 let apid = u11::new(0x1);
2057 let packet_type = PacketType::Tc;
2058 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new(
2059 SpacePacketHeader::new_from_apid(apid),
2060 packet_type,
2061 4,
2062 &mut buf,
2063 Some(ChecksumType::WithCrc16),
2064 )
2065 .unwrap();
2066 assert_eq!(packet_creator.packet_len(), 12);
2067 assert_eq!(packet_creator.raw_buffer().len(), 12);
2068 assert_eq!(packet_creator.data_len(), 5);
2069 assert_eq!(packet_creator.apid().value(), 0x1);
2070 assert_eq!(
2071 packet_creator.packet_id(),
2072 PacketId::new(packet_type, false, apid)
2073 );
2074 assert_eq!(
2075 packet_creator.psc(),
2076 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0))
2077 );
2078 assert_eq!(packet_creator.packet_data_mut(), &mut [0, 0, 0, 0]);
2079 assert_eq!(packet_creator.packet_data(), &[0, 0, 0, 0]);
2080 assert_eq!(packet_creator.ccsds_version(), u3::new(0b000));
2081 }
2082
2083 #[test]
2084 fn test_ccsds_creator_api_no_checksum() {
2085 let mut buf: [u8; 32] = [0; 32];
2086 let apid = u11::new(0x1);
2087 let packet_type = PacketType::Tm;
2088 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new(
2089 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2090 PacketType::Tm,
2091 4,
2092 &mut buf,
2093 None,
2094 )
2095 .unwrap();
2096 assert_eq!(packet_creator.packet_len(), 10);
2097 assert_eq!(packet_creator.data_len(), 3);
2098 assert_eq!(packet_creator.apid().value(), 0x1);
2099 assert_eq!(
2100 packet_creator.packet_id(),
2101 PacketId::new(packet_type, false, apid)
2102 );
2103 assert_eq!(
2104 packet_creator.psc(),
2105 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0))
2106 );
2107 assert_eq!(packet_creator.packet_data_mut(), &mut [0, 0, 0, 0]);
2108 assert_eq!(packet_creator.packet_data(), &[0, 0, 0, 0]);
2109 }
2110
2111 #[test]
2112 fn test_ccsds_creator_creation_with_reserved_data_alt_ctor() {
2113 let mut buf: [u8; 32] = [0; 32];
2114 let data = [1, 2, 3, 4];
2115 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new_with_checksum(
2116 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2117 PacketType::Tc,
2118 4,
2119 &mut buf,
2120 )
2121 .unwrap();
2122 packet_creator.packet_data_mut().copy_from_slice(&data);
2123 let written_len = packet_creator.finish();
2124 assert_eq!(
2125 CcsdsPacketCreatorWithReservedData::packet_len_for_user_data_with_checksum(4).unwrap(),
2126 written_len
2127 );
2128 assert_eq!(CRC_CCITT_FALSE.checksum(&buf[0..written_len]), 0);
2129 let sp_header = SpacePacketHeader::from_be_bytes(
2130 &buf[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2131 )
2132 .unwrap()
2133 .0;
2134 assert_eq!(sp_header.apid().value(), 0x1);
2135 assert_eq!(buf[6], 1);
2136 assert_eq!(buf[7], 2);
2137 assert_eq!(buf[8], 3);
2138 assert_eq!(buf[9], 4);
2139 assert_eq!(buf[12], 0);
2140 }
2141
2142 #[test]
2143 fn test_ccsds_creator_creation_with_reserved_data() {
2144 let mut buf: [u8; 32] = [0; 32];
2145 let data = [1, 2, 3, 4];
2146 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new(
2147 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2148 PacketType::Tc,
2149 4,
2150 &mut buf,
2151 Some(ChecksumType::WithCrc16),
2152 )
2153 .unwrap();
2154 packet_creator.packet_data_mut().copy_from_slice(&data);
2155 let written_len = packet_creator.finish();
2156 assert_eq!(
2157 CcsdsPacketCreatorWithReservedData::packet_len_for_user_data_with_checksum(4).unwrap(),
2158 written_len
2159 );
2160 assert_eq!(CRC_CCITT_FALSE.checksum(&buf[0..written_len]), 0);
2161 let sp_header = SpacePacketHeader::from_be_bytes(
2162 &buf[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2163 )
2164 .unwrap()
2165 .0;
2166 assert_eq!(sp_header.apid().value(), 0x1);
2167 assert_eq!(sp_header.packet_type(), PacketType::Tc);
2168 assert_eq!(buf[6], 1);
2169 assert_eq!(buf[7], 2);
2170 assert_eq!(buf[8], 3);
2171 assert_eq!(buf[9], 4);
2172 assert_eq!(buf[12], 0);
2173 }
2174
2175 #[test]
2176 fn test_ccsds_creator_creation_empty_user_data_no_checksum() {
2177 let mut buf: [u8; 32] = [0; 32];
2178 let packet_creator = CcsdsPacketCreatorWithReservedData::new(
2179 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2180 PacketType::Tc,
2181 0,
2182 &mut buf,
2183 None,
2184 )
2185 .unwrap();
2186 assert_eq!(packet_creator.packet_len(), 7);
2188 packet_creator.finish();
2189 let reader = CcsdsPacketReader::new(&buf[0..7], None).unwrap();
2190 assert_eq!(reader.packet_data(), &[0]);
2192 assert_eq!(reader.packet_len(), 7);
2193 }
2194
2195 #[test]
2196 fn test_ccsds_creator_creation_ignored_checksum() {
2197 let mut buf: [u8; 32] = [0; 32];
2198 let data = [1, 2, 3, 4, 5];
2199 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new(
2200 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2201 PacketType::Tc,
2202 data.len(),
2203 &mut buf,
2204 Some(ChecksumType::WithCrc16ButIgnored),
2205 )
2206 .unwrap();
2207 packet_creator.packet_data_mut().copy_from_slice(&data);
2208 assert_eq!(packet_creator.packet_len(), 13);
2210 packet_creator.finish();
2211 let reader =
2212 CcsdsPacketReader::new(&buf[0..13], Some(ChecksumType::WithCrc16ButIgnored)).unwrap();
2213 assert_eq!(reader.packet_data(), &data);
2215 assert_eq!(reader.packet_len(), 13);
2216 }
2217
2218 #[test]
2219 fn test_ccsds_creator_creation_buf_too_small() {
2220 let mut buf: [u8; 8] = [0; 8];
2221 let packet_creator = CcsdsPacketCreatorWithReservedData::new(
2222 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2223 PacketType::Tc,
2224 4,
2225 &mut buf,
2226 None,
2227 );
2228 assert!(packet_creator.is_err());
2229 matches!(
2230 packet_creator.unwrap_err(),
2231 CcsdsPacketCreationError::ByteConversion(ByteConversionError::ToSliceTooSmall {
2232 found: 8,
2233 expected: 10
2234 })
2235 );
2236 }
2237
2238 #[test]
2239 fn test_ccsds_creator_creation_with_reserved_data_tc_api() {
2240 let mut buf: [u8; 32] = [0; 32];
2241 let data = [1, 2, 3, 4];
2242 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new_tc_with_checksum(
2243 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2244 4,
2245 &mut buf,
2246 )
2247 .unwrap();
2248 packet_creator.packet_data_mut().copy_from_slice(&data);
2249 let written_len = packet_creator.finish();
2250 assert_eq!(
2251 CcsdsPacketCreatorWithReservedData::packet_len_for_user_data_with_checksum(4).unwrap(),
2252 written_len
2253 );
2254 assert_eq!(CRC_CCITT_FALSE.checksum(&buf[0..written_len]), 0);
2255 let sp_header = SpacePacketHeader::from_be_bytes(
2256 &buf[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2257 )
2258 .unwrap()
2259 .0;
2260 assert_eq!(sp_header.apid().value(), 0x1);
2261 assert_eq!(sp_header.packet_type(), PacketType::Tc);
2262 assert_eq!(buf[6], 1);
2263 assert_eq!(buf[7], 2);
2264 assert_eq!(buf[8], 3);
2265 assert_eq!(buf[9], 4);
2266 assert_eq!(buf[12], 0);
2267 }
2268
2269 #[test]
2270 fn test_ccsds_creator_creation_with_reserved_data_tm_api() {
2271 let mut buf: [u8; 32] = [0; 32];
2272 let data = [1, 2, 3, 4];
2273 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new_tm_with_checksum(
2274 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2275 4,
2276 &mut buf,
2277 )
2278 .unwrap();
2279 packet_creator.packet_data_mut().copy_from_slice(&data);
2280 let written_len = packet_creator.finish();
2281 assert_eq!(
2282 CcsdsPacketCreatorWithReservedData::packet_len_for_user_data_with_checksum(4).unwrap(),
2283 written_len
2284 );
2285 assert_eq!(CRC_CCITT_FALSE.checksum(&buf[0..written_len]), 0);
2286 let sp_header = SpacePacketHeader::from_be_bytes(
2287 &buf[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2288 )
2289 .unwrap()
2290 .0;
2291 assert_eq!(sp_header.apid().value(), 0x1);
2292 assert_eq!(sp_header.packet_type(), PacketType::Tm);
2293 assert_eq!(buf[6], 1);
2294 assert_eq!(buf[7], 2);
2295 assert_eq!(buf[8], 3);
2296 assert_eq!(buf[9], 4);
2297 assert_eq!(buf[12], 0);
2298 }
2299
2300 #[test]
2301 fn test_ccsds_creator_creation_with_reserved_data_no_checksum() {
2302 let mut buf: [u8; 32] = [0; 32];
2303 let data = [1, 2, 3, 4];
2304 let mut packet_creator = CcsdsPacketCreatorWithReservedData::new(
2305 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2306 PacketType::Tc,
2307 4,
2308 &mut buf,
2309 None,
2310 )
2311 .unwrap();
2312 let sph = *packet_creator.sp_header();
2313 packet_creator.packet_data_mut().copy_from_slice(&data);
2314 assert_eq!(
2315 packet_creator.ccsds_packet_id_and_psc(),
2316 CcsdsPacketIdAndPsc::from(sph)
2317 );
2318 let written_len = packet_creator.finish();
2319 assert_eq!(written_len, 10);
2320 let sp_header = SpacePacketHeader::from_be_bytes(
2321 &buf[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2322 )
2323 .unwrap()
2324 .0;
2325 assert_eq!(sp_header.apid().value(), 0x1);
2326 assert_eq!(buf[6], 1);
2327 assert_eq!(buf[7], 2);
2328 assert_eq!(buf[8], 3);
2329 assert_eq!(buf[9], 4);
2330 assert_eq!(buf[10], 0);
2331 assert_eq!(buf[11], 0);
2332 }
2333
2334 fn generic_ccsds_creator_test(alt_api: bool, owned: bool) {
2335 let data = [1, 2, 3, 4];
2336 let mut sp_header = SpacePacketHeader::new_from_apid(u11::new(0x1));
2337 sp_header.set_packet_type(PacketType::Tc);
2338
2339 let packet_raw = match (alt_api, owned) {
2340 (true, true) => CcsdsPacketCreatorOwned::new(
2341 sp_header,
2342 PacketType::Tc,
2343 &data,
2344 Some(ChecksumType::WithCrc16),
2345 )
2346 .unwrap()
2347 .to_vec(),
2348 (true, false) => CcsdsPacketCreator::new(
2349 sp_header,
2350 PacketType::Tc,
2351 &data,
2352 Some(ChecksumType::WithCrc16),
2353 )
2354 .unwrap()
2355 .to_vec(),
2356 (false, true) => {
2357 CcsdsPacketCreatorOwned::new_with_checksum(sp_header, PacketType::Tc, &data)
2358 .unwrap()
2359 .to_vec()
2360 }
2361 (false, false) => {
2362 CcsdsPacketCreator::new_with_checksum(sp_header, PacketType::Tc, &data)
2363 .unwrap()
2364 .to_vec()
2365 }
2366 };
2367 assert_eq!(CRC_CCITT_FALSE.checksum(&packet_raw), 0);
2368 let sp_header_from_raw = SpacePacketHeader::from_be_bytes(
2369 &packet_raw[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2370 )
2371 .unwrap()
2372 .0;
2373 assert_eq!(sp_header_from_raw.packet_id(), sp_header.packet_id());
2374 assert_eq!(sp_header_from_raw.psc(), sp_header.psc());
2375 assert_eq!(sp_header.apid().value(), 0x1);
2376 assert_eq!(sp_header.packet_type(), PacketType::Tc);
2377 assert_eq!(packet_raw[6], 1);
2378 assert_eq!(packet_raw[7], 2);
2379 assert_eq!(packet_raw[8], 3);
2380 assert_eq!(packet_raw[9], 4);
2381 }
2382
2383 #[test]
2384 fn test_ccsds_creator_creation_0() {
2385 generic_ccsds_creator_test(false, false);
2386 }
2387
2388 #[test]
2389 fn test_ccsds_creator_creation_1() {
2390 generic_ccsds_creator_test(false, true);
2391 }
2392
2393 #[test]
2394 fn test_ccsds_creator_creation_2() {
2395 generic_ccsds_creator_test(true, false);
2396 }
2397
2398 #[test]
2399 fn test_ccsds_creator_creation_3() {
2400 generic_ccsds_creator_test(true, true);
2401 }
2402
2403 #[test]
2404 fn test_ccsds_creator_ignored_checksum() {
2405 let data = [1, 2, 3, 4];
2406 let mut sp_header = SpacePacketHeader::new_from_apid(u11::new(0x1));
2407 sp_header.set_packet_type(PacketType::Tc);
2408 let packet_raw = CcsdsPacketCreatorOwned::new(
2409 sp_header,
2410 PacketType::Tc,
2411 &data,
2412 Some(ChecksumType::WithCrc16ButIgnored),
2413 )
2414 .unwrap()
2415 .to_vec();
2416 let reader =
2417 CcsdsPacketReader::new(&packet_raw, Some(ChecksumType::WithCrc16ButIgnored)).unwrap();
2418 assert_eq!(reader.packet_data(), data);
2419 }
2420
2421 fn generic_test_creator(packet_raw: &[u8], sp_header: &SpHeader, packet_type: PacketType) {
2422 assert_eq!(CRC_CCITT_FALSE.checksum(packet_raw), 0);
2423 let sp_header_from_raw = SpacePacketHeader::from_be_bytes(
2424 &packet_raw[0..CcsdsPacketCreatorWithReservedData::HEADER_LEN],
2425 )
2426 .unwrap()
2427 .0;
2428 assert_eq!(sp_header_from_raw, *sp_header);
2429 assert_eq!(sp_header.packet_type(), packet_type);
2430 assert_eq!(packet_raw[6], 1);
2431 assert_eq!(packet_raw[7], 2);
2432 assert_eq!(packet_raw[8], 3);
2433 assert_eq!(packet_raw[9], 4);
2434 }
2435
2436 #[test]
2437 fn test_ccsds_creator_creation_alt_tc() {
2438 let data = [1, 2, 3, 4];
2439 let packet_creator = CcsdsPacketCreator::new_tc_with_checksum(
2440 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2441 &data,
2442 )
2443 .unwrap();
2444 let packet_raw = packet_creator.to_vec();
2445 generic_test_creator(&packet_raw, packet_creator.sp_header(), PacketType::Tc);
2446 }
2447
2448 #[test]
2449 fn test_ccsds_creator_creation_alt_tc_owned() {
2450 let data = [1, 2, 3, 4];
2451 let packet_creator = CcsdsPacketCreatorOwned::new_tc_with_checksum(
2452 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2453 &data,
2454 )
2455 .unwrap();
2456 let packet_raw = packet_creator.to_vec();
2457 generic_test_creator(&packet_raw, packet_creator.sp_header(), PacketType::Tc);
2458 }
2459
2460 #[test]
2461 fn test_ccsds_creator_creation_alt_tm() {
2462 let data = [1, 2, 3, 4];
2463 let packet_creator = CcsdsPacketCreator::new_tm_with_checksum(
2464 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2465 &data,
2466 )
2467 .unwrap();
2468 let packet_raw = packet_creator.to_vec();
2469 generic_test_creator(&packet_raw, packet_creator.sp_header(), PacketType::Tm);
2470 }
2471
2472 #[test]
2473 fn test_ccsds_creator_creation_alt_tm_owned() {
2474 let data = [1, 2, 3, 4];
2475 let packet_creator = CcsdsPacketCreatorOwned::new_tm_with_checksum(
2476 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2477 &data,
2478 )
2479 .unwrap();
2480 let packet_raw = packet_creator.to_vec();
2481 generic_test_creator(&packet_raw, packet_creator.sp_header(), PacketType::Tm);
2482 }
2483
2484 fn generic_ccsds_reader_test(
2485 packet_data: &[u8],
2486 packet_raw: &[u8],
2487 packet_type: PacketType,
2488 sp_header: SpHeader,
2489 ) {
2490 assert_eq!(
2491 CcsdsPacketCreator::packet_len_for_user_data_with_checksum(4).unwrap(),
2492 packet_raw.len()
2493 );
2494 let reader = CcsdsPacketReader::new_with_checksum(packet_raw).unwrap();
2495 assert_eq!(*reader.sp_header(), sp_header);
2496 assert_eq!(reader.packet_data(), packet_data);
2497 assert_eq!(reader.apid(), u11::new(0x1));
2498 assert_eq!(
2499 reader.packet_id(),
2500 PacketId::new(packet_type, false, u11::new(0x1))
2501 );
2502 assert_eq!(
2503 reader.psc(),
2504 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0x0))
2505 );
2506 assert_eq!(reader.packet_len(), packet_raw.len());
2507 assert_eq!(reader.packet_type(), packet_type);
2508 assert_eq!(reader.data_len() as usize, packet_raw.len() - 7);
2509 }
2510
2511 #[test]
2512 fn test_ccsds_reader_tc() {
2513 let data = [1, 2, 3, 4];
2514 let packet_type = PacketType::Tc;
2515 let packet_creator = CcsdsPacketCreator::new(
2516 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2517 packet_type,
2518 &data,
2519 Some(ChecksumType::WithCrc16),
2520 )
2521 .unwrap();
2522 let sp_header = packet_creator.sp_header();
2523 generic_ccsds_reader_test(&data, &packet_creator.to_vec(), packet_type, *sp_header);
2524 }
2525
2526 #[test]
2527 fn test_ccsds_reader_tc_owned_creator() {
2528 let data = [1, 2, 3, 4];
2529 let packet_type = PacketType::Tc;
2530 let packet_creator = CcsdsPacketCreatorOwned::new(
2531 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2532 packet_type,
2533 &data,
2534 Some(ChecksumType::WithCrc16),
2535 )
2536 .unwrap();
2537 let sp_header = packet_creator.sp_header();
2538 generic_ccsds_reader_test(&data, &packet_creator.to_vec(), packet_type, *sp_header);
2539 }
2540
2541 #[test]
2542 fn test_ccsds_reader_tm() {
2543 let data = [1, 2, 3, 4];
2544 let packet_type = PacketType::Tm;
2545 let packet_creator = CcsdsPacketCreator::new(
2546 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2547 packet_type,
2548 &data,
2549 Some(ChecksumType::WithCrc16),
2550 )
2551 .unwrap();
2552 let sp_header = packet_creator.sp_header();
2553 generic_ccsds_reader_test(&data, &packet_creator.to_vec(), packet_type, *sp_header);
2554 }
2555
2556 #[test]
2557 fn test_ccsds_reader_tm_owned_creator() {
2558 let data = [1, 2, 3, 4];
2559 let packet_type = PacketType::Tm;
2560 let packet_creator = CcsdsPacketCreatorOwned::new(
2561 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2562 packet_type,
2563 &data,
2564 Some(ChecksumType::WithCrc16),
2565 )
2566 .unwrap();
2567 let sp_header = packet_creator.sp_header();
2568 generic_ccsds_reader_test(&data, &packet_creator.to_vec(), packet_type, *sp_header);
2569 }
2570
2571 fn generic_test_no_checksum(packet_raw: &[u8], packet_data: &[u8], sp_header: SpHeader) {
2572 let reader = CcsdsPacketReader::new(packet_raw, None).unwrap();
2573 assert_eq!(*reader.sp_header(), sp_header);
2574 assert_eq!(reader.packet_data(), packet_data);
2575 assert_eq!(reader.apid(), u11::new(0x1));
2576 assert_eq!(
2577 reader.packet_id(),
2578 PacketId::new(PacketType::Tc, false, u11::new(0x1))
2579 );
2580 assert_eq!(
2581 reader.psc(),
2582 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0x0))
2583 );
2584 assert_eq!(reader.packet_len(), packet_raw.len());
2585 assert_eq!(reader.packet_type(), PacketType::Tc);
2586 assert_eq!(reader.data_len() as usize, packet_raw.len() - 7);
2587 }
2588
2589 #[test]
2590 fn test_ccsds_reader_no_checksum() {
2591 let data = [1, 2, 3, 4];
2592 let packet_creator = CcsdsPacketCreator::new(
2593 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2594 PacketType::Tc,
2595 &data,
2596 None,
2597 )
2598 .unwrap();
2599 let sp_header = packet_creator.sp_header();
2600 assert_eq!(
2601 packet_creator.ccsds_packet_id_and_psc(),
2602 CcsdsPacketIdAndPsc::from(*sp_header)
2603 );
2604 assert_eq!(
2605 packet_creator.ccsds_packet_id_and_psc(),
2606 CcsdsPacketIdAndPsc::from(sp_header)
2607 );
2608 let packet_raw = packet_creator.to_vec();
2609 generic_test_no_checksum(&packet_raw, &data, *sp_header);
2610 }
2611
2612 #[test]
2613 fn test_ccsds_reader_no_checksum_owned() {
2614 let data = [1, 2, 3, 4];
2615 let packet_creator = CcsdsPacketCreatorOwned::new(
2616 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2617 PacketType::Tc,
2618 &data,
2619 None,
2620 )
2621 .unwrap();
2622 let sp_header = packet_creator.sp_header();
2623 assert_eq!(
2624 packet_creator.ccsds_packet_id_and_psc(),
2625 CcsdsPacketIdAndPsc::from(*sp_header)
2626 );
2627 assert_eq!(
2628 packet_creator.ccsds_packet_id_and_psc(),
2629 CcsdsPacketIdAndPsc::from(sp_header)
2630 );
2631 let packet_raw = packet_creator.to_vec();
2632 generic_test_no_checksum(&packet_raw, &data, *sp_header);
2633 }
2634
2635 #[test]
2636 fn test_ccsds_reader_buf_too_small() {
2637 let data = [1, 2, 3, 4];
2638 let packet_creator = CcsdsPacketCreator::new(
2639 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2640 PacketType::Tc,
2641 &data,
2642 None,
2643 )
2644 .unwrap();
2645 let packet_raw = packet_creator.to_vec();
2646 let reader_error = CcsdsPacketReader::new(&packet_raw[0..8], None);
2647 assert!(reader_error.is_err());
2648 let error = reader_error.unwrap_err();
2649 matches!(
2650 error,
2651 CcsdsPacketReadError::ByteConversion(ByteConversionError::FromSliceTooSmall {
2652 found: 8,
2653 expected: 10
2654 })
2655 );
2656 }
2657
2658 #[test]
2659 fn test_ccsds_reader_buf_too_small_owned() {
2660 let data = [1, 2, 3, 4];
2661 let packet_creator = CcsdsPacketCreatorOwned::new(
2662 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2663 PacketType::Tc,
2664 &data,
2665 None,
2666 )
2667 .unwrap();
2668 let packet_raw = packet_creator.to_vec();
2669 let reader_error = CcsdsPacketReader::new(&packet_raw[0..8], None);
2670 assert!(reader_error.is_err());
2671 let error = reader_error.unwrap_err();
2672 matches!(
2673 error,
2674 CcsdsPacketReadError::ByteConversion(ByteConversionError::FromSliceTooSmall {
2675 found: 8,
2676 expected: 10
2677 })
2678 );
2679 }
2680
2681 #[test]
2682 fn test_ccsds_checksum_error() {
2683 let data = [1, 2, 3, 4];
2684 let packet_creator = CcsdsPacketCreator::new_tc_with_checksum(
2685 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2686 &data,
2687 )
2688 .unwrap();
2689 let mut packet_raw = packet_creator.to_vec();
2690 *packet_raw.last_mut().unwrap() = 0;
2691 let reader_error = CcsdsPacketReader::new_with_checksum(&packet_raw);
2692 assert!(reader_error.is_err());
2693 assert_eq!(reader_error.unwrap_err(), CcsdsPacketReadError::CrcError);
2694 }
2695 #[test]
2696 fn test_ccsds_checksum_ignored() {
2697 let data = [1, 2, 3, 4];
2698 let packet_creator = CcsdsPacketCreator::new_tc_with_checksum(
2699 SpacePacketHeader::new_from_apid(u11::new(0x1)),
2700 &data,
2701 )
2702 .unwrap();
2703 let mut packet_raw = packet_creator.to_vec();
2704 *packet_raw.last_mut().unwrap() = 0;
2705 let reader =
2706 CcsdsPacketReader::new(&packet_raw, Some(ChecksumType::WithCrc16ButIgnored)).unwrap();
2707 assert_eq!(reader.packet_data(), data);
2708 }
2709
2710 #[test]
2711 fn sp_header_to_buf_too_small() {
2712 let sph = SpacePacketHeader::new_from_apid(u11::new(0x01));
2713 let mut buf: [u8; 5] = [0; 5];
2714 assert_eq!(
2715 sph.write_to_be_bytes(&mut buf).unwrap_err(),
2716 ByteConversionError::ToSliceTooSmall {
2717 found: 5,
2718 expected: 6
2719 }
2720 );
2721 }
2722
2723 #[test]
2724 fn sp_header_from_buf_too_small() {
2725 let buf: [u8; 5] = [0; 5];
2726 let sph = SpacePacketHeader::from_be_bytes(&buf);
2727 assert_eq!(
2728 sph.unwrap_err(),
2729 ByteConversionError::FromSliceTooSmall {
2730 found: 5,
2731 expected: 6
2732 }
2733 );
2734 }
2735
2736 #[test]
2737 fn sp_header_default() {
2738 let sph = SpacePacketHeader::default();
2739 assert_eq!(sph.packet_id(), PacketId::default());
2740 assert_eq!(sph.apid().value(), 0);
2741 assert_eq!(
2742 sph.psc(),
2743 PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0))
2744 );
2745 assert_eq!(sph.data_len(), 0);
2746 }
2747
2748 #[test]
2749 fn ccsds_packet_id() {
2750 let packet_id = PacketId::new_for_tc(false, u11::new(0x5));
2751 let psc = PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0));
2752 let sph = SpacePacketHeader::new(packet_id, psc, 0);
2753 let id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&sph);
2754
2755 assert_eq!(id.packet_id, packet_id);
2756 assert_eq!(id.psc, psc);
2757 assert_eq!(
2758 id.raw(),
2759 ((id.packet_id.raw() as u32) << 16) | id.psc.raw() as u32
2760 );
2761 let id_from = CcsdsPacketIdAndPsc::from(sph);
2762 assert_eq!(id_from, id);
2763
2764 use std::collections::hash_map::DefaultHasher;
2766 let mut hasher = DefaultHasher::new();
2767 id.hash(&mut hasher);
2768 }
2769}