added additional ctors which only set the APID #80

Merged
muellerr merged 2 commits from addition-sp-header-ctors into main 2024-04-03 22:59:19 +02:00
12 changed files with 325 additions and 1 deletions

View File

@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
to `new_for_tc_checked`, `new_for_tm_checked`, `new_for_unseg_tc_checked` and
`new_for_unseg_tm_checked`.
## Added
- `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
Major API changes for the time API. If you are using the time API, it is strongly recommended

View File

@ -62,6 +62,7 @@ pub(crate) fn generic_len_check_deserialization(
}
impl<'data> Lv<'data> {
#[inline]
pub fn new(data: &[u8]) -> Result<Lv, TlvLvError> {
if data.len() > u8::MAX as usize {
return Err(TlvLvError::DataTooLarge(data.len()));
@ -73,6 +74,7 @@ impl<'data> Lv<'data> {
}
/// Creates a LV with an empty value field.
#[inline]
pub fn new_empty() -> Lv<'data> {
Lv {
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
/// path LVs
#[inline]
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvError> {
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
/// path LVs
#[cfg(feature = "std")]
#[inline]
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvError> {
Self::new(string.as_bytes())
}
/// Returns the length of the value part, not including the length byte.
#[inline]
pub fn len_value(&self) -> usize {
self.data.len()
}
/// Returns the full raw length, including the length byte.
#[inline]
pub fn len_full(&self) -> usize {
self.len_value() + 1
}
/// Checks whether the value field is empty.
#[inline]
pub fn is_empty(&self) -> bool {
self.data.len() == 0
}
#[inline]
pub fn value(&self) -> &[u8] {
self.data
}
/// 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.
#[inline]
pub fn raw_data(&self) -> Option<&[u8]> {
self.raw_data
}
/// 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.
#[inline]
pub fn value_as_str(&self) -> Option<Result<&'data str, Utf8Error>> {
if self.is_empty() {
return None;
@ -135,6 +145,7 @@ impl<'data> Lv<'data> {
}
/// Reads a LV from a raw buffer.
#[inline]
pub fn from_bytes(buf: &'data [u8]) -> Result<Lv<'data>, ByteConversionError> {
generic_len_check_deserialization(buf, MIN_LV_LEN)?;
Self::from_be_bytes_no_len_check(buf)
@ -151,6 +162,7 @@ impl<'data> Lv<'data> {
MIN_LV_LEN + self.data.len()
}
#[inline]
pub(crate) fn from_be_bytes_no_len_check(
buf: &'data [u8],
) -> Result<Lv<'data>, ByteConversionError> {

View File

@ -150,12 +150,14 @@ impl Error for PduError {
}
impl From<ByteConversionError> for PduError {
#[inline]
fn from(value: ByteConversionError) -> Self {
Self::ByteConversion(value)
}
}
impl From<TlvLvError> for PduError {
#[inline]
fn from(e: TlvLvError) -> Self {
Self::TlvLvError(e)
}
@ -179,33 +181,42 @@ pub trait WritablePduPacket {
pub trait CfdpPdu {
fn pdu_header(&self) -> &PduHeader;
#[inline]
fn source_id(&self) -> UnsignedByteField {
self.pdu_header().common_pdu_conf().source_entity_id
}
#[inline]
fn dest_id(&self) -> UnsignedByteField {
self.pdu_header().common_pdu_conf().dest_entity_id
}
#[inline]
fn transaction_seq_num(&self) -> UnsignedByteField {
self.pdu_header().common_pdu_conf().transaction_seq_num
}
#[inline]
fn transmission_mode(&self) -> TransmissionMode {
self.pdu_header().common_pdu_conf().trans_mode
}
#[inline]
fn direction(&self) -> Direction {
self.pdu_header().common_pdu_conf().direction
}
#[inline]
fn crc_flag(&self) -> CrcFlag {
self.pdu_header().common_pdu_conf().crc_flag
}
#[inline]
fn file_flag(&self) -> LargeFileFlag {
self.pdu_header().common_pdu_conf().file_flag
}
#[inline]
fn pdu_type(&self) -> PduType {
self.pdu_header().pdu_type()
}
@ -234,6 +245,7 @@ pub struct CommonPduConfig {
// TODO: Builder pattern might be applicable here..
impl CommonPduConfig {
#[inline]
pub fn new(
source_id: impl Into<UnsignedByteField>,
dest_id: impl Into<UnsignedByteField>,
@ -265,6 +277,7 @@ impl CommonPduConfig {
})
}
#[inline]
pub fn new_with_byte_fields(
source_id: impl Into<UnsignedByteField>,
dest_id: impl Into<UnsignedByteField>,
@ -281,10 +294,12 @@ impl CommonPduConfig {
)
}
#[inline]
pub fn source_id(&self) -> UnsignedByteField {
self.source_entity_id
}
#[inline]
fn source_dest_id_check(
source_id: impl Into<UnsignedByteField>,
dest_id: impl Into<UnsignedByteField>,
@ -307,6 +322,7 @@ impl CommonPduConfig {
Ok((source_id, dest_id))
}
#[inline]
pub fn set_source_and_dest_id(
&mut self,
source_id: impl Into<UnsignedByteField>,
@ -318,6 +334,7 @@ impl CommonPduConfig {
Ok(())
}
#[inline]
pub fn dest_id(&self) -> UnsignedByteField {
self.dest_entity_id
}
@ -326,6 +343,7 @@ impl CommonPduConfig {
impl Default for CommonPduConfig {
/// The defaults for the source ID, destination ID and the transaction sequence number is the
/// [UnsignedByteFieldU8] with an intitial value of 0
#[inline]
fn default() -> Self {
// The new function can not fail for these input parameters.
Self::new(
@ -342,6 +360,7 @@ impl Default for CommonPduConfig {
}
impl PartialEq for CommonPduConfig {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.source_entity_id.value() == other.source_entity_id.value()
&& self.dest_entity_id.value() == other.dest_entity_id.value()
@ -370,6 +389,7 @@ pub struct PduHeader {
}
impl PduHeader {
#[inline]
pub fn new_for_file_data(
pdu_conf: CommonPduConfig,
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 {
Self::new_generic(
PduType::FileData,
@ -394,6 +415,7 @@ impl PduHeader {
SegmentationControl::NoRecordBoundaryPreservation,
)
}
#[inline]
pub fn new_no_file_data(pdu_conf: CommonPduConfig, pdu_datafield_len: u16) -> Self {
Self::new_generic(
PduType::FileDirective,
@ -404,6 +426,7 @@ impl PduHeader {
)
}
#[inline]
pub fn new_generic(
pdu_type: PduType,
pdu_conf: CommonPduConfig,
@ -421,6 +444,7 @@ impl PduHeader {
}
/// Returns only the length of the PDU header when written to a raw buffer.
#[inline]
pub fn header_len(&self) -> usize {
FIXED_HEADER_LEN
+ self.pdu_conf.source_entity_id.size()
@ -428,12 +452,14 @@ impl PduHeader {
+ self.pdu_conf.dest_entity_id.size()
}
#[inline]
pub fn pdu_datafield_len(&self) -> usize {
self.pdu_datafield_len.into()
}
/// Returns the full length of the PDU when written to a raw buffer, which is the header length
/// plus the PDU datafield length.
#[inline]
pub fn pdu_len(&self) -> usize {
self.header_len() + self.pdu_datafield_len as usize
}
@ -606,10 +632,13 @@ impl PduHeader {
current_idx,
))
}
#[inline]
pub fn pdu_type(&self) -> PduType {
self.pdu_type
}
#[inline]
pub fn common_pdu_conf(&self) -> &CommonPduConfig {
&self.pdu_conf
}
@ -617,6 +646,8 @@ impl PduHeader {
pub fn seg_metadata_flag(&self) -> SegmentMetadataFlag {
self.seg_metadata_flag
}
#[inline]
pub fn seg_ctrl(&self) -> SegmentationControl {
self.seg_ctrl
}

View File

@ -262,9 +262,13 @@ pub(crate) fn verify_crc16_ccitt_false_from_raw(raw_data: &[u8]) -> bool {
macro_rules! ccsds_impl {
() => {
delegate!(to self.sp_header {
#[inline]
fn ccsds_version(&self) -> u8;
#[inline]
fn packet_id(&self) -> crate::PacketId;
#[inline]
fn psc(&self) -> crate::PacketSequenceCtrl;
#[inline]
fn data_len(&self) -> u16;
});
}
@ -273,8 +277,11 @@ macro_rules! ccsds_impl {
macro_rules! sp_header_impls {
() => {
delegate!(to self.sp_header {
#[inline]
pub fn set_apid(&mut self, apid: u16) -> bool;
#[inline]
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
#[inline]
pub fn set_seq_flags(&mut self, seq_flag: SequenceFlags);
});
}

View File

@ -54,6 +54,7 @@ pub enum SchedStatus {
}
impl From<bool> for SchedStatus {
#[inline]
fn from(value: bool) -> Self {
if value {
SchedStatus::Enabled

View File

@ -111,22 +111,27 @@ pub mod zc {
}
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
#[inline]
fn pus_version(&self) -> PusVersion {
PusVersion::try_from(self.version_ack >> 4 & 0b1111).unwrap_or(PusVersion::Invalid)
}
#[inline]
fn ack_flags(&self) -> u8 {
self.version_ack & 0b1111
}
#[inline]
fn service(&self) -> u8 {
self.service
}
#[inline]
fn subservice(&self) -> u8 {
self.subservice
}
#[inline]
fn source_id(&self) -> u16 {
self.source_id.get()
}
@ -155,22 +160,27 @@ pub struct PusTcSecondaryHeader {
}
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
#[inline]
fn pus_version(&self) -> PusVersion {
self.version
}
#[inline]
fn ack_flags(&self) -> u8 {
self.ack
}
#[inline]
fn service(&self) -> u8 {
self.service
}
#[inline]
fn subservice(&self) -> u8 {
self.subservice
}
#[inline]
fn source_id(&self) -> u16 {
self.source_id
}
@ -191,6 +201,7 @@ impl TryFrom<zc::PusTcSecondaryHeader> for PusTcSecondaryHeader {
}
impl PusTcSecondaryHeader {
#[inline]
pub fn new_simple(service: u8, subservice: u8) -> Self {
PusTcSecondaryHeader {
service,
@ -201,6 +212,7 @@ impl PusTcSecondaryHeader {
}
}
#[inline]
pub fn new(service: u8, subservice: u8, ack: u8, source_id: u16) -> Self {
PusTcSecondaryHeader {
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
/// 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
#[inline]
pub fn new(
sp_header: &mut SpHeader,
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
/// and subservice instead of the full PUS TC secondary header.
#[inline]
pub fn new_simple(
sph: &mut SpHeader,
service: u8,
@ -278,6 +292,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
)
}
#[inline]
pub fn new_no_app_data(
sp_header: &mut SpHeader,
sec_header: PusTcSecondaryHeader,
@ -286,10 +301,12 @@ impl<'raw_data> PusTcCreator<'raw_data> {
Self::new(sp_header, sec_header, &[], set_ccsds_len)
}
#[inline]
pub fn sp_header(&self) -> &SpHeader {
&self.sp_header
}
#[inline]
pub fn set_ack_field(&mut self, ack: u8) -> bool {
if ack > 0b1111 {
return false;
@ -298,6 +315,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
true
}
#[inline]
pub fn set_source_id(&mut self, source_id: u16) {
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,
/// this function needs to be called to ensure that the data length field of the CCSDS header
/// is set correctly.
#[inline]
pub fn update_ccsds_data_len(&mut self) {
self.sp_header.data_len =
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<'_> {
#[inline]
fn len_written(&self) -> usize {
PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len()
}
@ -385,15 +405,20 @@ impl CcsdsPacket for PusTcCreator<'_> {
impl PusPacket for PusTcCreator<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
});
#[inline]
fn user_data(&self) -> &[u8] {
self.app_data
}
#[inline]
fn crc16(&self) -> Option<u16> {
Some(self.calc_own_crc16())
}
@ -401,10 +426,15 @@ impl PusPacket for PusTcCreator<'_> {
impl GenericPusTcSecondaryHeader for PusTcCreator<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
#[inline]
fn source_id(&self) -> u16;
#[inline]
fn ack_flags(&self) -> u8;
});
}
@ -482,24 +512,29 @@ impl<'raw_data> PusTcReader<'raw_data> {
Ok((pus_tc, total_len))
}
#[inline]
pub fn app_data(&self) -> &[u8] {
self.user_data()
}
#[inline]
pub fn raw_data(&self) -> &[u8] {
self.raw_data
}
#[inline]
pub fn len_packed(&self) -> usize {
self.sp_header.total_len()
}
#[inline]
pub fn sp_header(&self) -> &SpHeader {
&self.sp_header
}
}
impl PartialEq for PusTcReader<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.raw_data == other.raw_data
}
@ -511,15 +546,20 @@ impl CcsdsPacket for PusTcReader<'_> {
impl PusPacket for PusTcReader<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
});
#[inline]
fn user_data(&self) -> &[u8] {
self.app_data
}
#[inline]
fn crc16(&self) -> Option<u16> {
Some(self.crc16)
}
@ -527,10 +567,15 @@ impl PusPacket for PusTcReader<'_> {
impl GenericPusTcSecondaryHeader for PusTcReader<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
#[inline]
fn source_id(&self) -> u16;
#[inline]
fn ack_flags(&self) -> u8;
});
}

View File

@ -86,27 +86,33 @@ pub mod zc {
}
impl GenericPusTmSecondaryHeader for PusTmSecHeaderWithoutTimestamp {
#[inline]
fn pus_version(&self) -> PusVersion {
PusVersion::try_from(self.pus_version_and_sc_time_ref_status >> 4 & 0b1111)
.unwrap_or(PusVersion::Invalid)
}
#[inline]
fn sc_time_ref_status(&self) -> u8 {
self.pus_version_and_sc_time_ref_status & 0b1111
}
#[inline]
fn service(&self) -> u8 {
self.service
}
#[inline]
fn subservice(&self) -> u8 {
self.subservice
}
#[inline]
fn msg_counter(&self) -> u16 {
self.msg_counter.get()
}
#[inline]
fn dest_id(&self) -> u16 {
self.dest_id.get()
}
@ -127,15 +133,18 @@ pub struct PusTmSecondaryHeader<'stamp> {
}
impl<'stamp> PusTmSecondaryHeader<'stamp> {
#[inline]
pub fn new_simple(service: u8, subservice: u8, time_stamp: &'stamp [u8]) -> Self {
Self::new(service, subservice, 0, 0, time_stamp)
}
/// Like [Self::new_simple] but without a timestamp.
#[inline]
pub fn new_simple_no_timestamp(service: u8, subservice: u8) -> Self {
Self::new(service, subservice, 0, 0, &[])
}
#[inline]
pub fn new(
service: u8,
subservice: u8,
@ -156,26 +165,32 @@ impl<'stamp> PusTmSecondaryHeader<'stamp> {
}
impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
#[inline]
fn pus_version(&self) -> PusVersion {
self.pus_version
}
#[inline]
fn sc_time_ref_status(&self) -> u8 {
self.sc_time_ref_status
}
#[inline]
fn service(&self) -> u8 {
self.service
}
#[inline]
fn subservice(&self) -> u8 {
self.subservice
}
#[inline]
fn msg_counter(&self) -> u16 {
self.msg_counter
}
#[inline]
fn dest_id(&self) -> u16 {
self.dest_id
}
@ -184,6 +199,7 @@ impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice> {
type Error = ();
#[inline]
fn try_from(sec_header: zc::PusTmSecHeader<'slice>) -> Result<Self, Self::Error> {
Ok(PusTmSecondaryHeader {
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
/// 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
#[inline]
pub fn new(
sp_header: &mut SpHeader,
sec_header: PusTmSecondaryHeader<'time>,
@ -255,6 +272,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
pus_tm
}
#[inline]
pub fn new_simple(
sp_header: &mut SpHeader,
service: u8,
@ -275,6 +293,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
))
}
#[inline]
pub fn new_no_source_data(
sp_header: &mut SpHeader,
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)
}
#[inline]
pub fn timestamp(&self) -> &[u8] {
self.sec_header.time_stamp
}
#[inline]
pub fn source_data(&self) -> &[u8] {
self.source_data
}
#[inline]
pub fn set_dest_id(&mut self, dest_id: u16) {
self.sec_header.dest_id = dest_id;
}
#[inline]
pub fn set_msg_counter(&mut self, msg_counter: u16) {
self.sec_header.msg_counter = msg_counter
}
#[inline]
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;
}
@ -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,
/// this function needs to be called to ensure that the data length field of the CCSDS header
/// is set correctly
#[inline]
pub fn update_ccsds_data_len(&mut self) {
self.sp_header.data_len =
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]
#[inline]
pub fn update_packet_fields(&mut self) {
self.update_ccsds_data_len();
}
@ -386,6 +412,7 @@ impl<'time, 'raw_data> PusTmCreator<'time, 'raw_data> {
}
impl WritablePusPacket for PusTmCreator<'_, '_> {
#[inline]
fn len_written(&self) -> usize {
PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA
+ self.sec_header.time_stamp.len()
@ -411,15 +438,20 @@ impl CcsdsPacket for PusTmCreator<'_, '_> {
impl PusPacket for PusTmCreator<'_, '_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
});
#[inline]
fn user_data(&self) -> &[u8] {
self.source_data
}
#[inline]
fn crc16(&self) -> Option<u16> {
Some(self.calc_own_crc16())
}
@ -427,11 +459,17 @@ impl PusPacket for PusTmCreator<'_, '_> {
impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
#[inline]
fn dest_id(&self) -> u16;
#[inline]
fn msg_counter(&self) -> u16;
#[inline]
fn sc_time_ref_status(&self) -> u8;
});
}
@ -518,19 +556,23 @@ impl<'raw_data> PusTmReader<'raw_data> {
Ok((pus_tm, total_len))
}
#[inline]
pub fn len_packed(&self) -> usize {
self.sp_header.total_len()
}
#[inline]
pub fn source_data(&self) -> &[u8] {
self.user_data()
}
#[inline]
pub fn timestamp(&self) -> &[u8] {
self.sec_header.time_stamp
}
/// This function will return the slice [Self] was constructed from.
#[inline]
pub fn raw_data(&self) -> &[u8] {
self.raw_data
}
@ -551,15 +593,20 @@ impl CcsdsPacket for PusTmReader<'_> {
impl PusPacket for PusTmReader<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
});
#[inline]
fn user_data(&self) -> &[u8] {
self.source_data
}
#[inline]
fn crc16(&self) -> Option<u16> {
Some(self.crc16)
}
@ -567,11 +614,17 @@ impl PusPacket for PusTmReader<'_> {
impl GenericPusTmSecondaryHeader for PusTmReader<'_> {
delegate!(to self.sec_header {
#[inline]
fn pus_version(&self) -> PusVersion;
#[inline]
fn service(&self) -> u8;
#[inline]
fn subservice(&self) -> u8;
#[inline]
fn dest_id(&self) -> u16;
#[inline]
fn msg_counter(&self) -> u16;
#[inline]
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
/// exceeds [MAX_APID].
#[inline]
pub fn set_apid(&mut self, apid: u16) -> bool {
if apid > MAX_APID {
return false;
@ -645,11 +699,13 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
}
/// This function sets the message counter in the PUS TM secondary header.
#[inline]
pub fn set_msg_count(&mut self, msg_count: u16) {
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.
#[inline]
pub fn set_destination_id(&mut self, dest_id: u16) {
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
/// exceeds [MAX_SEQ_COUNT].
#[inline]
pub fn set_seq_count(&mut self, seq_count: u16) -> bool {
if seq_count > MAX_SEQ_COUNT {
return false;

View File

@ -207,18 +207,21 @@ pub struct PacketId {
}
impl PartialEq for PacketId {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.raw().eq(&other.raw())
}
}
impl PartialOrd for PacketId {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for PacketId {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.raw().cmp(&other.raw())
}
@ -232,6 +235,7 @@ impl Hash for PacketId {
}
impl Default for PacketId {
#[inline]
fn default() -> Self {
PacketId {
ptype: PacketType::Tm,
@ -244,26 +248,31 @@ impl Default for PacketId {
impl PacketId {
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked constructor variants to avoid panics.
#[inline]
pub const fn new_for_tc(sec_header: bool, apid: u16) -> Self {
Self::new(PacketType::Tc, sec_header, apid)
}
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked constructor variants to avoid panics.
#[inline]
pub const fn new_for_tm(sec_header: bool, apid: u16) -> Self {
Self::new(PacketType::Tm, sec_header, apid)
}
#[inline]
pub fn new_for_tc_checked(sec_header: bool, apid: u16) -> Option<Self> {
Self::new_checked(PacketType::Tc, sec_header, apid)
}
#[inline]
pub fn new_for_tm_checked(sec_header: bool, apid: u16) -> Option<Self> {
Self::new_checked(PacketType::Tm, sec_header, apid)
}
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked variants to avoid panics.
#[inline]
pub const fn new(ptype: PacketType, sec_header: bool, apid: u16) -> Self {
if apid > MAX_APID {
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> {
if apid > MAX_APID {
return None;
@ -285,6 +295,7 @@ impl PacketId {
/// 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
/// 2047
#[inline]
pub fn set_apid(&mut self, apid: u16) -> bool {
if apid > MAX_APID {
return false;
@ -293,6 +304,7 @@ impl PacketId {
true
}
#[inline]
pub fn apid(&self) -> u16 {
self.apid
}
@ -326,6 +338,7 @@ pub struct PacketSequenceCtrl {
impl PacketSequenceCtrl {
/// This constructor panics if the sequence count exceeds [MAX_SEQ_COUNT].
/// Use [Self::new_checked] to avoid panics.
#[inline]
pub const fn new(seq_flags: SequenceFlags, seq_count: u16) -> PacketSequenceCtrl {
if seq_count > MAX_SEQ_COUNT {
panic!("Sequence count too large");
@ -337,18 +350,22 @@ impl PacketSequenceCtrl {
}
/// Returns [None] if the passed sequence count exceeds [MAX_SEQ_COUNT].
#[inline]
pub fn new_checked(seq_flags: SequenceFlags, seq_count: u16) -> Option<PacketSequenceCtrl> {
if seq_count > MAX_SEQ_COUNT {
return None;
}
Some(PacketSequenceCtrl::new(seq_flags, seq_count))
}
#[inline]
pub fn raw(&self) -> u16 {
((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 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 {
if ssc > MAX_SEQ_COUNT {
return false;
@ -357,6 +374,7 @@ impl PacketSequenceCtrl {
true
}
#[inline]
pub fn seq_count(&self) -> u16 {
self.seq_count
}
@ -398,6 +416,7 @@ pub trait CcsdsPacket {
/// Retrieve data length field
fn data_len(&self) -> u16;
/// Retrieve the total packet size based on the data length field
#[inline]
fn total_len(&self) -> usize {
usize::from(self.data_len()) + CCSDS_HEADER_LEN + 1
}
@ -489,6 +508,7 @@ pub struct SpHeader {
impl Default for SpHeader {
/// 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.
#[inline]
fn default() -> Self {
SpHeader {
version: 0,
@ -503,6 +523,7 @@ impl Default for SpHeader {
}
impl SpHeader {
#[inline]
pub const fn new(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16) -> Self {
Self {
version: 0,
@ -512,10 +533,42 @@ impl SpHeader {
}
}
/// This constructor sets the sequence flag field to [SequenceFlags::Unsegmented]. The data
/// length field is set to 1, which denotes an empty space packets.
///
/// This constructor will panic if the APID exceeds [MAX_APID].
#[inline]
pub const fn new_from_apid(apid: u16) -> Self {
SpHeader {
version: 0,
packet_id: PacketId::new(PacketType::Tm, false, apid),
psc: PacketSequenceCtrl {
seq_flags: SequenceFlags::Unsegmented,
seq_count: 0,
},
data_len: 1,
}
}
/// Checked variant of [Self::new_from_apid].
#[inline]
pub fn new_from_apid_checked(apid: u16) -> Option<Self> {
Some(SpHeader {
version: 0,
packet_id: PacketId::new_checked(PacketType::Tm, false, apid)?,
psc: PacketSequenceCtrl {
seq_flags: SequenceFlags::Unsegmented,
seq_count: 0,
},
data_len: 1,
})
}
/// This constructor panics if the passed APID exceeds [MAX_APID] or the passed packet sequence
/// count exceeds [MAX_SEQ_COUNT].
///
/// The checked constructor variants can be used to avoid panics.
#[inline]
const fn new_from_fields(
ptype: PacketType,
sec_header: bool,
@ -543,6 +596,7 @@ impl SpHeader {
///
/// 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.
#[inline]
pub fn new_from_fields_checked(
ptype: PacketType,
sec_header: bool,
@ -561,6 +615,7 @@ impl SpHeader {
/// Helper function for telemetry space packet headers. The packet type field will be
/// set accordingly. The secondary header flag field is set to false.
#[inline]
pub fn new_for_tm_checked(
apid: u16,
seq_flags: SequenceFlags,
@ -572,6 +627,7 @@ impl SpHeader {
/// Helper function for telemetry space packet headers. The packet type field will be
/// set accordingly. The secondary header flag field is set to false.
#[inline]
pub fn new_for_tc_checked(
apid: u16,
seq_flags: SequenceFlags,
@ -582,6 +638,7 @@ impl SpHeader {
}
/// This is an unchecked constructor which can panic on invalid input.
#[inline]
pub const fn new_for_tm(
apid: u16,
seq_flags: SequenceFlags,
@ -592,6 +649,7 @@ impl SpHeader {
}
/// This is an unchecked constructor which can panic on invalid input.
#[inline]
pub const fn new_for_tc(
apid: u16,
seq_flags: SequenceFlags,
@ -602,11 +660,13 @@ impl SpHeader {
}
/// 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> {
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]
#[inline]
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)
}
@ -614,6 +674,7 @@ impl SpHeader {
/// 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.
#[inline]
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)
}
@ -621,6 +682,7 @@ impl SpHeader {
/// 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.
#[inline]
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)
}
@ -628,6 +690,7 @@ impl SpHeader {
delegate! {
to self.packet_id {
/// Returns [false] and fails if the APID exceeds [MAX_APID]
#[inline]
pub fn set_apid(&mut self, apid: u16) -> bool;
}
}
@ -635,22 +698,27 @@ impl SpHeader {
delegate! {
to self.psc {
/// Returns [false] and fails if the sequence count exceeds [MAX_SEQ_COUNT]
#[inline]
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
}
}
#[inline]
pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
self.psc.seq_flags = seq_flags;
}
#[inline]
pub fn set_sec_header_flag(&mut self) {
self.packet_id.sec_header_flag = true;
}
#[inline]
pub fn clear_sec_header_flag(&mut self) {
self.packet_id.sec_header_flag = false;
}
#[inline]
pub fn set_packet_type(&mut self, packet_type: PacketType) {
self.packet_id.ptype = packet_type;
}
@ -713,6 +781,7 @@ impl CcsdsPacket for SpHeader {
}
impl CcsdsPrimaryHeader for SpHeader {
#[inline]
fn from_composite_fields(
packet_id: PacketId,
psc: PacketSequenceCtrl,
@ -780,9 +849,12 @@ pub mod zc {
((self.version_packet_id.get() >> 13) as u8) & 0b111
}
#[inline]
fn packet_id(&self) -> PacketId {
PacketId::from(self.packet_id_raw())
}
#[inline]
fn psc(&self) -> PacketSequenceCtrl {
PacketSequenceCtrl::from(self.psc_raw())
}
@ -792,10 +864,12 @@ pub mod zc {
self.data_len.get()
}
#[inline]
fn packet_id_raw(&self) -> u16 {
self.version_packet_id.get() & (!VERSION_MASK)
}
#[inline]
fn psc_raw(&self) -> u16 {
self.psc.get()
}
@ -1180,4 +1254,16 @@ pub(crate) mod tests {
let mut id_set = HashSet::new();
id_set.insert(PacketId::from(1_u16));
}
#[test]
fn sp_header_from_apid() {
let sp_header = SpHeader::new_from_apid(0x03);
assert_eq!(sp_header.apid(), 0x03);
}
#[test]
fn sp_header_from_apid_checked() {
let sp_header = SpHeader::new_from_apid_checked(0x03).unwrap();
assert_eq!(sp_header.apid(), 0x03);
}
}

View File

@ -145,6 +145,7 @@ pub fn length_of_day_segment_from_pfield(pfield: u8) -> LengthOfDaySegment {
LengthOfDaySegment::Short16Bits
}
#[inline]
pub fn precision_from_pfield(pfield: u8) -> SubmillisPrecision {
match pfield & 0b11 {
0b01 => SubmillisPrecision::Microseconds,
@ -272,24 +273,29 @@ impl ConversionFromUnix {
}
impl CdsCommon for ConversionFromUnix {
#[inline]
fn submillis_precision(&self) -> SubmillisPrecision {
self.submilis_prec
}
#[inline]
fn ms_of_day(&self) -> u32 {
self.ms_of_day
}
#[inline]
fn ccsds_days_as_u32(&self) -> u32 {
self.ccsds_days
}
#[inline]
fn submillis(&self) -> u32 {
self.submillis
}
}
impl CdsConverter for ConversionFromUnix {
#[inline]
fn unix_days_seconds(&self) -> i64 {
self.unix_days_seconds
}
@ -302,24 +308,31 @@ struct ConversionFromChronoDatetime {
}
impl CdsCommon for ConversionFromChronoDatetime {
#[inline]
fn submillis_precision(&self) -> SubmillisPrecision {
self.submillis_prec
}
delegate! {
to self.unix_conversion {
#[inline]
fn ms_of_day(&self) -> u32;
#[inline]
fn ccsds_days_as_u32(&self) -> u32;
}
}
#[inline]
fn submillis(&self) -> u32 {
self.submillis
}
}
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]

View File

@ -177,6 +177,7 @@ pub struct FractionalPart {
}
impl FractionalPart {
#[inline]
pub const fn new(resolution: FractionalResolution, counter: u32) -> Self {
let div = fractional_res_to_div(resolution);
assert!(counter <= div, "invalid counter for resolution");
@ -187,15 +188,18 @@ impl FractionalPart {
}
/// An empty fractional part for second resolution only.
#[inline]
pub const fn new_with_seconds_resolution() -> Self {
Self::new(FractionalResolution::Seconds, 0)
}
/// Helper method which simply calls [Self::new_with_seconds_resolution].
#[inline]
pub const fn new_empty() -> Self {
Self::new_with_seconds_resolution()
}
#[inline]
pub fn new_checked(resolution: FractionalResolution, counter: u32) -> Option<Self> {
let div = fractional_res_to_div(resolution);
if counter > div {
@ -207,14 +211,17 @@ impl FractionalPart {
})
}
#[inline]
pub fn resolution(&self) -> FractionalResolution {
self.resolution
}
#[inline]
pub fn counter(&self) -> u32 {
self.counter
}
#[inline]
pub fn no_fractional_part(&self) -> bool {
self.resolution == FractionalResolution::Seconds
}
@ -285,6 +292,7 @@ pub struct CucTimeWithLeapSecs {
}
impl CucTimeWithLeapSecs {
#[inline]
pub fn new(time: CucTime, leap_seconds: u32) -> Self {
Self { time, leap_seconds }
}
@ -300,6 +308,7 @@ pub fn pfield_len(pfield: u8) -> usize {
impl CucTime {
/// Create a time provider with a four byte counter and no fractional part.
#[inline]
pub fn new(counter: u32) -> Self {
// These values are definitely valid, so it is okay to unwrap here.
Self::new_generic(
@ -310,11 +319,13 @@ impl CucTime {
}
/// 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> {
Self::new_generic(WidthCounterPair(4, counter), fractions)
}
/// Fractions with a resolution of ~ 4 ms
#[inline]
pub fn new_with_coarse_fractions(counter: u32, subsec_fractions: u8) -> Self {
// These values are definitely valid, so it is okay to unwrap here.
Self::new_generic(
@ -328,6 +339,7 @@ impl CucTime {
}
/// Fractions with a resolution of ~ 16 us
#[inline]
pub fn new_with_medium_fractions(counter: u32, subsec_fractions: u16) -> Self {
// These values are definitely valid, so it is okay to unwrap here.
Self::new_generic(
@ -343,6 +355,7 @@ impl CucTime {
/// 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
/// [CucError::InvalidFractions] if the fractional value exceeds the value.
#[inline]
pub fn new_with_fine_fractions(counter: u32, subsec_fractions: u32) -> Result<Self, CucError> {
Self::new_generic(
WidthCounterPair(4, counter),
@ -457,6 +470,7 @@ impl CucTime {
/// Most generic constructor which allows full configurability for the counter and for the
/// fractions.
#[inline]
pub fn new_generic(
width_and_counter: WidthCounterPair,
fractions: FractionalPart,
@ -476,31 +490,38 @@ impl CucTime {
})
}
#[inline]
pub fn ccsds_time_code(&self) -> CcsdsTimeCode {
CcsdsTimeCode::CucCcsdsEpoch
}
#[inline]
pub fn width_counter_pair(&self) -> WidthCounterPair {
self.counter
}
#[inline]
pub fn counter_width(&self) -> u8 {
self.counter.0
}
#[inline]
pub fn counter(&self) -> u32 {
self.counter.1
}
/// Subsecond fractional part of the CUC time.
#[inline]
pub fn fractions(&self) -> FractionalPart {
self.fractions
}
#[inline]
pub fn to_leap_sec_helper(&self, leap_seconds: u32) -> CucTimeWithLeapSecs {
CucTimeWithLeapSecs::new(*self, leap_seconds)
}
#[inline]
pub fn set_fractions(&mut self, fractions: FractionalPart) -> Result<(), CucError> {
Self::verify_fractions_value(fractions)?;
self.fractions = fractions;
@ -510,6 +531,7 @@ impl CucTime {
/// Set a fractional resolution. Please note that this function will reset the fractional value
/// to 0 if the resolution changes.
#[inline]
pub fn set_fractional_resolution(&mut self, res: FractionalResolution) {
if res == FractionalResolution::Seconds {
self.fractions = FractionalPart::new_with_seconds_resolution();
@ -519,6 +541,7 @@ impl CucTime {
}
}
#[inline]
fn build_p_field(counter_width: u8, resolution: FractionalResolution) -> u8 {
let mut pfield = P_FIELD_BASE;
if !(1..=4).contains(&counter_width) {
@ -538,6 +561,7 @@ impl CucTime {
pfield
}
#[inline]
fn update_p_field_fractions(&mut self) {
self.pfield &= !(0b11);
self.pfield |= self.fractions.resolution() as u8;
@ -582,6 +606,7 @@ impl CucTime {
)
}
#[inline]
pub fn len_packed_from_pfield(pfield: u8) -> usize {
let mut base_len: usize = 1;
base_len += Self::len_cntr_from_pfield(pfield) as usize;
@ -590,6 +615,7 @@ impl CucTime {
}
/// Verifies the raw width parameter.
#[inline]
fn verify_counter_width(width: u8) -> Result<(), CucError> {
if width == 0 || width > 4 {
return Err(CucError::InvalidCounterWidth(width));
@ -597,6 +623,7 @@ impl CucTime {
Ok(())
}
#[inline]
fn verify_fractions_value(val: FractionalPart) -> Result<(), CucError> {
if val.counter > 2u32.pow((val.resolution as u32) * 8) - 1 {
return Err(CucError::InvalidFractions {
@ -607,10 +634,12 @@ impl CucTime {
Ok(())
}
#[inline]
fn len_as_bytes(&self) -> usize {
Self::len_packed_from_pfield(self.pfield)
}
#[inline]
fn subsec_nanos(&self) -> u32 {
if self.fractions.resolution() == FractionalResolution::Seconds {
return 0;
@ -751,22 +780,27 @@ impl TimeWriter for CucTime {
}
impl CcsdsTimeProvider for CucTimeWithLeapSecs {
#[inline]
fn len_as_bytes(&self) -> usize {
self.time.len_as_bytes()
}
#[inline]
fn p_field(&self) -> (usize, [u8; 2]) {
(1, [self.time.pfield, 0])
}
#[inline]
fn ccdsd_time_code(&self) -> CcsdsTimeCode {
self.time.ccsds_time_code()
}
#[inline]
fn unix_secs(&self) -> i64 {
self.time.unix_secs(self.leap_seconds)
}
#[inline]
fn subsec_nanos(&self) -> u32 {
self.time.subsec_nanos()
}

View File

@ -166,6 +166,7 @@ pub fn seconds_since_epoch() -> f64 {
///
/// - CCSDS epoch: 1958-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 {
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
/// - UNIX Epoch: 1970-01-01T00:00:00+00:00
#[inline]
pub const fn ccsds_to_unix_days(ccsds_days: i64) -> 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
/// seconds since the CCSDS and UNIX epoch times.
#[inline]
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)
}
#[inline]
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)
}

View File

@ -15,10 +15,12 @@ pub trait ToBeBytes {
impl ToBeBytes for () {
type ByteArray = [u8; 0];
#[inline]
fn written_len(&self) -> usize {
0
}
#[inline]
fn to_be_bytes(&self) -> Self::ByteArray {
[]
}
@ -27,9 +29,12 @@ impl ToBeBytes for () {
impl ToBeBytes for u8 {
type ByteArray = [u8; 1];
#[inline]
fn written_len(&self) -> usize {
1
}
#[inline]
fn to_be_bytes(&self) -> Self::ByteArray {
u8::to_be_bytes(*self)
}
@ -38,9 +43,12 @@ impl ToBeBytes for u8 {
impl ToBeBytes for u16 {
type ByteArray = [u8; 2];
#[inline]
fn written_len(&self) -> usize {
2
}
#[inline]
fn to_be_bytes(&self) -> Self::ByteArray {
u16::to_be_bytes(*self)
}
@ -49,9 +57,12 @@ impl ToBeBytes for u16 {
impl ToBeBytes for u32 {
type ByteArray = [u8; 4];
#[inline]
fn written_len(&self) -> usize {
4
}
#[inline]
fn to_be_bytes(&self) -> Self::ByteArray {
u32::to_be_bytes(*self)
}
@ -60,9 +71,12 @@ impl ToBeBytes for u32 {
impl ToBeBytes for u64 {
type ByteArray = [u8; 8];
#[inline]
fn written_len(&self) -> usize {
8
}
#[inline]
fn to_be_bytes(&self) -> Self::ByteArray {
u64::to_be_bytes(*self)
}
@ -104,6 +118,7 @@ pub enum UnsignedByteFieldError {
}
impl From<ByteConversionError> for UnsignedByteFieldError {
#[inline]
fn from(value: ByteConversionError) -> Self {
Self::ByteConversionError(value)
}
@ -138,14 +153,17 @@ pub struct UnsignedByteField {
}
impl UnsignedByteField {
#[inline]
pub const fn new(width: usize, value: u64) -> Self {
Self { width, value }
}
#[inline]
pub const fn value_const(&self) -> u64 {
self.value
}
#[inline]
pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> {
if width > buf.len() {
return Err(ByteConversionError::FromSliceTooSmall {
@ -178,10 +196,12 @@ impl UnsignedByteField {
}
impl UnsignedEnum for UnsignedByteField {
#[inline]
fn size(&self) -> usize {
self.width
}
#[inline]
fn value(&self) -> u64 {
self.value_const()
}
@ -237,6 +257,7 @@ impl<TYPE: Copy + Into<u64>> GenericUnsignedByteField<TYPE> {
}
impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteField<TYPE> {
#[inline]
fn size(&self) -> usize {
self.value.written_len()
}
@ -252,6 +273,7 @@ impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteFie
Ok(self.value.written_len())
}
#[inline]
fn value(&self) -> u64 {
self.value_typed().into()
}
@ -277,6 +299,7 @@ impl From<UnsignedByteFieldU8> for UnsignedByteField {
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
type Error = UnsignedByteFieldError;
#[inline]
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
if value.width != 1 {
return Err(UnsignedByteFieldError::InvalidWidth {
@ -289,6 +312,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
}
impl From<UnsignedByteFieldU16> for UnsignedByteField {
#[inline]
fn from(value: UnsignedByteFieldU16) -> Self {
Self::new(2, value.value as u64)
}
@ -297,6 +321,7 @@ impl From<UnsignedByteFieldU16> for UnsignedByteField {
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
type Error = UnsignedByteFieldError;
#[inline]
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
if value.width != 2 {
return Err(UnsignedByteFieldError::InvalidWidth {
@ -309,6 +334,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
}
impl From<UnsignedByteFieldU32> for UnsignedByteField {
#[inline]
fn from(value: UnsignedByteFieldU32) -> Self {
Self::new(4, value.value as u64)
}
@ -317,6 +343,7 @@ impl From<UnsignedByteFieldU32> for UnsignedByteField {
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
type Error = UnsignedByteFieldError;
#[inline]
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
if value.width != 4 {
return Err(UnsignedByteFieldError::InvalidWidth {
@ -329,6 +356,7 @@ impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
}
impl From<UnsignedByteFieldU64> for UnsignedByteField {
#[inline]
fn from(value: UnsignedByteFieldU64) -> Self {
Self::new(8, value.value)
}
@ -337,6 +365,7 @@ impl From<UnsignedByteFieldU64> for UnsignedByteField {
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU64 {
type Error = UnsignedByteFieldError;
#[inline]
fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
if value.width != 8 {
return Err(UnsignedByteFieldError::InvalidWidth {