//! Low-level CCSDS File Delivery Protocol (CFDP) support according to [CCSDS 727.0-B-5](https://public.ccsds.org/Pubs/727x0b5.pdf). use crate::ByteConversionError; use core::fmt::{Display, Formatter}; use num_enum::{IntoPrimitive, TryFromPrimitive}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use std::error::Error; pub mod lv; pub mod pdu; pub mod tlv; /// This is the name of the standard this module is based on. pub const CFDP_VERSION_2_NAME: &str = "CCSDS 727.0-B-5"; /// Currently, only this version is supported. pub const CFDP_VERSION_2: u8 = 0b001; #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum PduType { FileDirective = 0, FileData = 1, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum Direction { TowardsReceiver = 0, TowardsSender = 1, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum TransmissionMode { Acknowledged = 0, Unacknowledged = 1, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum CrcFlag { NoCrc = 0, WithCrc = 1, } /// Always 0 and ignores for File Directive PDUs (CCSDS 727.0-B-5 P.75) #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum SegmentMetadataFlag { NotPresent = 0, Present = 1, } /// Always 0 and ignores for File Directive PDUs (CCSDS 727.0-B-5 P.75) #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum SegmentationControl { NoRecordBoundaryPreservation = 0, WithRecordBoundaryPreservation = 1, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum FaultHandlerCode { NoticeOfCancellation = 0b0001, NoticeOfSuspension = 0b0010, IgnoreError = 0b0011, AbandonTransaction = 0b0100, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum LenInBytes { ZeroOrNone = 0, OneByte = 1, TwoBytes = 2, ThreeBytes = 4, FourBytes = 8, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum ConditionCode { /// This is not an error condition for which a faulty handler override can be specified NoError = 0b0000, PositiveAckLimitReached = 0b0001, KeepAliveLimitReached = 0b0010, InvalidTransmissionMode = 0b0011, FilestoreRejection = 0b0100, FileChecksumFailure = 0b0101, FileSizeError = 0b0110, NakLimitReached = 0b0111, InactivityDetected = 0b1000, CheckLimitReached = 0b1001, UnsupportedChecksumType = 0b1011, /// Not an actual fault condition for which fault handler overrides can be specified SuspendRequestReceived = 0b1110, /// Not an actual fault condition for which fault handler overrides can be specified CancelRequestReceived = 0b1111, } #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum LargeFileFlag { /// 32 bit maximum file size and FSS size Normal = 0, /// 64 bit maximum file size and FSS size Large = 1, } /// Checksum types according to the /// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/) #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[repr(u8)] pub enum ChecksumType { /// Modular legacy checksum Modular = 0, Crc32Proximity1 = 1, Crc32C = 2, /// Polynomial: 0x4C11DB7. Preferred checksum for now. Crc32 = 3, NullChecksum = 15, } pub const NULL_CHECKSUM_U32: [u8; 4] = [0; 4]; #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum TlvLvError { DataTooLarge(usize), ByteConversionError(ByteConversionError), /// First value: Found value. Second value: Expected value if there is one. InvalidTlvTypeField((u8, Option)), /// Logically invalid value length detected. The value length may not exceed 255 bytes. /// Depending on the concrete TLV type, the value length may also be logically invalid. InvalidValueLength(usize), /// Only applies to filestore requests and responses. Second name was missing where one is /// expected. SecondNameMissing, /// Invalid action code for filestore requests or responses. InvalidFilestoreActionCode(u8), } impl From for TlvLvError { fn from(value: ByteConversionError) -> Self { Self::ByteConversionError(value) } } impl Display for TlvLvError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { TlvLvError::DataTooLarge(data_len) => { write!( f, "data with size {} larger than allowed {} bytes", data_len, u8::MAX ) } TlvLvError::ByteConversionError(e) => { write!(f, "{}", e) } TlvLvError::InvalidTlvTypeField((found, expected)) => { write!( f, "invalid TLV type field, found {found}, possibly expected {expected:?}" ) } TlvLvError::InvalidValueLength(len) => { write!(f, "invalid value length {len} detected") } TlvLvError::SecondNameMissing => { write!(f, "second name missing for filestore request or response") } TlvLvError::InvalidFilestoreActionCode(raw) => { write!(f, "invalid filestore action code with raw value {raw}") } } } } #[cfg(feature = "std")] impl Error for TlvLvError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { TlvLvError::ByteConversionError(e) => Some(e), _ => None, } } }