added additional ctors which only set the APID #80
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
## Added
|
## Added
|
||||||
|
|
||||||
- `SpHeader::new_from_apid` and `SpHeader::new_from_apid_checked` constructor.
|
- `SpHeader::new_from_apid` and `SpHeader::new_from_apid_checked` constructor.
|
||||||
|
- `#[inline]` attribute for a lot of small functions.
|
||||||
|
|
||||||
# [v0.11.0-rc.1] 2024-04-03
|
# [v0.11.0-rc.1] 2024-04-03
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ pub(crate) fn generic_len_check_deserialization(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> Lv<'data> {
|
impl<'data> Lv<'data> {
|
||||||
|
#[inline]
|
||||||
pub fn new(data: &[u8]) -> Result<Lv, TlvLvError> {
|
pub fn new(data: &[u8]) -> Result<Lv, TlvLvError> {
|
||||||
if data.len() > u8::MAX as usize {
|
if data.len() > u8::MAX as usize {
|
||||||
return Err(TlvLvError::DataTooLarge(data.len()));
|
return Err(TlvLvError::DataTooLarge(data.len()));
|
||||||
@ -73,6 +74,7 @@ impl<'data> Lv<'data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a LV with an empty value field.
|
/// Creates a LV with an empty value field.
|
||||||
|
#[inline]
|
||||||
pub fn new_empty() -> Lv<'data> {
|
pub fn new_empty() -> Lv<'data> {
|
||||||
Lv {
|
Lv {
|
||||||
data: &[],
|
data: &[],
|
||||||
@ -82,6 +84,7 @@ impl<'data> Lv<'data> {
|
|||||||
|
|
||||||
/// Helper function to build a string LV. This is especially useful for the file or directory
|
/// Helper function to build a string LV. This is especially useful for the file or directory
|
||||||
/// path LVs
|
/// path LVs
|
||||||
|
#[inline]
|
||||||
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvError> {
|
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvError> {
|
||||||
Self::new(str_slice.as_bytes())
|
Self::new(str_slice.as_bytes())
|
||||||
}
|
}
|
||||||
@ -89,37 +92,44 @@ impl<'data> Lv<'data> {
|
|||||||
/// Helper function to build a string LV. This is especially useful for the file or directory
|
/// Helper function to build a string LV. This is especially useful for the file or directory
|
||||||
/// path LVs
|
/// path LVs
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[inline]
|
||||||
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvError> {
|
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvError> {
|
||||||
Self::new(string.as_bytes())
|
Self::new(string.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the value part, not including the length byte.
|
/// Returns the length of the value part, not including the length byte.
|
||||||
|
#[inline]
|
||||||
pub fn len_value(&self) -> usize {
|
pub fn len_value(&self) -> usize {
|
||||||
self.data.len()
|
self.data.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the full raw length, including the length byte.
|
/// Returns the full raw length, including the length byte.
|
||||||
|
#[inline]
|
||||||
pub fn len_full(&self) -> usize {
|
pub fn len_full(&self) -> usize {
|
||||||
self.len_value() + 1
|
self.len_value() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether the value field is empty.
|
/// Checks whether the value field is empty.
|
||||||
|
#[inline]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.data.len() == 0
|
self.data.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn value(&self) -> &[u8] {
|
pub fn value(&self) -> &[u8] {
|
||||||
self.data
|
self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the LV was generated from a raw bytestream using [Self::from_bytes], the raw start
|
/// If the LV was generated from a raw bytestream using [Self::from_bytes], the raw start
|
||||||
/// of the LV can be retrieved with this method.
|
/// of the LV can be retrieved with this method.
|
||||||
|
#[inline]
|
||||||
pub fn raw_data(&self) -> Option<&[u8]> {
|
pub fn raw_data(&self) -> Option<&[u8]> {
|
||||||
self.raw_data
|
self.raw_data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to extract the value as a [str]. This is useful if the LV is
|
/// Convenience function to extract the value as a [str]. This is useful if the LV is
|
||||||
/// known to contain a [str], for example being a file name.
|
/// known to contain a [str], for example being a file name.
|
||||||
|
#[inline]
|
||||||
pub fn value_as_str(&self) -> Option<Result<&'data str, Utf8Error>> {
|
pub fn value_as_str(&self) -> Option<Result<&'data str, Utf8Error>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
@ -135,6 +145,7 @@ impl<'data> Lv<'data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a LV from a raw buffer.
|
/// Reads a LV from a raw buffer.
|
||||||
|
#[inline]
|
||||||
pub fn from_bytes(buf: &'data [u8]) -> Result<Lv<'data>, ByteConversionError> {
|
pub fn from_bytes(buf: &'data [u8]) -> Result<Lv<'data>, ByteConversionError> {
|
||||||
generic_len_check_deserialization(buf, MIN_LV_LEN)?;
|
generic_len_check_deserialization(buf, MIN_LV_LEN)?;
|
||||||
Self::from_be_bytes_no_len_check(buf)
|
Self::from_be_bytes_no_len_check(buf)
|
||||||
@ -151,6 +162,7 @@ impl<'data> Lv<'data> {
|
|||||||
MIN_LV_LEN + self.data.len()
|
MIN_LV_LEN + self.data.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) fn from_be_bytes_no_len_check(
|
pub(crate) fn from_be_bytes_no_len_check(
|
||||||
buf: &'data [u8],
|
buf: &'data [u8],
|
||||||
) -> Result<Lv<'data>, ByteConversionError> {
|
) -> Result<Lv<'data>, ByteConversionError> {
|
||||||
|
@ -150,12 +150,14 @@ impl Error for PduError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<ByteConversionError> for PduError {
|
impl From<ByteConversionError> for PduError {
|
||||||
|
#[inline]
|
||||||
fn from(value: ByteConversionError) -> Self {
|
fn from(value: ByteConversionError) -> Self {
|
||||||
Self::ByteConversion(value)
|
Self::ByteConversion(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TlvLvError> for PduError {
|
impl From<TlvLvError> for PduError {
|
||||||
|
#[inline]
|
||||||
fn from(e: TlvLvError) -> Self {
|
fn from(e: TlvLvError) -> Self {
|
||||||
Self::TlvLvError(e)
|
Self::TlvLvError(e)
|
||||||
}
|
}
|
||||||
@ -179,33 +181,42 @@ pub trait WritablePduPacket {
|
|||||||
pub trait CfdpPdu {
|
pub trait CfdpPdu {
|
||||||
fn pdu_header(&self) -> &PduHeader;
|
fn pdu_header(&self) -> &PduHeader;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn source_id(&self) -> UnsignedByteField {
|
fn source_id(&self) -> UnsignedByteField {
|
||||||
self.pdu_header().common_pdu_conf().source_entity_id
|
self.pdu_header().common_pdu_conf().source_entity_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn dest_id(&self) -> UnsignedByteField {
|
fn dest_id(&self) -> UnsignedByteField {
|
||||||
self.pdu_header().common_pdu_conf().dest_entity_id
|
self.pdu_header().common_pdu_conf().dest_entity_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn transaction_seq_num(&self) -> UnsignedByteField {
|
fn transaction_seq_num(&self) -> UnsignedByteField {
|
||||||
self.pdu_header().common_pdu_conf().transaction_seq_num
|
self.pdu_header().common_pdu_conf().transaction_seq_num
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn transmission_mode(&self) -> TransmissionMode {
|
fn transmission_mode(&self) -> TransmissionMode {
|
||||||
self.pdu_header().common_pdu_conf().trans_mode
|
self.pdu_header().common_pdu_conf().trans_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn direction(&self) -> Direction {
|
fn direction(&self) -> Direction {
|
||||||
self.pdu_header().common_pdu_conf().direction
|
self.pdu_header().common_pdu_conf().direction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn crc_flag(&self) -> CrcFlag {
|
fn crc_flag(&self) -> CrcFlag {
|
||||||
self.pdu_header().common_pdu_conf().crc_flag
|
self.pdu_header().common_pdu_conf().crc_flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn file_flag(&self) -> LargeFileFlag {
|
fn file_flag(&self) -> LargeFileFlag {
|
||||||
self.pdu_header().common_pdu_conf().file_flag
|
self.pdu_header().common_pdu_conf().file_flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn pdu_type(&self) -> PduType {
|
fn pdu_type(&self) -> PduType {
|
||||||
self.pdu_header().pdu_type()
|
self.pdu_header().pdu_type()
|
||||||
}
|
}
|
||||||
@ -234,6 +245,7 @@ pub struct CommonPduConfig {
|
|||||||
|
|
||||||
// TODO: Builder pattern might be applicable here..
|
// TODO: Builder pattern might be applicable here..
|
||||||
impl CommonPduConfig {
|
impl CommonPduConfig {
|
||||||
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
source_id: impl Into<UnsignedByteField>,
|
source_id: impl Into<UnsignedByteField>,
|
||||||
dest_id: impl Into<UnsignedByteField>,
|
dest_id: impl Into<UnsignedByteField>,
|
||||||
@ -265,6 +277,7 @@ impl CommonPduConfig {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_with_byte_fields(
|
pub fn new_with_byte_fields(
|
||||||
source_id: impl Into<UnsignedByteField>,
|
source_id: impl Into<UnsignedByteField>,
|
||||||
dest_id: impl Into<UnsignedByteField>,
|
dest_id: impl Into<UnsignedByteField>,
|
||||||
@ -281,10 +294,12 @@ impl CommonPduConfig {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn source_id(&self) -> UnsignedByteField {
|
pub fn source_id(&self) -> UnsignedByteField {
|
||||||
self.source_entity_id
|
self.source_entity_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn source_dest_id_check(
|
fn source_dest_id_check(
|
||||||
source_id: impl Into<UnsignedByteField>,
|
source_id: impl Into<UnsignedByteField>,
|
||||||
dest_id: impl Into<UnsignedByteField>,
|
dest_id: impl Into<UnsignedByteField>,
|
||||||
@ -307,6 +322,7 @@ impl CommonPduConfig {
|
|||||||
Ok((source_id, dest_id))
|
Ok((source_id, dest_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_source_and_dest_id(
|
pub fn set_source_and_dest_id(
|
||||||
&mut self,
|
&mut self,
|
||||||
source_id: impl Into<UnsignedByteField>,
|
source_id: impl Into<UnsignedByteField>,
|
||||||
@ -318,6 +334,7 @@ impl CommonPduConfig {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn dest_id(&self) -> UnsignedByteField {
|
pub fn dest_id(&self) -> UnsignedByteField {
|
||||||
self.dest_entity_id
|
self.dest_entity_id
|
||||||
}
|
}
|
||||||
@ -326,6 +343,7 @@ impl CommonPduConfig {
|
|||||||
impl Default for CommonPduConfig {
|
impl Default for CommonPduConfig {
|
||||||
/// The defaults for the source ID, destination ID and the transaction sequence number is the
|
/// The defaults for the source ID, destination ID and the transaction sequence number is the
|
||||||
/// [UnsignedByteFieldU8] with an intitial value of 0
|
/// [UnsignedByteFieldU8] with an intitial value of 0
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// The new function can not fail for these input parameters.
|
// The new function can not fail for these input parameters.
|
||||||
Self::new(
|
Self::new(
|
||||||
@ -342,6 +360,7 @@ impl Default for CommonPduConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for CommonPduConfig {
|
impl PartialEq for CommonPduConfig {
|
||||||
|
#[inline]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.source_entity_id.value() == other.source_entity_id.value()
|
self.source_entity_id.value() == other.source_entity_id.value()
|
||||||
&& self.dest_entity_id.value() == other.dest_entity_id.value()
|
&& self.dest_entity_id.value() == other.dest_entity_id.value()
|
||||||
@ -370,6 +389,7 @@ pub struct PduHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PduHeader {
|
impl PduHeader {
|
||||||
|
#[inline]
|
||||||
pub fn new_for_file_data(
|
pub fn new_for_file_data(
|
||||||
pdu_conf: CommonPduConfig,
|
pdu_conf: CommonPduConfig,
|
||||||
pdu_datafield_len: u16,
|
pdu_datafield_len: u16,
|
||||||
@ -385,6 +405,7 @@ impl PduHeader {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_for_file_data_default(pdu_conf: CommonPduConfig, pdu_datafield_len: u16) -> Self {
|
pub fn new_for_file_data_default(pdu_conf: CommonPduConfig, pdu_datafield_len: u16) -> Self {
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
PduType::FileData,
|
PduType::FileData,
|
||||||
@ -394,6 +415,7 @@ impl PduHeader {
|
|||||||
SegmentationControl::NoRecordBoundaryPreservation,
|
SegmentationControl::NoRecordBoundaryPreservation,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn new_no_file_data(pdu_conf: CommonPduConfig, pdu_datafield_len: u16) -> Self {
|
pub fn new_no_file_data(pdu_conf: CommonPduConfig, pdu_datafield_len: u16) -> Self {
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
PduType::FileDirective,
|
PduType::FileDirective,
|
||||||
@ -404,6 +426,7 @@ impl PduHeader {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_generic(
|
pub fn new_generic(
|
||||||
pdu_type: PduType,
|
pdu_type: PduType,
|
||||||
pdu_conf: CommonPduConfig,
|
pdu_conf: CommonPduConfig,
|
||||||
@ -421,6 +444,7 @@ impl PduHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns only the length of the PDU header when written to a raw buffer.
|
/// Returns only the length of the PDU header when written to a raw buffer.
|
||||||
|
#[inline]
|
||||||
pub fn header_len(&self) -> usize {
|
pub fn header_len(&self) -> usize {
|
||||||
FIXED_HEADER_LEN
|
FIXED_HEADER_LEN
|
||||||
+ self.pdu_conf.source_entity_id.size()
|
+ self.pdu_conf.source_entity_id.size()
|
||||||
@ -428,12 +452,14 @@ impl PduHeader {
|
|||||||
+ self.pdu_conf.dest_entity_id.size()
|
+ self.pdu_conf.dest_entity_id.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn pdu_datafield_len(&self) -> usize {
|
pub fn pdu_datafield_len(&self) -> usize {
|
||||||
self.pdu_datafield_len.into()
|
self.pdu_datafield_len.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the full length of the PDU when written to a raw buffer, which is the header length
|
/// Returns the full length of the PDU when written to a raw buffer, which is the header length
|
||||||
/// plus the PDU datafield length.
|
/// plus the PDU datafield length.
|
||||||
|
#[inline]
|
||||||
pub fn pdu_len(&self) -> usize {
|
pub fn pdu_len(&self) -> usize {
|
||||||
self.header_len() + self.pdu_datafield_len as usize
|
self.header_len() + self.pdu_datafield_len as usize
|
||||||
}
|
}
|
||||||
@ -606,10 +632,13 @@ impl PduHeader {
|
|||||||
current_idx,
|
current_idx,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn pdu_type(&self) -> PduType {
|
pub fn pdu_type(&self) -> PduType {
|
||||||
self.pdu_type
|
self.pdu_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn common_pdu_conf(&self) -> &CommonPduConfig {
|
pub fn common_pdu_conf(&self) -> &CommonPduConfig {
|
||||||
&self.pdu_conf
|
&self.pdu_conf
|
||||||
}
|
}
|
||||||
@ -617,6 +646,8 @@ impl PduHeader {
|
|||||||
pub fn seg_metadata_flag(&self) -> SegmentMetadataFlag {
|
pub fn seg_metadata_flag(&self) -> SegmentMetadataFlag {
|
||||||
self.seg_metadata_flag
|
self.seg_metadata_flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn seg_ctrl(&self) -> SegmentationControl {
|
pub fn seg_ctrl(&self) -> SegmentationControl {
|
||||||
self.seg_ctrl
|
self.seg_ctrl
|
||||||
}
|
}
|
||||||
|
@ -262,9 +262,13 @@ pub(crate) fn verify_crc16_ccitt_false_from_raw(raw_data: &[u8]) -> bool {
|
|||||||
macro_rules! ccsds_impl {
|
macro_rules! ccsds_impl {
|
||||||
() => {
|
() => {
|
||||||
delegate!(to self.sp_header {
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
fn ccsds_version(&self) -> u8;
|
fn ccsds_version(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn packet_id(&self) -> crate::PacketId;
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
fn psc(&self) -> crate::PacketSequenceCtrl;
|
fn psc(&self) -> crate::PacketSequenceCtrl;
|
||||||
|
#[inline]
|
||||||
fn data_len(&self) -> u16;
|
fn data_len(&self) -> u16;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -273,8 +277,11 @@ macro_rules! ccsds_impl {
|
|||||||
macro_rules! sp_header_impls {
|
macro_rules! sp_header_impls {
|
||||||
() => {
|
() => {
|
||||||
delegate!(to self.sp_header {
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool;
|
pub fn set_apid(&mut self, apid: u16) -> bool;
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
|
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_flags(&mut self, seq_flag: SequenceFlags);
|
pub fn set_seq_flags(&mut self, seq_flag: SequenceFlags);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ pub enum SchedStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<bool> for SchedStatus {
|
impl From<bool> for SchedStatus {
|
||||||
|
#[inline]
|
||||||
fn from(value: bool) -> Self {
|
fn from(value: bool) -> Self {
|
||||||
if value {
|
if value {
|
||||||
SchedStatus::Enabled
|
SchedStatus::Enabled
|
||||||
|
@ -111,22 +111,27 @@ pub mod zc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> PusVersion {
|
||||||
PusVersion::try_from(self.version_ack >> 4 & 0b1111).unwrap_or(PusVersion::Invalid)
|
PusVersion::try_from(self.version_ack >> 4 & 0b1111).unwrap_or(PusVersion::Invalid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ack_flags(&self) -> u8 {
|
fn ack_flags(&self) -> u8 {
|
||||||
self.version_ack & 0b1111
|
self.version_ack & 0b1111
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8 {
|
fn service(&self) -> u8 {
|
||||||
self.service
|
self.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8 {
|
fn subservice(&self) -> u8 {
|
||||||
self.subservice
|
self.subservice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn source_id(&self) -> u16 {
|
fn source_id(&self) -> u16 {
|
||||||
self.source_id.get()
|
self.source_id.get()
|
||||||
}
|
}
|
||||||
@ -155,22 +160,27 @@ pub struct PusTcSecondaryHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> PusVersion {
|
||||||
self.version
|
self.version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ack_flags(&self) -> u8 {
|
fn ack_flags(&self) -> u8 {
|
||||||
self.ack
|
self.ack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8 {
|
fn service(&self) -> u8 {
|
||||||
self.service
|
self.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8 {
|
fn subservice(&self) -> u8 {
|
||||||
self.subservice
|
self.subservice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn source_id(&self) -> u16 {
|
fn source_id(&self) -> u16 {
|
||||||
self.source_id
|
self.source_id
|
||||||
}
|
}
|
||||||
@ -191,6 +201,7 @@ impl TryFrom<zc::PusTcSecondaryHeader> for PusTcSecondaryHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTcSecondaryHeader {
|
impl PusTcSecondaryHeader {
|
||||||
|
#[inline]
|
||||||
pub fn new_simple(service: u8, subservice: u8) -> Self {
|
pub fn new_simple(service: u8, subservice: u8) -> Self {
|
||||||
PusTcSecondaryHeader {
|
PusTcSecondaryHeader {
|
||||||
service,
|
service,
|
||||||
@ -201,6 +212,7 @@ impl PusTcSecondaryHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new(service: u8, subservice: u8, ack: u8, source_id: u16) -> Self {
|
pub fn new(service: u8, subservice: u8, ack: u8, source_id: u16) -> Self {
|
||||||
PusTcSecondaryHeader {
|
PusTcSecondaryHeader {
|
||||||
service,
|
service,
|
||||||
@ -242,6 +254,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
/// * `set_ccsds_len` - Can be used to automatically update the CCSDS space packet data length
|
/// * `set_ccsds_len` - Can be used to automatically update the CCSDS space packet data length
|
||||||
/// field. If this is not set to true, [Self::update_ccsds_data_len] can be called to set
|
/// field. If this is not set to true, [Self::update_ccsds_data_len] can be called to set
|
||||||
/// the correct value to this field manually
|
/// the correct value to this field manually
|
||||||
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
sec_header: PusTcSecondaryHeader,
|
sec_header: PusTcSecondaryHeader,
|
||||||
@ -263,6 +276,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
|
|
||||||
/// Simplified version of the [Self::new] function which allows to only specify service
|
/// Simplified version of the [Self::new] function which allows to only specify service
|
||||||
/// and subservice instead of the full PUS TC secondary header.
|
/// and subservice instead of the full PUS TC secondary header.
|
||||||
|
#[inline]
|
||||||
pub fn new_simple(
|
pub fn new_simple(
|
||||||
sph: &mut SpHeader,
|
sph: &mut SpHeader,
|
||||||
service: u8,
|
service: u8,
|
||||||
@ -278,6 +292,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_no_app_data(
|
pub fn new_no_app_data(
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
sec_header: PusTcSecondaryHeader,
|
sec_header: PusTcSecondaryHeader,
|
||||||
@ -286,10 +301,12 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
Self::new(sp_header, sec_header, &[], set_ccsds_len)
|
Self::new(sp_header, sec_header, &[], set_ccsds_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn sp_header(&self) -> &SpHeader {
|
pub fn sp_header(&self) -> &SpHeader {
|
||||||
&self.sp_header
|
&self.sp_header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_ack_field(&mut self, ack: u8) -> bool {
|
pub fn set_ack_field(&mut self, ack: u8) -> bool {
|
||||||
if ack > 0b1111 {
|
if ack > 0b1111 {
|
||||||
return false;
|
return false;
|
||||||
@ -298,6 +315,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_source_id(&mut self, source_id: u16) {
|
pub fn set_source_id(&mut self, source_id: u16) {
|
||||||
self.sec_header.source_id = source_id;
|
self.sec_header.source_id = source_id;
|
||||||
}
|
}
|
||||||
@ -310,6 +328,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
/// If this was not done or the application data is set or changed after construction,
|
/// If this was not done or the application data is set or changed after construction,
|
||||||
/// this function needs to be called to ensure that the data length field of the CCSDS header
|
/// this function needs to be called to ensure that the data length field of the CCSDS header
|
||||||
/// is set correctly.
|
/// is set correctly.
|
||||||
|
#[inline]
|
||||||
pub fn update_ccsds_data_len(&mut self) {
|
pub fn update_ccsds_data_len(&mut self) {
|
||||||
self.sp_header.data_len =
|
self.sp_header.data_len =
|
||||||
self.len_written() as u16 - size_of::<crate::zc::SpHeader>() as u16 - 1;
|
self.len_written() as u16 - size_of::<crate::zc::SpHeader>() as u16 - 1;
|
||||||
@ -345,6 +364,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WritablePusPacket for PusTcCreator<'_> {
|
impl WritablePusPacket for PusTcCreator<'_> {
|
||||||
|
#[inline]
|
||||||
fn len_written(&self) -> usize {
|
fn len_written(&self) -> usize {
|
||||||
PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len()
|
PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len()
|
||||||
}
|
}
|
||||||
@ -385,15 +405,20 @@ impl CcsdsPacket for PusTcCreator<'_> {
|
|||||||
|
|
||||||
impl PusPacket for PusTcCreator<'_> {
|
impl PusPacket for PusTcCreator<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn user_data(&self) -> &[u8] {
|
fn user_data(&self) -> &[u8] {
|
||||||
self.app_data
|
self.app_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn crc16(&self) -> Option<u16> {
|
fn crc16(&self) -> Option<u16> {
|
||||||
Some(self.calc_own_crc16())
|
Some(self.calc_own_crc16())
|
||||||
}
|
}
|
||||||
@ -401,10 +426,15 @@ impl PusPacket for PusTcCreator<'_> {
|
|||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcCreator<'_> {
|
impl GenericPusTcSecondaryHeader for PusTcCreator<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn source_id(&self) -> u16;
|
fn source_id(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn ack_flags(&self) -> u8;
|
fn ack_flags(&self) -> u8;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -482,24 +512,29 @@ impl<'raw_data> PusTcReader<'raw_data> {
|
|||||||
Ok((pus_tc, total_len))
|
Ok((pus_tc, total_len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn app_data(&self) -> &[u8] {
|
pub fn app_data(&self) -> &[u8] {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn raw_data(&self) -> &[u8] {
|
pub fn raw_data(&self) -> &[u8] {
|
||||||
self.raw_data
|
self.raw_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn len_packed(&self) -> usize {
|
pub fn len_packed(&self) -> usize {
|
||||||
self.sp_header.total_len()
|
self.sp_header.total_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn sp_header(&self) -> &SpHeader {
|
pub fn sp_header(&self) -> &SpHeader {
|
||||||
&self.sp_header
|
&self.sp_header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for PusTcReader<'_> {
|
impl PartialEq for PusTcReader<'_> {
|
||||||
|
#[inline]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.raw_data == other.raw_data
|
self.raw_data == other.raw_data
|
||||||
}
|
}
|
||||||
@ -511,15 +546,20 @@ impl CcsdsPacket for PusTcReader<'_> {
|
|||||||
|
|
||||||
impl PusPacket for PusTcReader<'_> {
|
impl PusPacket for PusTcReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn user_data(&self) -> &[u8] {
|
fn user_data(&self) -> &[u8] {
|
||||||
self.app_data
|
self.app_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn crc16(&self) -> Option<u16> {
|
fn crc16(&self) -> Option<u16> {
|
||||||
Some(self.crc16)
|
Some(self.crc16)
|
||||||
}
|
}
|
||||||
@ -527,10 +567,15 @@ impl PusPacket for PusTcReader<'_> {
|
|||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcReader<'_> {
|
impl GenericPusTcSecondaryHeader for PusTcReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn source_id(&self) -> u16;
|
fn source_id(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn ack_flags(&self) -> u8;
|
fn ack_flags(&self) -> u8;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -86,27 +86,33 @@ pub mod zc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmSecHeaderWithoutTimestamp {
|
impl GenericPusTmSecondaryHeader for PusTmSecHeaderWithoutTimestamp {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> PusVersion {
|
||||||
PusVersion::try_from(self.pus_version_and_sc_time_ref_status >> 4 & 0b1111)
|
PusVersion::try_from(self.pus_version_and_sc_time_ref_status >> 4 & 0b1111)
|
||||||
.unwrap_or(PusVersion::Invalid)
|
.unwrap_or(PusVersion::Invalid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn sc_time_ref_status(&self) -> u8 {
|
fn sc_time_ref_status(&self) -> u8 {
|
||||||
self.pus_version_and_sc_time_ref_status & 0b1111
|
self.pus_version_and_sc_time_ref_status & 0b1111
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8 {
|
fn service(&self) -> u8 {
|
||||||
self.service
|
self.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8 {
|
fn subservice(&self) -> u8 {
|
||||||
self.subservice
|
self.subservice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn msg_counter(&self) -> u16 {
|
fn msg_counter(&self) -> u16 {
|
||||||
self.msg_counter.get()
|
self.msg_counter.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn dest_id(&self) -> u16 {
|
fn dest_id(&self) -> u16 {
|
||||||
self.dest_id.get()
|
self.dest_id.get()
|
||||||
}
|
}
|
||||||
@ -127,15 +133,18 @@ pub struct PusTmSecondaryHeader<'stamp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'stamp> PusTmSecondaryHeader<'stamp> {
|
impl<'stamp> PusTmSecondaryHeader<'stamp> {
|
||||||
|
#[inline]
|
||||||
pub fn new_simple(service: u8, subservice: u8, time_stamp: &'stamp [u8]) -> Self {
|
pub fn new_simple(service: u8, subservice: u8, time_stamp: &'stamp [u8]) -> Self {
|
||||||
Self::new(service, subservice, 0, 0, time_stamp)
|
Self::new(service, subservice, 0, 0, time_stamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [Self::new_simple] but without a timestamp.
|
/// Like [Self::new_simple] but without a timestamp.
|
||||||
|
#[inline]
|
||||||
pub fn new_simple_no_timestamp(service: u8, subservice: u8) -> Self {
|
pub fn new_simple_no_timestamp(service: u8, subservice: u8) -> Self {
|
||||||
Self::new(service, subservice, 0, 0, &[])
|
Self::new(service, subservice, 0, 0, &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
service: u8,
|
service: u8,
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
@ -156,26 +165,32 @@ impl<'stamp> PusTmSecondaryHeader<'stamp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> PusVersion {
|
||||||
self.pus_version
|
self.pus_version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn sc_time_ref_status(&self) -> u8 {
|
fn sc_time_ref_status(&self) -> u8 {
|
||||||
self.sc_time_ref_status
|
self.sc_time_ref_status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8 {
|
fn service(&self) -> u8 {
|
||||||
self.service
|
self.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8 {
|
fn subservice(&self) -> u8 {
|
||||||
self.subservice
|
self.subservice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn msg_counter(&self) -> u16 {
|
fn msg_counter(&self) -> u16 {
|
||||||
self.msg_counter
|
self.msg_counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn dest_id(&self) -> u16 {
|
fn dest_id(&self) -> u16 {
|
||||||
self.dest_id
|
self.dest_id
|
||||||
}
|
}
|
||||||
@ -184,6 +199,7 @@ impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
|||||||
impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice> {
|
impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice> {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn try_from(sec_header: zc::PusTmSecHeader<'slice>) -> Result<Self, Self::Error> {
|
fn try_from(sec_header: zc::PusTmSecHeader<'slice>) -> Result<Self, Self::Error> {
|
||||||
Ok(PusTmSecondaryHeader {
|
Ok(PusTmSecondaryHeader {
|
||||||
pus_version: sec_header.zc_header.pus_version(),
|
pus_version: sec_header.zc_header.pus_version(),
|
||||||
@ -235,6 +251,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
/// * `set_ccsds_len` - Can be used to automatically update the CCSDS space packet data length
|
/// * `set_ccsds_len` - Can be used to automatically update the CCSDS space packet data length
|
||||||
/// field. If this is not set to true, [Self::update_ccsds_data_len] can be called to set
|
/// field. If this is not set to true, [Self::update_ccsds_data_len] can be called to set
|
||||||
/// the correct value to this field manually
|
/// the correct value to this field manually
|
||||||
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
sec_header: PusTmSecondaryHeader<'time>,
|
sec_header: PusTmSecondaryHeader<'time>,
|
||||||
@ -255,6 +272,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
pus_tm
|
pus_tm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_simple(
|
pub fn new_simple(
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
service: u8,
|
service: u8,
|
||||||
@ -275,6 +293,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_no_source_data(
|
pub fn new_no_source_data(
|
||||||
sp_header: &mut SpHeader,
|
sp_header: &mut SpHeader,
|
||||||
sec_header: PusTmSecondaryHeader<'time>,
|
sec_header: PusTmSecondaryHeader<'time>,
|
||||||
@ -283,22 +302,27 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
Self::new(sp_header, sec_header, &[], set_ccsds_len)
|
Self::new(sp_header, sec_header, &[], set_ccsds_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn timestamp(&self) -> &[u8] {
|
pub fn timestamp(&self) -> &[u8] {
|
||||||
self.sec_header.time_stamp
|
self.sec_header.time_stamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn source_data(&self) -> &[u8] {
|
pub fn source_data(&self) -> &[u8] {
|
||||||
self.source_data
|
self.source_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_dest_id(&mut self, dest_id: u16) {
|
pub fn set_dest_id(&mut self, dest_id: u16) {
|
||||||
self.sec_header.dest_id = dest_id;
|
self.sec_header.dest_id = dest_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_msg_counter(&mut self, msg_counter: u16) {
|
pub fn set_msg_counter(&mut self, msg_counter: u16) {
|
||||||
self.sec_header.msg_counter = msg_counter
|
self.sec_header.msg_counter = msg_counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_sc_time_ref_status(&mut self, sc_time_ref_status: u8) {
|
pub fn set_sc_time_ref_status(&mut self, sc_time_ref_status: u8) {
|
||||||
self.sec_header.sc_time_ref_status = sc_time_ref_status & 0b1111;
|
self.sec_header.sc_time_ref_status = sc_time_ref_status & 0b1111;
|
||||||
}
|
}
|
||||||
@ -310,6 +334,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
/// If this was not done or the time stamp or source data is set or changed after construction,
|
/// If this was not done or the time stamp or source data is set or changed after construction,
|
||||||
/// this function needs to be called to ensure that the data length field of the CCSDS header
|
/// this function needs to be called to ensure that the data length field of the CCSDS header
|
||||||
/// is set correctly
|
/// is set correctly
|
||||||
|
#[inline]
|
||||||
pub fn update_ccsds_data_len(&mut self) {
|
pub fn update_ccsds_data_len(&mut self) {
|
||||||
self.sp_header.data_len =
|
self.sp_header.data_len =
|
||||||
self.len_written() as u16 - size_of::<crate::zc::SpHeader>() as u16 - 1;
|
self.len_written() as u16 - size_of::<crate::zc::SpHeader>() as u16 - 1;
|
||||||
@ -329,6 +354,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This helper function calls both [Self::update_ccsds_data_len] and [Self::calc_own_crc16]
|
/// This helper function calls both [Self::update_ccsds_data_len] and [Self::calc_own_crc16]
|
||||||
|
#[inline]
|
||||||
pub fn update_packet_fields(&mut self) {
|
pub fn update_packet_fields(&mut self) {
|
||||||
self.update_ccsds_data_len();
|
self.update_ccsds_data_len();
|
||||||
}
|
}
|
||||||
@ -386,6 +412,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WritablePusPacket for PusTmCreator<'_, '_> {
|
impl WritablePusPacket for PusTmCreator<'_, '_> {
|
||||||
|
#[inline]
|
||||||
fn len_written(&self) -> usize {
|
fn len_written(&self) -> usize {
|
||||||
PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA
|
PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA
|
||||||
+ self.sec_header.time_stamp.len()
|
+ self.sec_header.time_stamp.len()
|
||||||
@ -411,15 +438,20 @@ impl CcsdsPacket for PusTmCreator<'_, '_> {
|
|||||||
|
|
||||||
impl PusPacket for PusTmCreator<'_, '_> {
|
impl PusPacket for PusTmCreator<'_, '_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn user_data(&self) -> &[u8] {
|
fn user_data(&self) -> &[u8] {
|
||||||
self.source_data
|
self.source_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn crc16(&self) -> Option<u16> {
|
fn crc16(&self) -> Option<u16> {
|
||||||
Some(self.calc_own_crc16())
|
Some(self.calc_own_crc16())
|
||||||
}
|
}
|
||||||
@ -427,11 +459,17 @@ impl PusPacket for PusTmCreator<'_, '_> {
|
|||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> {
|
impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn dest_id(&self) -> u16;
|
fn dest_id(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn msg_counter(&self) -> u16;
|
fn msg_counter(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn sc_time_ref_status(&self) -> u8;
|
fn sc_time_ref_status(&self) -> u8;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -518,19 +556,23 @@ impl<'raw_data> PusTmReader<'raw_data> {
|
|||||||
Ok((pus_tm, total_len))
|
Ok((pus_tm, total_len))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn len_packed(&self) -> usize {
|
pub fn len_packed(&self) -> usize {
|
||||||
self.sp_header.total_len()
|
self.sp_header.total_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn source_data(&self) -> &[u8] {
|
pub fn source_data(&self) -> &[u8] {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn timestamp(&self) -> &[u8] {
|
pub fn timestamp(&self) -> &[u8] {
|
||||||
self.sec_header.time_stamp
|
self.sec_header.time_stamp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function will return the slice [Self] was constructed from.
|
/// This function will return the slice [Self] was constructed from.
|
||||||
|
#[inline]
|
||||||
pub fn raw_data(&self) -> &[u8] {
|
pub fn raw_data(&self) -> &[u8] {
|
||||||
self.raw_data
|
self.raw_data
|
||||||
}
|
}
|
||||||
@ -551,15 +593,20 @@ impl CcsdsPacket for PusTmReader<'_> {
|
|||||||
|
|
||||||
impl PusPacket for PusTmReader<'_> {
|
impl PusPacket for PusTmReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn user_data(&self) -> &[u8] {
|
fn user_data(&self) -> &[u8] {
|
||||||
self.source_data
|
self.source_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn crc16(&self) -> Option<u16> {
|
fn crc16(&self) -> Option<u16> {
|
||||||
Some(self.crc16)
|
Some(self.crc16)
|
||||||
}
|
}
|
||||||
@ -567,11 +614,17 @@ impl PusPacket for PusTmReader<'_> {
|
|||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmReader<'_> {
|
impl GenericPusTmSecondaryHeader for PusTmReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> PusVersion;
|
||||||
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
|
#[inline]
|
||||||
fn dest_id(&self) -> u16;
|
fn dest_id(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn msg_counter(&self) -> u16;
|
fn msg_counter(&self) -> u16;
|
||||||
|
#[inline]
|
||||||
fn sc_time_ref_status(&self) -> u8;
|
fn sc_time_ref_status(&self) -> u8;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -633,6 +686,7 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
|
|||||||
|
|
||||||
/// Set the sequence count. Returns false and does not update the value if the passed value
|
/// Set the sequence count. Returns false and does not update the value if the passed value
|
||||||
/// exceeds [MAX_APID].
|
/// exceeds [MAX_APID].
|
||||||
|
#[inline]
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool {
|
pub fn set_apid(&mut self, apid: u16) -> bool {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return false;
|
return false;
|
||||||
@ -645,11 +699,13 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This function sets the message counter in the PUS TM secondary header.
|
/// This function sets the message counter in the PUS TM secondary header.
|
||||||
|
#[inline]
|
||||||
pub fn set_msg_count(&mut self, msg_count: u16) {
|
pub fn set_msg_count(&mut self, msg_count: u16) {
|
||||||
self.raw_tm[9..11].copy_from_slice(&msg_count.to_be_bytes());
|
self.raw_tm[9..11].copy_from_slice(&msg_count.to_be_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function sets the destination ID in the PUS TM secondary header.
|
/// This function sets the destination ID in the PUS TM secondary header.
|
||||||
|
#[inline]
|
||||||
pub fn set_destination_id(&mut self, dest_id: u16) {
|
pub fn set_destination_id(&mut self, dest_id: u16) {
|
||||||
self.raw_tm[11..13].copy_from_slice(&dest_id.to_be_bytes())
|
self.raw_tm[11..13].copy_from_slice(&dest_id.to_be_bytes())
|
||||||
}
|
}
|
||||||
@ -674,6 +730,7 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
|
|||||||
|
|
||||||
/// Set the sequence count. Returns false and does not update the value if the passed value
|
/// Set the sequence count. Returns false and does not update the value if the passed value
|
||||||
/// exceeds [MAX_SEQ_COUNT].
|
/// exceeds [MAX_SEQ_COUNT].
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_count(&mut self, seq_count: u16) -> bool {
|
pub fn set_seq_count(&mut self, seq_count: u16) -> bool {
|
||||||
if seq_count > MAX_SEQ_COUNT {
|
if seq_count > MAX_SEQ_COUNT {
|
||||||
return false;
|
return false;
|
||||||
|
45
src/lib.rs
45
src/lib.rs
@ -207,18 +207,21 @@ pub struct PacketId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for PacketId {
|
impl PartialEq for PacketId {
|
||||||
|
#[inline]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.raw().eq(&other.raw())
|
self.raw().eq(&other.raw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for PacketId {
|
impl PartialOrd for PacketId {
|
||||||
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for PacketId {
|
impl Ord for PacketId {
|
||||||
|
#[inline]
|
||||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||||
self.raw().cmp(&other.raw())
|
self.raw().cmp(&other.raw())
|
||||||
}
|
}
|
||||||
@ -232,6 +235,7 @@ impl Hash for PacketId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PacketId {
|
impl Default for PacketId {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
PacketId {
|
PacketId {
|
||||||
ptype: PacketType::Tm,
|
ptype: PacketType::Tm,
|
||||||
@ -244,26 +248,31 @@ impl Default for PacketId {
|
|||||||
impl PacketId {
|
impl PacketId {
|
||||||
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
||||||
/// Use the checked constructor variants to avoid panics.
|
/// Use the checked constructor variants to avoid panics.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_tc(sec_header: bool, apid: u16) -> Self {
|
pub const fn new_for_tc(sec_header: bool, apid: u16) -> Self {
|
||||||
Self::new(PacketType::Tc, sec_header, apid)
|
Self::new(PacketType::Tc, sec_header, apid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
||||||
/// Use the checked constructor variants to avoid panics.
|
/// Use the checked constructor variants to avoid panics.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_tm(sec_header: bool, apid: u16) -> Self {
|
pub const fn new_for_tm(sec_header: bool, apid: u16) -> Self {
|
||||||
Self::new(PacketType::Tm, sec_header, apid)
|
Self::new(PacketType::Tm, sec_header, apid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_for_tc_checked(sec_header: bool, apid: u16) -> Option<Self> {
|
pub fn new_for_tc_checked(sec_header: bool, apid: u16) -> Option<Self> {
|
||||||
Self::new_checked(PacketType::Tc, sec_header, apid)
|
Self::new_checked(PacketType::Tc, sec_header, apid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_for_tm_checked(sec_header: bool, apid: u16) -> Option<Self> {
|
pub fn new_for_tm_checked(sec_header: bool, apid: u16) -> Option<Self> {
|
||||||
Self::new_checked(PacketType::Tm, sec_header, apid)
|
Self::new_checked(PacketType::Tm, sec_header, apid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
||||||
/// Use the checked variants to avoid panics.
|
/// Use the checked variants to avoid panics.
|
||||||
|
#[inline]
|
||||||
pub const fn new(ptype: PacketType, sec_header: bool, apid: u16) -> Self {
|
pub const fn new(ptype: PacketType, sec_header: bool, apid: u16) -> Self {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
panic!("APID too large");
|
panic!("APID too large");
|
||||||
@ -275,6 +284,7 @@ impl PacketId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_checked(ptype: PacketType, sec_header_flag: bool, apid: u16) -> Option<PacketId> {
|
pub fn new_checked(ptype: PacketType, sec_header_flag: bool, apid: u16) -> Option<PacketId> {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return None;
|
return None;
|
||||||
@ -285,6 +295,7 @@ impl PacketId {
|
|||||||
/// Set a new Application Process ID (APID). If the passed number is invalid, the APID will
|
/// Set a new Application Process ID (APID). If the passed number is invalid, the APID will
|
||||||
/// not be set and false will be returned. The maximum allowed value for the 11-bit field is
|
/// not be set and false will be returned. The maximum allowed value for the 11-bit field is
|
||||||
/// 2047
|
/// 2047
|
||||||
|
#[inline]
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool {
|
pub fn set_apid(&mut self, apid: u16) -> bool {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return false;
|
return false;
|
||||||
@ -293,6 +304,7 @@ impl PacketId {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn apid(&self) -> u16 {
|
pub fn apid(&self) -> u16 {
|
||||||
self.apid
|
self.apid
|
||||||
}
|
}
|
||||||
@ -326,6 +338,7 @@ pub struct PacketSequenceCtrl {
|
|||||||
impl PacketSequenceCtrl {
|
impl PacketSequenceCtrl {
|
||||||
/// This constructor panics if the sequence count exceeds [MAX_SEQ_COUNT].
|
/// This constructor panics if the sequence count exceeds [MAX_SEQ_COUNT].
|
||||||
/// Use [Self::new_checked] to avoid panics.
|
/// Use [Self::new_checked] to avoid panics.
|
||||||
|
#[inline]
|
||||||
pub const fn new(seq_flags: SequenceFlags, seq_count: u16) -> PacketSequenceCtrl {
|
pub const fn new(seq_flags: SequenceFlags, seq_count: u16) -> PacketSequenceCtrl {
|
||||||
if seq_count > MAX_SEQ_COUNT {
|
if seq_count > MAX_SEQ_COUNT {
|
||||||
panic!("Sequence count too large");
|
panic!("Sequence count too large");
|
||||||
@ -337,18 +350,22 @@ impl PacketSequenceCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [None] if the passed sequence count exceeds [MAX_SEQ_COUNT].
|
/// Returns [None] if the passed sequence count exceeds [MAX_SEQ_COUNT].
|
||||||
|
#[inline]
|
||||||
pub fn new_checked(seq_flags: SequenceFlags, seq_count: u16) -> Option<PacketSequenceCtrl> {
|
pub fn new_checked(seq_flags: SequenceFlags, seq_count: u16) -> Option<PacketSequenceCtrl> {
|
||||||
if seq_count > MAX_SEQ_COUNT {
|
if seq_count > MAX_SEQ_COUNT {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(PacketSequenceCtrl::new(seq_flags, seq_count))
|
Some(PacketSequenceCtrl::new(seq_flags, seq_count))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn raw(&self) -> u16 {
|
pub fn raw(&self) -> u16 {
|
||||||
((self.seq_flags as u16) << 14) | self.seq_count
|
((self.seq_flags as u16) << 14) | self.seq_count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a new sequence count. If the passed number is invalid, the sequence count will not be
|
/// Set a new sequence count. If the passed number is invalid, the sequence count will not be
|
||||||
/// set and false will be returned. The maximum allowed value for the 14-bit field is 16383.
|
/// set and false will be returned. The maximum allowed value for the 14-bit field is 16383.
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_count(&mut self, ssc: u16) -> bool {
|
pub fn set_seq_count(&mut self, ssc: u16) -> bool {
|
||||||
if ssc > MAX_SEQ_COUNT {
|
if ssc > MAX_SEQ_COUNT {
|
||||||
return false;
|
return false;
|
||||||
@ -357,6 +374,7 @@ impl PacketSequenceCtrl {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn seq_count(&self) -> u16 {
|
pub fn seq_count(&self) -> u16 {
|
||||||
self.seq_count
|
self.seq_count
|
||||||
}
|
}
|
||||||
@ -398,6 +416,7 @@ pub trait CcsdsPacket {
|
|||||||
/// Retrieve data length field
|
/// Retrieve data length field
|
||||||
fn data_len(&self) -> u16;
|
fn data_len(&self) -> u16;
|
||||||
/// Retrieve the total packet size based on the data length field
|
/// Retrieve the total packet size based on the data length field
|
||||||
|
#[inline]
|
||||||
fn total_len(&self) -> usize {
|
fn total_len(&self) -> usize {
|
||||||
usize::from(self.data_len()) + CCSDS_HEADER_LEN + 1
|
usize::from(self.data_len()) + CCSDS_HEADER_LEN + 1
|
||||||
}
|
}
|
||||||
@ -489,6 +508,7 @@ pub struct SpHeader {
|
|||||||
impl Default for SpHeader {
|
impl Default for SpHeader {
|
||||||
/// The default function sets the sequence flag field to [SequenceFlags::Unsegmented]. The data
|
/// The default function sets the sequence flag field to [SequenceFlags::Unsegmented]. The data
|
||||||
/// length field is set to 1, which denotes an empty space packets.
|
/// length field is set to 1, which denotes an empty space packets.
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
SpHeader {
|
SpHeader {
|
||||||
version: 0,
|
version: 0,
|
||||||
@ -503,6 +523,7 @@ impl Default for SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SpHeader {
|
impl SpHeader {
|
||||||
|
#[inline]
|
||||||
pub const fn new(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16) -> Self {
|
pub const fn new(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
version: 0,
|
version: 0,
|
||||||
@ -516,6 +537,7 @@ impl SpHeader {
|
|||||||
/// length field is set to 1, which denotes an empty space packets.
|
/// length field is set to 1, which denotes an empty space packets.
|
||||||
///
|
///
|
||||||
/// This constructor will panic if the APID exceeds [MAX_APID].
|
/// This constructor will panic if the APID exceeds [MAX_APID].
|
||||||
|
#[inline]
|
||||||
pub const fn new_from_apid(apid: u16) -> Self {
|
pub const fn new_from_apid(apid: u16) -> Self {
|
||||||
SpHeader {
|
SpHeader {
|
||||||
version: 0,
|
version: 0,
|
||||||
@ -529,6 +551,7 @@ impl SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checked variant of [Self::new_from_apid].
|
/// Checked variant of [Self::new_from_apid].
|
||||||
|
#[inline]
|
||||||
pub fn new_from_apid_checked(apid: u16) -> Option<Self> {
|
pub fn new_from_apid_checked(apid: u16) -> Option<Self> {
|
||||||
Some(SpHeader {
|
Some(SpHeader {
|
||||||
version: 0,
|
version: 0,
|
||||||
@ -545,6 +568,7 @@ impl SpHeader {
|
|||||||
/// count exceeds [MAX_SEQ_COUNT].
|
/// count exceeds [MAX_SEQ_COUNT].
|
||||||
///
|
///
|
||||||
/// The checked constructor variants can be used to avoid panics.
|
/// The checked constructor variants can be used to avoid panics.
|
||||||
|
#[inline]
|
||||||
const fn new_from_fields(
|
const fn new_from_fields(
|
||||||
ptype: PacketType,
|
ptype: PacketType,
|
||||||
sec_header: bool,
|
sec_header: bool,
|
||||||
@ -572,6 +596,7 @@ impl SpHeader {
|
|||||||
///
|
///
|
||||||
/// This will return [None] if the APID or sequence count argument
|
/// This will return [None] if the APID or sequence count argument
|
||||||
/// exceed [MAX_APID] or [MAX_SEQ_COUNT] respectively. The version field is set to 0b000.
|
/// exceed [MAX_APID] or [MAX_SEQ_COUNT] respectively. The version field is set to 0b000.
|
||||||
|
#[inline]
|
||||||
pub fn new_from_fields_checked(
|
pub fn new_from_fields_checked(
|
||||||
ptype: PacketType,
|
ptype: PacketType,
|
||||||
sec_header: bool,
|
sec_header: bool,
|
||||||
@ -590,6 +615,7 @@ impl SpHeader {
|
|||||||
|
|
||||||
/// Helper function for telemetry space packet headers. The packet type field will be
|
/// Helper function for telemetry space packet headers. The packet type field will be
|
||||||
/// set accordingly. The secondary header flag field is set to false.
|
/// set accordingly. The secondary header flag field is set to false.
|
||||||
|
#[inline]
|
||||||
pub fn new_for_tm_checked(
|
pub fn new_for_tm_checked(
|
||||||
apid: u16,
|
apid: u16,
|
||||||
seq_flags: SequenceFlags,
|
seq_flags: SequenceFlags,
|
||||||
@ -601,6 +627,7 @@ impl SpHeader {
|
|||||||
|
|
||||||
/// Helper function for telemetry space packet headers. The packet type field will be
|
/// Helper function for telemetry space packet headers. The packet type field will be
|
||||||
/// set accordingly. The secondary header flag field is set to false.
|
/// set accordingly. The secondary header flag field is set to false.
|
||||||
|
#[inline]
|
||||||
pub fn new_for_tc_checked(
|
pub fn new_for_tc_checked(
|
||||||
apid: u16,
|
apid: u16,
|
||||||
seq_flags: SequenceFlags,
|
seq_flags: SequenceFlags,
|
||||||
@ -611,6 +638,7 @@ impl SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This is an unchecked constructor which can panic on invalid input.
|
/// This is an unchecked constructor which can panic on invalid input.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_tm(
|
pub const fn new_for_tm(
|
||||||
apid: u16,
|
apid: u16,
|
||||||
seq_flags: SequenceFlags,
|
seq_flags: SequenceFlags,
|
||||||
@ -621,6 +649,7 @@ impl SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This is an unchecked constructor which can panic on invalid input.
|
/// This is an unchecked constructor which can panic on invalid input.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_tc(
|
pub const fn new_for_tc(
|
||||||
apid: u16,
|
apid: u16,
|
||||||
seq_flags: SequenceFlags,
|
seq_flags: SequenceFlags,
|
||||||
@ -631,11 +660,13 @@ impl SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Variant of [SpHeader::new_for_tm_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
|
/// Variant of [SpHeader::new_for_tm_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
|
||||||
|
#[inline]
|
||||||
pub fn new_for_unseg_tm_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
pub fn new_for_unseg_tm_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
||||||
Self::new_for_tm_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
Self::new_for_tm_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Variant of [SpHeader::new_for_tc_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
|
/// Variant of [SpHeader::new_for_tc_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
|
||||||
|
#[inline]
|
||||||
pub fn new_for_unseg_tc_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
pub fn new_for_unseg_tc_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
||||||
Self::new_for_tc_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
Self::new_for_tc_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||||
}
|
}
|
||||||
@ -643,6 +674,7 @@ impl SpHeader {
|
|||||||
/// Variant of [SpHeader::new_for_tc] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
/// Variant of [SpHeader::new_for_tc] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
||||||
///
|
///
|
||||||
/// This is an unchecked constructor which can panic on invalid input.
|
/// This is an unchecked constructor which can panic on invalid input.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_unseg_tc(apid: u16, seq_count: u16, data_len: u16) -> Self {
|
pub const fn new_for_unseg_tc(apid: u16, seq_count: u16, data_len: u16) -> Self {
|
||||||
Self::new_for_tc(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
Self::new_for_tc(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||||
}
|
}
|
||||||
@ -650,6 +682,7 @@ impl SpHeader {
|
|||||||
/// Variant of [SpHeader::new_for_tm] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
/// Variant of [SpHeader::new_for_tm] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
||||||
///
|
///
|
||||||
/// This is an unchecked constructor which can panic on invalid input.
|
/// This is an unchecked constructor which can panic on invalid input.
|
||||||
|
#[inline]
|
||||||
pub const fn new_for_unseg_tm(apid: u16, seq_count: u16, data_len: u16) -> Self {
|
pub const fn new_for_unseg_tm(apid: u16, seq_count: u16, data_len: u16) -> Self {
|
||||||
Self::new_for_tm(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
Self::new_for_tm(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||||
}
|
}
|
||||||
@ -657,6 +690,7 @@ impl SpHeader {
|
|||||||
delegate! {
|
delegate! {
|
||||||
to self.packet_id {
|
to self.packet_id {
|
||||||
/// Returns [false] and fails if the APID exceeds [MAX_APID]
|
/// Returns [false] and fails if the APID exceeds [MAX_APID]
|
||||||
|
#[inline]
|
||||||
pub fn set_apid(&mut self, apid: u16) -> bool;
|
pub fn set_apid(&mut self, apid: u16) -> bool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,22 +698,27 @@ impl SpHeader {
|
|||||||
delegate! {
|
delegate! {
|
||||||
to self.psc {
|
to self.psc {
|
||||||
/// Returns [false] and fails if the sequence count exceeds [MAX_SEQ_COUNT]
|
/// Returns [false] and fails if the sequence count exceeds [MAX_SEQ_COUNT]
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
|
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
|
pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
|
||||||
self.psc.seq_flags = seq_flags;
|
self.psc.seq_flags = seq_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_sec_header_flag(&mut self) {
|
pub fn set_sec_header_flag(&mut self) {
|
||||||
self.packet_id.sec_header_flag = true;
|
self.packet_id.sec_header_flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn clear_sec_header_flag(&mut self) {
|
pub fn clear_sec_header_flag(&mut self) {
|
||||||
self.packet_id.sec_header_flag = false;
|
self.packet_id.sec_header_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_packet_type(&mut self, packet_type: PacketType) {
|
pub fn set_packet_type(&mut self, packet_type: PacketType) {
|
||||||
self.packet_id.ptype = packet_type;
|
self.packet_id.ptype = packet_type;
|
||||||
}
|
}
|
||||||
@ -742,6 +781,7 @@ impl CcsdsPacket for SpHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPrimaryHeader for SpHeader {
|
impl CcsdsPrimaryHeader for SpHeader {
|
||||||
|
#[inline]
|
||||||
fn from_composite_fields(
|
fn from_composite_fields(
|
||||||
packet_id: PacketId,
|
packet_id: PacketId,
|
||||||
psc: PacketSequenceCtrl,
|
psc: PacketSequenceCtrl,
|
||||||
@ -809,9 +849,12 @@ pub mod zc {
|
|||||||
((self.version_packet_id.get() >> 13) as u8) & 0b111
|
((self.version_packet_id.get() >> 13) as u8) & 0b111
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn packet_id(&self) -> PacketId {
|
fn packet_id(&self) -> PacketId {
|
||||||
PacketId::from(self.packet_id_raw())
|
PacketId::from(self.packet_id_raw())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn psc(&self) -> PacketSequenceCtrl {
|
fn psc(&self) -> PacketSequenceCtrl {
|
||||||
PacketSequenceCtrl::from(self.psc_raw())
|
PacketSequenceCtrl::from(self.psc_raw())
|
||||||
}
|
}
|
||||||
@ -821,10 +864,12 @@ pub mod zc {
|
|||||||
self.data_len.get()
|
self.data_len.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn packet_id_raw(&self) -> u16 {
|
fn packet_id_raw(&self) -> u16 {
|
||||||
self.version_packet_id.get() & (!VERSION_MASK)
|
self.version_packet_id.get() & (!VERSION_MASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn psc_raw(&self) -> u16 {
|
fn psc_raw(&self) -> u16 {
|
||||||
self.psc.get()
|
self.psc.get()
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,7 @@ pub fn length_of_day_segment_from_pfield(pfield: u8) -> LengthOfDaySegment {
|
|||||||
LengthOfDaySegment::Short16Bits
|
LengthOfDaySegment::Short16Bits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn precision_from_pfield(pfield: u8) -> SubmillisPrecision {
|
pub fn precision_from_pfield(pfield: u8) -> SubmillisPrecision {
|
||||||
match pfield & 0b11 {
|
match pfield & 0b11 {
|
||||||
0b01 => SubmillisPrecision::Microseconds,
|
0b01 => SubmillisPrecision::Microseconds,
|
||||||
@ -272,24 +273,29 @@ impl ConversionFromUnix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CdsCommon for ConversionFromUnix {
|
impl CdsCommon for ConversionFromUnix {
|
||||||
|
#[inline]
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
self.submilis_prec
|
self.submilis_prec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ms_of_day(&self) -> u32 {
|
fn ms_of_day(&self) -> u32 {
|
||||||
self.ms_of_day
|
self.ms_of_day
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ccsds_days_as_u32(&self) -> u32 {
|
fn ccsds_days_as_u32(&self) -> u32 {
|
||||||
self.ccsds_days
|
self.ccsds_days
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn submillis(&self) -> u32 {
|
fn submillis(&self) -> u32 {
|
||||||
self.submillis
|
self.submillis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CdsConverter for ConversionFromUnix {
|
impl CdsConverter for ConversionFromUnix {
|
||||||
|
#[inline]
|
||||||
fn unix_days_seconds(&self) -> i64 {
|
fn unix_days_seconds(&self) -> i64 {
|
||||||
self.unix_days_seconds
|
self.unix_days_seconds
|
||||||
}
|
}
|
||||||
@ -302,24 +308,31 @@ struct ConversionFromChronoDatetime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CdsCommon for ConversionFromChronoDatetime {
|
impl CdsCommon for ConversionFromChronoDatetime {
|
||||||
|
#[inline]
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
self.submillis_prec
|
self.submillis_prec
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate! {
|
delegate! {
|
||||||
to self.unix_conversion {
|
to self.unix_conversion {
|
||||||
|
#[inline]
|
||||||
fn ms_of_day(&self) -> u32;
|
fn ms_of_day(&self) -> u32;
|
||||||
|
#[inline]
|
||||||
fn ccsds_days_as_u32(&self) -> u32;
|
fn ccsds_days_as_u32(&self) -> u32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn submillis(&self) -> u32 {
|
fn submillis(&self) -> u32 {
|
||||||
self.submillis
|
self.submillis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CdsConverter for ConversionFromChronoDatetime {
|
impl CdsConverter for ConversionFromChronoDatetime {
|
||||||
delegate! {to self.unix_conversion { fn unix_days_seconds(&self) -> i64; }}
|
delegate! {to self.unix_conversion {
|
||||||
|
#[inline]
|
||||||
|
fn unix_days_seconds(&self) -> i64;
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -177,6 +177,7 @@ pub struct FractionalPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FractionalPart {
|
impl FractionalPart {
|
||||||
|
#[inline]
|
||||||
pub const fn new(resolution: FractionalResolution, counter: u32) -> Self {
|
pub const fn new(resolution: FractionalResolution, counter: u32) -> Self {
|
||||||
let div = fractional_res_to_div(resolution);
|
let div = fractional_res_to_div(resolution);
|
||||||
assert!(counter <= div, "invalid counter for resolution");
|
assert!(counter <= div, "invalid counter for resolution");
|
||||||
@ -187,15 +188,18 @@ impl FractionalPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An empty fractional part for second resolution only.
|
/// An empty fractional part for second resolution only.
|
||||||
|
#[inline]
|
||||||
pub const fn new_with_seconds_resolution() -> Self {
|
pub const fn new_with_seconds_resolution() -> Self {
|
||||||
Self::new(FractionalResolution::Seconds, 0)
|
Self::new(FractionalResolution::Seconds, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method which simply calls [Self::new_with_seconds_resolution].
|
/// Helper method which simply calls [Self::new_with_seconds_resolution].
|
||||||
|
#[inline]
|
||||||
pub const fn new_empty() -> Self {
|
pub const fn new_empty() -> Self {
|
||||||
Self::new_with_seconds_resolution()
|
Self::new_with_seconds_resolution()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_checked(resolution: FractionalResolution, counter: u32) -> Option<Self> {
|
pub fn new_checked(resolution: FractionalResolution, counter: u32) -> Option<Self> {
|
||||||
let div = fractional_res_to_div(resolution);
|
let div = fractional_res_to_div(resolution);
|
||||||
if counter > div {
|
if counter > div {
|
||||||
@ -207,14 +211,17 @@ impl FractionalPart {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn resolution(&self) -> FractionalResolution {
|
pub fn resolution(&self) -> FractionalResolution {
|
||||||
self.resolution
|
self.resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn counter(&self) -> u32 {
|
pub fn counter(&self) -> u32 {
|
||||||
self.counter
|
self.counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn no_fractional_part(&self) -> bool {
|
pub fn no_fractional_part(&self) -> bool {
|
||||||
self.resolution == FractionalResolution::Seconds
|
self.resolution == FractionalResolution::Seconds
|
||||||
}
|
}
|
||||||
@ -285,6 +292,7 @@ pub struct CucTimeWithLeapSecs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CucTimeWithLeapSecs {
|
impl CucTimeWithLeapSecs {
|
||||||
|
#[inline]
|
||||||
pub fn new(time: CucTime, leap_seconds: u32) -> Self {
|
pub fn new(time: CucTime, leap_seconds: u32) -> Self {
|
||||||
Self { time, leap_seconds }
|
Self { time, leap_seconds }
|
||||||
}
|
}
|
||||||
@ -300,6 +308,7 @@ pub fn pfield_len(pfield: u8) -> usize {
|
|||||||
|
|
||||||
impl CucTime {
|
impl CucTime {
|
||||||
/// Create a time provider with a four byte counter and no fractional part.
|
/// Create a time provider with a four byte counter and no fractional part.
|
||||||
|
#[inline]
|
||||||
pub fn new(counter: u32) -> Self {
|
pub fn new(counter: u32) -> Self {
|
||||||
// These values are definitely valid, so it is okay to unwrap here.
|
// These values are definitely valid, so it is okay to unwrap here.
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
@ -310,11 +319,13 @@ impl CucTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Like [CucTime::new] but allow to supply a fractional part as well.
|
/// Like [CucTime::new] but allow to supply a fractional part as well.
|
||||||
|
#[inline]
|
||||||
pub fn new_with_fractions(counter: u32, fractions: FractionalPart) -> Result<Self, CucError> {
|
pub fn new_with_fractions(counter: u32, fractions: FractionalPart) -> Result<Self, CucError> {
|
||||||
Self::new_generic(WidthCounterPair(4, counter), fractions)
|
Self::new_generic(WidthCounterPair(4, counter), fractions)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fractions with a resolution of ~ 4 ms
|
/// Fractions with a resolution of ~ 4 ms
|
||||||
|
#[inline]
|
||||||
pub fn new_with_coarse_fractions(counter: u32, subsec_fractions: u8) -> Self {
|
pub fn new_with_coarse_fractions(counter: u32, subsec_fractions: u8) -> Self {
|
||||||
// These values are definitely valid, so it is okay to unwrap here.
|
// These values are definitely valid, so it is okay to unwrap here.
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
@ -328,6 +339,7 @@ impl CucTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fractions with a resolution of ~ 16 us
|
/// Fractions with a resolution of ~ 16 us
|
||||||
|
#[inline]
|
||||||
pub fn new_with_medium_fractions(counter: u32, subsec_fractions: u16) -> Self {
|
pub fn new_with_medium_fractions(counter: u32, subsec_fractions: u16) -> Self {
|
||||||
// These values are definitely valid, so it is okay to unwrap here.
|
// These values are definitely valid, so it is okay to unwrap here.
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
@ -343,6 +355,7 @@ impl CucTime {
|
|||||||
/// Fractions with a resolution of ~ 60 ns. The fractional part value is limited by the
|
/// Fractions with a resolution of ~ 60 ns. The fractional part value is limited by the
|
||||||
/// 24 bits of the fractional field, so this function will fail with
|
/// 24 bits of the fractional field, so this function will fail with
|
||||||
/// [CucError::InvalidFractions] if the fractional value exceeds the value.
|
/// [CucError::InvalidFractions] if the fractional value exceeds the value.
|
||||||
|
#[inline]
|
||||||
pub fn new_with_fine_fractions(counter: u32, subsec_fractions: u32) -> Result<Self, CucError> {
|
pub fn new_with_fine_fractions(counter: u32, subsec_fractions: u32) -> Result<Self, CucError> {
|
||||||
Self::new_generic(
|
Self::new_generic(
|
||||||
WidthCounterPair(4, counter),
|
WidthCounterPair(4, counter),
|
||||||
@ -457,6 +470,7 @@ impl CucTime {
|
|||||||
|
|
||||||
/// Most generic constructor which allows full configurability for the counter and for the
|
/// Most generic constructor which allows full configurability for the counter and for the
|
||||||
/// fractions.
|
/// fractions.
|
||||||
|
#[inline]
|
||||||
pub fn new_generic(
|
pub fn new_generic(
|
||||||
width_and_counter: WidthCounterPair,
|
width_and_counter: WidthCounterPair,
|
||||||
fractions: FractionalPart,
|
fractions: FractionalPart,
|
||||||
@ -476,31 +490,38 @@ impl CucTime {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn ccsds_time_code(&self) -> CcsdsTimeCode {
|
pub fn ccsds_time_code(&self) -> CcsdsTimeCode {
|
||||||
CcsdsTimeCode::CucCcsdsEpoch
|
CcsdsTimeCode::CucCcsdsEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn width_counter_pair(&self) -> WidthCounterPair {
|
pub fn width_counter_pair(&self) -> WidthCounterPair {
|
||||||
self.counter
|
self.counter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn counter_width(&self) -> u8 {
|
pub fn counter_width(&self) -> u8 {
|
||||||
self.counter.0
|
self.counter.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn counter(&self) -> u32 {
|
pub fn counter(&self) -> u32 {
|
||||||
self.counter.1
|
self.counter.1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subsecond fractional part of the CUC time.
|
/// Subsecond fractional part of the CUC time.
|
||||||
|
#[inline]
|
||||||
pub fn fractions(&self) -> FractionalPart {
|
pub fn fractions(&self) -> FractionalPart {
|
||||||
self.fractions
|
self.fractions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn to_leap_sec_helper(&self, leap_seconds: u32) -> CucTimeWithLeapSecs {
|
pub fn to_leap_sec_helper(&self, leap_seconds: u32) -> CucTimeWithLeapSecs {
|
||||||
CucTimeWithLeapSecs::new(*self, leap_seconds)
|
CucTimeWithLeapSecs::new(*self, leap_seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn set_fractions(&mut self, fractions: FractionalPart) -> Result<(), CucError> {
|
pub fn set_fractions(&mut self, fractions: FractionalPart) -> Result<(), CucError> {
|
||||||
Self::verify_fractions_value(fractions)?;
|
Self::verify_fractions_value(fractions)?;
|
||||||
self.fractions = fractions;
|
self.fractions = fractions;
|
||||||
@ -510,6 +531,7 @@ impl CucTime {
|
|||||||
|
|
||||||
/// Set a fractional resolution. Please note that this function will reset the fractional value
|
/// Set a fractional resolution. Please note that this function will reset the fractional value
|
||||||
/// to 0 if the resolution changes.
|
/// to 0 if the resolution changes.
|
||||||
|
#[inline]
|
||||||
pub fn set_fractional_resolution(&mut self, res: FractionalResolution) {
|
pub fn set_fractional_resolution(&mut self, res: FractionalResolution) {
|
||||||
if res == FractionalResolution::Seconds {
|
if res == FractionalResolution::Seconds {
|
||||||
self.fractions = FractionalPart::new_with_seconds_resolution();
|
self.fractions = FractionalPart::new_with_seconds_resolution();
|
||||||
@ -519,6 +541,7 @@ impl CucTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn build_p_field(counter_width: u8, resolution: FractionalResolution) -> u8 {
|
fn build_p_field(counter_width: u8, resolution: FractionalResolution) -> u8 {
|
||||||
let mut pfield = P_FIELD_BASE;
|
let mut pfield = P_FIELD_BASE;
|
||||||
if !(1..=4).contains(&counter_width) {
|
if !(1..=4).contains(&counter_width) {
|
||||||
@ -538,6 +561,7 @@ impl CucTime {
|
|||||||
pfield
|
pfield
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn update_p_field_fractions(&mut self) {
|
fn update_p_field_fractions(&mut self) {
|
||||||
self.pfield &= !(0b11);
|
self.pfield &= !(0b11);
|
||||||
self.pfield |= self.fractions.resolution() as u8;
|
self.pfield |= self.fractions.resolution() as u8;
|
||||||
@ -582,6 +606,7 @@ impl CucTime {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn len_packed_from_pfield(pfield: u8) -> usize {
|
pub fn len_packed_from_pfield(pfield: u8) -> usize {
|
||||||
let mut base_len: usize = 1;
|
let mut base_len: usize = 1;
|
||||||
base_len += Self::len_cntr_from_pfield(pfield) as usize;
|
base_len += Self::len_cntr_from_pfield(pfield) as usize;
|
||||||
@ -590,6 +615,7 @@ impl CucTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies the raw width parameter.
|
/// Verifies the raw width parameter.
|
||||||
|
#[inline]
|
||||||
fn verify_counter_width(width: u8) -> Result<(), CucError> {
|
fn verify_counter_width(width: u8) -> Result<(), CucError> {
|
||||||
if width == 0 || width > 4 {
|
if width == 0 || width > 4 {
|
||||||
return Err(CucError::InvalidCounterWidth(width));
|
return Err(CucError::InvalidCounterWidth(width));
|
||||||
@ -597,6 +623,7 @@ impl CucTime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn verify_fractions_value(val: FractionalPart) -> Result<(), CucError> {
|
fn verify_fractions_value(val: FractionalPart) -> Result<(), CucError> {
|
||||||
if val.counter > 2u32.pow((val.resolution as u32) * 8) - 1 {
|
if val.counter > 2u32.pow((val.resolution as u32) * 8) - 1 {
|
||||||
return Err(CucError::InvalidFractions {
|
return Err(CucError::InvalidFractions {
|
||||||
@ -607,10 +634,12 @@ impl CucTime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn len_as_bytes(&self) -> usize {
|
fn len_as_bytes(&self) -> usize {
|
||||||
Self::len_packed_from_pfield(self.pfield)
|
Self::len_packed_from_pfield(self.pfield)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subsec_nanos(&self) -> u32 {
|
fn subsec_nanos(&self) -> u32 {
|
||||||
if self.fractions.resolution() == FractionalResolution::Seconds {
|
if self.fractions.resolution() == FractionalResolution::Seconds {
|
||||||
return 0;
|
return 0;
|
||||||
@ -751,22 +780,27 @@ impl TimeWriter for CucTime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsTimeProvider for CucTimeWithLeapSecs {
|
impl CcsdsTimeProvider for CucTimeWithLeapSecs {
|
||||||
|
#[inline]
|
||||||
fn len_as_bytes(&self) -> usize {
|
fn len_as_bytes(&self) -> usize {
|
||||||
self.time.len_as_bytes()
|
self.time.len_as_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn p_field(&self) -> (usize, [u8; 2]) {
|
fn p_field(&self) -> (usize, [u8; 2]) {
|
||||||
(1, [self.time.pfield, 0])
|
(1, [self.time.pfield, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ccdsd_time_code(&self) -> CcsdsTimeCode {
|
fn ccdsd_time_code(&self) -> CcsdsTimeCode {
|
||||||
self.time.ccsds_time_code()
|
self.time.ccsds_time_code()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn unix_secs(&self) -> i64 {
|
fn unix_secs(&self) -> i64 {
|
||||||
self.time.unix_secs(self.leap_seconds)
|
self.time.unix_secs(self.leap_seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn subsec_nanos(&self) -> u32 {
|
fn subsec_nanos(&self) -> u32 {
|
||||||
self.time.subsec_nanos()
|
self.time.subsec_nanos()
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,7 @@ pub fn seconds_since_epoch() -> f64 {
|
|||||||
///
|
///
|
||||||
/// - CCSDS epoch: 1958-01-01T00:00:00+00:00
|
/// - CCSDS epoch: 1958-01-01T00:00:00+00:00
|
||||||
/// - UNIX Epoch: 1970-01-01T00:00:00+00:00
|
/// - UNIX Epoch: 1970-01-01T00:00:00+00:00
|
||||||
|
#[inline]
|
||||||
pub const fn unix_to_ccsds_days(unix_days: i64) -> i64 {
|
pub const fn unix_to_ccsds_days(unix_days: i64) -> i64 {
|
||||||
unix_days - DAYS_CCSDS_TO_UNIX as i64
|
unix_days - DAYS_CCSDS_TO_UNIX as i64
|
||||||
}
|
}
|
||||||
@ -174,16 +175,19 @@ pub const fn unix_to_ccsds_days(unix_days: i64) -> i64 {
|
|||||||
///
|
///
|
||||||
/// - CCSDS epoch: 1958-01-01T00:00:00+00:00
|
/// - CCSDS epoch: 1958-01-01T00:00:00+00:00
|
||||||
/// - UNIX Epoch: 1970-01-01T00:00:00+00:00
|
/// - UNIX Epoch: 1970-01-01T00:00:00+00:00
|
||||||
|
#[inline]
|
||||||
pub const fn ccsds_to_unix_days(ccsds_days: i64) -> i64 {
|
pub const fn ccsds_to_unix_days(ccsds_days: i64) -> i64 {
|
||||||
ccsds_days + DAYS_CCSDS_TO_UNIX as i64
|
ccsds_days + DAYS_CCSDS_TO_UNIX as i64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Similar to [unix_to_ccsds_days] but converts the epoch instead, which is the number of elpased
|
/// Similar to [unix_to_ccsds_days] but converts the epoch instead, which is the number of elpased
|
||||||
/// seconds since the CCSDS and UNIX epoch times.
|
/// seconds since the CCSDS and UNIX epoch times.
|
||||||
|
#[inline]
|
||||||
pub const fn unix_epoch_to_ccsds_epoch(unix_epoch: i64) -> i64 {
|
pub const fn unix_epoch_to_ccsds_epoch(unix_epoch: i64) -> i64 {
|
||||||
unix_epoch - (DAYS_CCSDS_TO_UNIX as i64 * SECONDS_PER_DAY as i64)
|
unix_epoch - (DAYS_CCSDS_TO_UNIX as i64 * SECONDS_PER_DAY as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub const fn ccsds_epoch_to_unix_epoch(ccsds_epoch: i64) -> i64 {
|
pub const fn ccsds_epoch_to_unix_epoch(ccsds_epoch: i64) -> i64 {
|
||||||
ccsds_epoch + (DAYS_CCSDS_TO_UNIX as i64 * SECONDS_PER_DAY as i64)
|
ccsds_epoch + (DAYS_CCSDS_TO_UNIX as i64 * SECONDS_PER_DAY as i64)
|
||||||
}
|
}
|
||||||
|
29
src/util.rs
29
src/util.rs
@ -15,10 +15,12 @@ pub trait ToBeBytes {
|
|||||||
impl ToBeBytes for () {
|
impl ToBeBytes for () {
|
||||||
type ByteArray = [u8; 0];
|
type ByteArray = [u8; 0];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn written_len(&self) -> usize {
|
fn written_len(&self) -> usize {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn to_be_bytes(&self) -> Self::ByteArray {
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
[]
|
[]
|
||||||
}
|
}
|
||||||
@ -27,9 +29,12 @@ impl ToBeBytes for () {
|
|||||||
impl ToBeBytes for u8 {
|
impl ToBeBytes for u8 {
|
||||||
type ByteArray = [u8; 1];
|
type ByteArray = [u8; 1];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn written_len(&self) -> usize {
|
fn written_len(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn to_be_bytes(&self) -> Self::ByteArray {
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
u8::to_be_bytes(*self)
|
u8::to_be_bytes(*self)
|
||||||
}
|
}
|
||||||
@ -38,9 +43,12 @@ impl ToBeBytes for u8 {
|
|||||||
impl ToBeBytes for u16 {
|
impl ToBeBytes for u16 {
|
||||||
type ByteArray = [u8; 2];
|
type ByteArray = [u8; 2];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn written_len(&self) -> usize {
|
fn written_len(&self) -> usize {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn to_be_bytes(&self) -> Self::ByteArray {
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
u16::to_be_bytes(*self)
|
u16::to_be_bytes(*self)
|
||||||
}
|
}
|
||||||
@ -49,9 +57,12 @@ impl ToBeBytes for u16 {
|
|||||||
impl ToBeBytes for u32 {
|
impl ToBeBytes for u32 {
|
||||||
type ByteArray = [u8; 4];
|
type ByteArray = [u8; 4];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn written_len(&self) -> usize {
|
fn written_len(&self) -> usize {
|
||||||
4
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn to_be_bytes(&self) -> Self::ByteArray {
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
u32::to_be_bytes(*self)
|
u32::to_be_bytes(*self)
|
||||||
}
|
}
|
||||||
@ -60,9 +71,12 @@ impl ToBeBytes for u32 {
|
|||||||
impl ToBeBytes for u64 {
|
impl ToBeBytes for u64 {
|
||||||
type ByteArray = [u8; 8];
|
type ByteArray = [u8; 8];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn written_len(&self) -> usize {
|
fn written_len(&self) -> usize {
|
||||||
8
|
8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn to_be_bytes(&self) -> Self::ByteArray {
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
u64::to_be_bytes(*self)
|
u64::to_be_bytes(*self)
|
||||||
}
|
}
|
||||||
@ -104,6 +118,7 @@ pub enum UnsignedByteFieldError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<ByteConversionError> for UnsignedByteFieldError {
|
impl From<ByteConversionError> for UnsignedByteFieldError {
|
||||||
|
#[inline]
|
||||||
fn from(value: ByteConversionError) -> Self {
|
fn from(value: ByteConversionError) -> Self {
|
||||||
Self::ByteConversionError(value)
|
Self::ByteConversionError(value)
|
||||||
}
|
}
|
||||||
@ -138,14 +153,17 @@ pub struct UnsignedByteField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UnsignedByteField {
|
impl UnsignedByteField {
|
||||||
|
#[inline]
|
||||||
pub const fn new(width: usize, value: u64) -> Self {
|
pub const fn new(width: usize, value: u64) -> Self {
|
||||||
Self { width, value }
|
Self { width, value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub const fn value_const(&self) -> u64 {
|
pub const fn value_const(&self) -> u64 {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> {
|
pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> {
|
||||||
if width > buf.len() {
|
if width > buf.len() {
|
||||||
return Err(ByteConversionError::FromSliceTooSmall {
|
return Err(ByteConversionError::FromSliceTooSmall {
|
||||||
@ -178,10 +196,12 @@ impl UnsignedByteField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UnsignedEnum for UnsignedByteField {
|
impl UnsignedEnum for UnsignedByteField {
|
||||||
|
#[inline]
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn value(&self) -> u64 {
|
fn value(&self) -> u64 {
|
||||||
self.value_const()
|
self.value_const()
|
||||||
}
|
}
|
||||||
@ -237,6 +257,7 @@ impl<TYPE: Copy + Into<u64>> GenericUnsignedByteField<TYPE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteField<TYPE> {
|
impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteField<TYPE> {
|
||||||
|
#[inline]
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.value.written_len()
|
self.value.written_len()
|
||||||
}
|
}
|
||||||
@ -252,6 +273,7 @@ impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteFie
|
|||||||
Ok(self.value.written_len())
|
Ok(self.value.written_len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn value(&self) -> u64 {
|
fn value(&self) -> u64 {
|
||||||
self.value_typed().into()
|
self.value_typed().into()
|
||||||
}
|
}
|
||||||
@ -277,6 +299,7 @@ impl From<UnsignedByteFieldU8> for UnsignedByteField {
|
|||||||
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
|
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
|
||||||
type Error = UnsignedByteFieldError;
|
type Error = UnsignedByteFieldError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
||||||
if value.width != 1 {
|
if value.width != 1 {
|
||||||
return Err(UnsignedByteFieldError::InvalidWidth {
|
return Err(UnsignedByteFieldError::InvalidWidth {
|
||||||
@ -289,6 +312,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<UnsignedByteFieldU16> for UnsignedByteField {
|
impl From<UnsignedByteFieldU16> for UnsignedByteField {
|
||||||
|
#[inline]
|
||||||
fn from(value: UnsignedByteFieldU16) -> Self {
|
fn from(value: UnsignedByteFieldU16) -> Self {
|
||||||
Self::new(2, value.value as u64)
|
Self::new(2, value.value as u64)
|
||||||
}
|
}
|
||||||
@ -297,6 +321,7 @@ impl From<UnsignedByteFieldU16> for UnsignedByteField {
|
|||||||
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
|
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
|
||||||
type Error = UnsignedByteFieldError;
|
type Error = UnsignedByteFieldError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
||||||
if value.width != 2 {
|
if value.width != 2 {
|
||||||
return Err(UnsignedByteFieldError::InvalidWidth {
|
return Err(UnsignedByteFieldError::InvalidWidth {
|
||||||
@ -309,6 +334,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<UnsignedByteFieldU32> for UnsignedByteField {
|
impl From<UnsignedByteFieldU32> for UnsignedByteField {
|
||||||
|
#[inline]
|
||||||
fn from(value: UnsignedByteFieldU32) -> Self {
|
fn from(value: UnsignedByteFieldU32) -> Self {
|
||||||
Self::new(4, value.value as u64)
|
Self::new(4, value.value as u64)
|
||||||
}
|
}
|
||||||
@ -317,6 +343,7 @@ impl From<UnsignedByteFieldU32> for UnsignedByteField {
|
|||||||
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
|
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
|
||||||
type Error = UnsignedByteFieldError;
|
type Error = UnsignedByteFieldError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
||||||
if value.width != 4 {
|
if value.width != 4 {
|
||||||
return Err(UnsignedByteFieldError::InvalidWidth {
|
return Err(UnsignedByteFieldError::InvalidWidth {
|
||||||
@ -329,6 +356,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<UnsignedByteFieldU64> for UnsignedByteField {
|
impl From<UnsignedByteFieldU64> for UnsignedByteField {
|
||||||
|
#[inline]
|
||||||
fn from(value: UnsignedByteFieldU64) -> Self {
|
fn from(value: UnsignedByteFieldU64) -> Self {
|
||||||
Self::new(8, value.value)
|
Self::new(8, value.value)
|
||||||
}
|
}
|
||||||
@ -337,6 +365,7 @@ impl From<UnsignedByteFieldU64> for UnsignedByteField {
|
|||||||
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU64 {
|
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU64 {
|
||||||
type Error = UnsignedByteFieldError;
|
type Error = UnsignedByteFieldError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
|
||||||
if value.width != 8 {
|
if value.width != 8 {
|
||||||
return Err(UnsignedByteFieldError::InvalidWidth {
|
return Err(UnsignedByteFieldError::InvalidWidth {
|
||||||
|
Loading…
Reference in New Issue
Block a user