finished basic EOF unittests
This commit is contained in:
parent
bce16a6018
commit
006bc39ff6
@ -1,8 +1,9 @@
|
|||||||
|
use crate::cfdp::pdu::{read_fss_field, write_fss_field, FileDirectiveType, PduError, PduHeader};
|
||||||
use crate::cfdp::tlv::EntityIdTlv;
|
use crate::cfdp::tlv::EntityIdTlv;
|
||||||
use crate::cfdp::ConditionCode;
|
use crate::cfdp::{ConditionCode, LargeFileFlag};
|
||||||
|
use crate::{ByteConversionError, SizeMissmatch};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::cfdp::pdu::PduHeader;
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
@ -16,12 +17,187 @@ pub struct EofPdu {
|
|||||||
|
|
||||||
impl EofPdu {
|
impl EofPdu {
|
||||||
pub fn new_no_error(pdu_header: PduHeader, file_checksum: u32, file_size: u64) -> Self {
|
pub fn new_no_error(pdu_header: PduHeader, file_checksum: u32, file_size: u64) -> Self {
|
||||||
Self {
|
let mut eof_pdu = Self {
|
||||||
pdu_header,
|
pdu_header,
|
||||||
condition_code: ConditionCode::NoError,
|
condition_code: ConditionCode::NoError,
|
||||||
file_checksum,
|
file_checksum,
|
||||||
file_size,
|
file_size,
|
||||||
fault_location: None
|
fault_location: None,
|
||||||
}
|
};
|
||||||
|
eof_pdu.pdu_header.pdu_datafield_len = eof_pdu.calc_pdu_datafield_len() as u16;
|
||||||
|
eof_pdu
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pub fn pdu_header(&self) -> &PduHeader {
|
||||||
|
&self.pdu_header
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn written_len(&self) -> usize {
|
||||||
|
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn condition_code(&self) -> ConditionCode {
|
||||||
|
self.condition_code
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_checksum(&self) -> u32 {
|
||||||
|
self.file_checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_size(&self) -> u64 {
|
||||||
|
self.file_size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_pdu_datafield_len(&self) -> usize {
|
||||||
|
// One directive type octet, 4 bits condition code, 4 spare bits.
|
||||||
|
let mut len = 2 + core::mem::size_of::<u32>() + 4;
|
||||||
|
if self.pdu_header.pdu_conf.file_flag == LargeFileFlag::Large {
|
||||||
|
len += 4;
|
||||||
|
}
|
||||||
|
if let Some(fault_location) = self.fault_location {
|
||||||
|
len += fault_location.len_full();
|
||||||
|
}
|
||||||
|
len
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||||
|
let expected_len = self.written_len();
|
||||||
|
if buf.len() < expected_len {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: expected_len,
|
||||||
|
})
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let mut current_idx = self.pdu_header.write_to_bytes(buf)?;
|
||||||
|
buf[current_idx] = FileDirectiveType::EofPdu as u8;
|
||||||
|
current_idx += 1;
|
||||||
|
buf[current_idx] = (self.condition_code as u8) << 4;
|
||||||
|
current_idx += 1;
|
||||||
|
buf[current_idx..current_idx + 4].copy_from_slice(&self.file_checksum.to_be_bytes());
|
||||||
|
current_idx += 4;
|
||||||
|
current_idx += write_fss_field(
|
||||||
|
self.pdu_header.pdu_conf.file_flag,
|
||||||
|
self.file_size,
|
||||||
|
&mut buf[current_idx..],
|
||||||
|
)?;
|
||||||
|
if let Some(fault_location) = self.fault_location {
|
||||||
|
current_idx += fault_location.write_to_be_bytes(buf)?;
|
||||||
|
}
|
||||||
|
Ok(current_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(buf: &[u8]) -> Result<EofPdu, PduError> {
|
||||||
|
let (pdu_header, mut current_idx) = PduHeader::from_bytes(buf)?;
|
||||||
|
let full_len_without_crc = pdu_header.verify_length_and_checksum(buf)?;
|
||||||
|
let is_large_file = pdu_header.pdu_conf.file_flag == LargeFileFlag::Large;
|
||||||
|
let mut min_expected_len = 2 + 4 + 4;
|
||||||
|
if is_large_file {
|
||||||
|
min_expected_len += 4;
|
||||||
|
}
|
||||||
|
if pdu_header.header_len() + min_expected_len > buf.len() {
|
||||||
|
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: pdu_header.header_len() + min_expected_len,
|
||||||
|
})
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let directive_type = FileDirectiveType::try_from(buf[current_idx]).map_err(|_| {
|
||||||
|
PduError::InvalidDirectiveType((buf[current_idx], FileDirectiveType::EofPdu))
|
||||||
|
})?;
|
||||||
|
if directive_type != FileDirectiveType::EofPdu {
|
||||||
|
return Err(PduError::WrongDirectiveType((
|
||||||
|
directive_type,
|
||||||
|
FileDirectiveType::EofPdu,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
current_idx += 1;
|
||||||
|
let condition_code = ConditionCode::try_from((buf[current_idx] >> 4) & 0b1111)
|
||||||
|
.map_err(|_| PduError::InvalidConditionCode((buf[current_idx] >> 4) & 0b1111))?;
|
||||||
|
current_idx += 1;
|
||||||
|
let file_checksum =
|
||||||
|
u32::from_be_bytes(buf[current_idx..current_idx + 4].try_into().unwrap());
|
||||||
|
current_idx += 4;
|
||||||
|
let (fss_field_len, file_size) =
|
||||||
|
read_fss_field(pdu_header.pdu_conf.file_flag, &buf[current_idx..]);
|
||||||
|
current_idx += fss_field_len;
|
||||||
|
let mut fault_location = None;
|
||||||
|
if condition_code != ConditionCode::NoError && current_idx < full_len_without_crc {
|
||||||
|
fault_location = Some(EntityIdTlv::from_bytes(&buf[current_idx..])?);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
pdu_header,
|
||||||
|
condition_code,
|
||||||
|
file_checksum,
|
||||||
|
file_size,
|
||||||
|
fault_location,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::cfdp::pdu::eof::EofPdu;
|
||||||
|
use crate::cfdp::pdu::tests::{common_pdu_conf, verify_raw_header};
|
||||||
|
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
|
||||||
|
use crate::cfdp::{ConditionCode, CrcFlag, LargeFileFlag};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basic() {
|
||||||
|
let pdu_conf = common_pdu_conf(CrcFlag::NoCrc, LargeFileFlag::Normal);
|
||||||
|
let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0);
|
||||||
|
let eof_pdu = EofPdu::new_no_error(pdu_header, 0x01020304, 12);
|
||||||
|
assert_eq!(eof_pdu.written_len(), pdu_header.header_len() + 2 + 4 + 4);
|
||||||
|
assert_eq!(eof_pdu.file_checksum(), 0x01020304);
|
||||||
|
assert_eq!(eof_pdu.file_size(), 12);
|
||||||
|
assert_eq!(eof_pdu.condition_code(), ConditionCode::NoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialization() {
|
||||||
|
let pdu_conf = common_pdu_conf(CrcFlag::NoCrc, LargeFileFlag::Normal);
|
||||||
|
let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0);
|
||||||
|
let eof_pdu = EofPdu::new_no_error(pdu_header, 0x01020304, 12);
|
||||||
|
let mut buf: [u8; 64] = [0; 64];
|
||||||
|
let res = eof_pdu.write_to_bytes(&mut buf);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let written = res.unwrap();
|
||||||
|
assert_eq!(written, eof_pdu.written_len());
|
||||||
|
verify_raw_header(eof_pdu.pdu_header(), &buf);
|
||||||
|
let mut current_idx = eof_pdu.pdu_header().header_len();
|
||||||
|
buf[current_idx] = FileDirectiveType::EofPdu as u8;
|
||||||
|
current_idx += 1;
|
||||||
|
assert_eq!(
|
||||||
|
(buf[current_idx] >> 4) & 0b1111,
|
||||||
|
ConditionCode::NoError as u8
|
||||||
|
);
|
||||||
|
current_idx += 1;
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_be_bytes(buf[current_idx..current_idx + 4].try_into().unwrap()),
|
||||||
|
0x01020304
|
||||||
|
);
|
||||||
|
current_idx += 4;
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_be_bytes(buf[current_idx..current_idx + 4].try_into().unwrap()),
|
||||||
|
12
|
||||||
|
);
|
||||||
|
current_idx += 4;
|
||||||
|
assert_eq!(current_idx, written);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialization() {
|
||||||
|
let pdu_conf = common_pdu_conf(CrcFlag::NoCrc, LargeFileFlag::Normal);
|
||||||
|
let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0);
|
||||||
|
let eof_pdu = EofPdu::new_no_error(pdu_header, 0x01020304, 12);
|
||||||
|
let mut buf: [u8; 64] = [0; 64];
|
||||||
|
eof_pdu.write_to_bytes(&mut buf).unwrap();
|
||||||
|
let eof_read_back = EofPdu::from_bytes(&buf);
|
||||||
|
if !eof_read_back.is_ok() {
|
||||||
|
let e = eof_read_back.unwrap_err();
|
||||||
|
panic!("deserialization failed with: {e}")
|
||||||
|
}
|
||||||
|
let eof_read_back = eof_read_back.unwrap();
|
||||||
|
assert_eq!(eof_read_back, eof_pdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::cfdp::pdu::PduHeader;
|
use crate::cfdp::pdu::PduHeader;
|
||||||
|
use crate::cfdp::tlv::EntityIdTlv;
|
||||||
use crate::cfdp::ConditionCode;
|
use crate::cfdp::ConditionCode;
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -29,6 +30,6 @@ pub struct FinishPdu<'fs_responses> {
|
|||||||
condition_code: ConditionCode,
|
condition_code: ConditionCode,
|
||||||
delivery_code: DeliveryCode,
|
delivery_code: DeliveryCode,
|
||||||
file_status: FileStatus,
|
file_status: FileStatus,
|
||||||
fs_responses: Optional<&'fs_responses [u8]>,
|
fs_responses: Option<&'fs_responses [u8]>,
|
||||||
// fault_location:
|
fault_location: Option<EntityIdTlv>,
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,6 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn written_len(&self) -> usize {
|
pub fn written_len(&self) -> usize {
|
||||||
// One directive type octet, and one byte of the parameter field.
|
|
||||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,29 +295,17 @@ pub mod tests {
|
|||||||
build_metadata_opts_from_slice, build_metadata_opts_from_vec, MetadataGenericParams,
|
build_metadata_opts_from_slice, build_metadata_opts_from_vec, MetadataGenericParams,
|
||||||
MetadataPdu,
|
MetadataPdu,
|
||||||
};
|
};
|
||||||
use crate::cfdp::pdu::tests::verify_raw_header;
|
use crate::cfdp::pdu::tests::{common_pdu_conf, verify_raw_header};
|
||||||
use crate::cfdp::pdu::{CommonPduConfig, FileDirectiveType, PduHeader};
|
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
|
||||||
use crate::cfdp::tlv::{Tlv, TlvType};
|
use crate::cfdp::tlv::{Tlv, TlvType};
|
||||||
use crate::cfdp::{
|
use crate::cfdp::{
|
||||||
ChecksumType, CrcFlag, LargeFileFlag, PduType, SegmentMetadataFlag, SegmentationControl,
|
ChecksumType, CrcFlag, LargeFileFlag, PduType, SegmentMetadataFlag, SegmentationControl,
|
||||||
};
|
};
|
||||||
use crate::util::UbfU8;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
const SRC_FILENAME: &'static str = "hello-world.txt";
|
const SRC_FILENAME: &'static str = "hello-world.txt";
|
||||||
const DEST_FILENAME: &'static str = "hello-world2.txt";
|
const DEST_FILENAME: &'static str = "hello-world2.txt";
|
||||||
|
|
||||||
fn common_pdu_conf(crc_flag: CrcFlag, fss: LargeFileFlag) -> CommonPduConfig {
|
|
||||||
let src_id = UbfU8::new(5);
|
|
||||||
let dest_id = UbfU8::new(10);
|
|
||||||
let transaction_seq_num = UbfU8::new(20);
|
|
||||||
let mut pdu_conf = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_seq_num)
|
|
||||||
.expect("Generating common PDU config");
|
|
||||||
pdu_conf.crc_flag = crc_flag;
|
|
||||||
pdu_conf.file_flag = fss;
|
|
||||||
pdu_conf
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_metadata_pdu<'opts>(
|
fn generic_metadata_pdu<'opts>(
|
||||||
crc_flag: CrcFlag,
|
crc_flag: CrcFlag,
|
||||||
fss: LargeFileFlag,
|
fss: LargeFileFlag,
|
||||||
|
@ -45,12 +45,16 @@ pub enum PduError {
|
|||||||
/// The first tuple entry will be the found raw number, the second entry the expected entry
|
/// The first tuple entry will be the found raw number, the second entry the expected entry
|
||||||
/// type.
|
/// type.
|
||||||
InvalidDirectiveType((u8, FileDirectiveType)),
|
InvalidDirectiveType((u8, FileDirectiveType)),
|
||||||
|
/// Invalid condition code. Contains the raw detected value.
|
||||||
|
InvalidConditionCode(u8),
|
||||||
/// Invalid checksum type which is not part of the checksums listed in the
|
/// Invalid checksum type which is not part of the checksums listed in the
|
||||||
/// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/).
|
/// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/).
|
||||||
InvalidChecksumType(u8),
|
InvalidChecksumType(u8),
|
||||||
FileSizeTooLarge(u64),
|
FileSizeTooLarge(u64),
|
||||||
/// If the CRC flag for a PDU is enabled and the checksum check fails. Contains raw 16-bit CRC.
|
/// If the CRC flag for a PDU is enabled and the checksum check fails. Contains raw 16-bit CRC.
|
||||||
ChecksumError(u16),
|
ChecksumError(u16),
|
||||||
|
/// Error handling a TLV field.
|
||||||
|
TlvLvError(TlvLvError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for PduError {
|
impl Display for PduError {
|
||||||
@ -89,6 +93,9 @@ impl Display for PduError {
|
|||||||
PduError::WrongDirectiveType((found, expected)) => {
|
PduError::WrongDirectiveType((found, expected)) => {
|
||||||
write!(f, "found directive type {found:?}, expected {expected:?}")
|
write!(f, "found directive type {found:?}, expected {expected:?}")
|
||||||
}
|
}
|
||||||
|
PduError::InvalidConditionCode(raw_code) => {
|
||||||
|
write!(f, "found invalid condition code with raw value {raw_code}")
|
||||||
|
}
|
||||||
PduError::InvalidDirectiveType((found, expected)) => {
|
PduError::InvalidDirectiveType((found, expected)) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
@ -102,6 +109,9 @@ impl Display for PduError {
|
|||||||
PduError::ChecksumError(checksum) => {
|
PduError::ChecksumError(checksum) => {
|
||||||
write!(f, "checksum error for CRC {checksum:#04x}")
|
write!(f, "checksum error for CRC {checksum:#04x}")
|
||||||
}
|
}
|
||||||
|
PduError::TlvLvError(error) => {
|
||||||
|
write!(f, "pdu tlv error: {error}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +121,7 @@ impl Error for PduError {
|
|||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
match self {
|
match self {
|
||||||
PduError::ByteConversionError(e) => Some(e),
|
PduError::ByteConversionError(e) => Some(e),
|
||||||
|
PduError::TlvLvError(e) => Some(e),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,6 +133,12 @@ impl From<ByteConversionError> for PduError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TlvLvError> for PduError {
|
||||||
|
fn from(e: TlvLvError) -> Self {
|
||||||
|
Self::TlvLvError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Common configuration fields for a PDU.
|
/// Common configuration fields for a PDU.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
@ -514,6 +531,17 @@ mod tests {
|
|||||||
use crate::ByteConversionError;
|
use crate::ByteConversionError;
|
||||||
use std::format;
|
use std::format;
|
||||||
|
|
||||||
|
pub(crate) fn common_pdu_conf(crc_flag: CrcFlag, fss: LargeFileFlag) -> CommonPduConfig {
|
||||||
|
let src_id = UbfU8::new(5);
|
||||||
|
let dest_id = UbfU8::new(10);
|
||||||
|
let transaction_seq_num = UbfU8::new(20);
|
||||||
|
let mut pdu_conf = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_seq_num)
|
||||||
|
.expect("Generating common PDU config");
|
||||||
|
pdu_conf.crc_flag = crc_flag;
|
||||||
|
pdu_conf.file_flag = fss;
|
||||||
|
pdu_conf
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn verify_raw_header(pdu_conf: &PduHeader, buf: &[u8]) {
|
pub(crate) fn verify_raw_header(pdu_conf: &PduHeader, buf: &[u8]) {
|
||||||
assert_eq!((buf[0] >> 5) & 0b111, CFDP_VERSION_2);
|
assert_eq!((buf[0] >> 5) & 0b111, CFDP_VERSION_2);
|
||||||
// File directive
|
// File directive
|
||||||
|
@ -132,7 +132,7 @@ impl EntityIdTlv {
|
|||||||
Self { entity_id }
|
Self { entity_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len_check(buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
fn len_check(buf: &[u8]) -> Result<(), ByteConversionError> {
|
||||||
if buf.len() < 2 {
|
if buf.len() < 2 {
|
||||||
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
found: buf.len(),
|
found: buf.len(),
|
||||||
@ -142,13 +142,34 @@ impl EntityIdTlv {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
pub fn len_value(&self) -> usize {
|
||||||
|
self.entity_id.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len_full(&self) -> usize {
|
||||||
|
2 + self.entity_id.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
Self::len_check(buf)?;
|
Self::len_check(buf)?;
|
||||||
buf[0] = TlvType::EntityId as u8;
|
buf[0] = TlvType::EntityId as u8;
|
||||||
buf[1] = self.entity_id.len() as u8;
|
buf[1] = self.entity_id.len() as u8;
|
||||||
self.entity_id.write_to_be_bytes(&mut buf[2..])
|
self.entity_id.write_to_be_bytes(&mut buf[2..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(buf: &[u8]) -> Result<Self, TlvLvError> {
|
||||||
|
Self::len_check(buf)?;
|
||||||
|
TlvType::try_from(buf[0])
|
||||||
|
.map_err(|_| TlvLvError::InvalidTlvTypeField((buf[0], TlvType::EntityId as u8)))?;
|
||||||
|
let len = buf[1];
|
||||||
|
if len != 1 && len != 2 && len != 4 && len != 8 {
|
||||||
|
return Err(TlvLvError::InvalidValueLength(len));
|
||||||
|
}
|
||||||
|
// Okay to unwrap here. The checks before make sure that the deserialization never fails
|
||||||
|
let entity_id = UnsignedByteField::new_from_be_bytes(len as usize, &buf[2..]).unwrap();
|
||||||
|
Ok(Self { entity_id })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_tlv(self, buf: &mut [u8]) -> Result<Tlv, ByteConversionError> {
|
pub fn to_tlv(self, buf: &mut [u8]) -> Result<Tlv, ByteConversionError> {
|
||||||
Self::len_check(buf)?;
|
Self::len_check(buf)?;
|
||||||
self.entity_id
|
self.entity_id
|
||||||
|
@ -328,7 +328,7 @@ impl<TYPE: ToBeBytes> UnsignedEnum for GenericEcssEnumWrapper<TYPE> {
|
|||||||
(self.pfc() / 8) as usize
|
(self.pfc() / 8) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
self.field.write_to_be_bytes(buf)
|
self.field.write_to_be_bytes(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/util.rs
27
src/util.rs
@ -71,7 +71,8 @@ impl ToBeBytes for u64 {
|
|||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
pub trait UnsignedEnum {
|
pub trait UnsignedEnum {
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
|
/// Write the unsigned enumeration to a raw buffer. Returns the written size on success.
|
||||||
|
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UnsignedEnumExt: UnsignedEnum + Debug + Copy + Clone + PartialEq + Eq {}
|
pub trait UnsignedEnumExt: UnsignedEnum + Debug + Copy + Clone + PartialEq + Eq {}
|
||||||
@ -163,7 +164,7 @@ impl UnsignedEnum for UnsignedByteField {
|
|||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
if buf.len() < self.len() {
|
if buf.len() < self.len() {
|
||||||
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
expected: self.len(),
|
expected: self.len(),
|
||||||
@ -171,7 +172,7 @@ impl UnsignedEnum for UnsignedByteField {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
match self.len() {
|
match self.len() {
|
||||||
0 => Ok(()),
|
0 => Ok(0),
|
||||||
1 => {
|
1 => {
|
||||||
let u8 = UnsignedByteFieldU8::try_from(*self).unwrap();
|
let u8 = UnsignedByteFieldU8::try_from(*self).unwrap();
|
||||||
u8.write_to_be_bytes(buf)
|
u8.write_to_be_bytes(buf)
|
||||||
@ -213,7 +214,7 @@ impl<TYPE: ToBeBytes> UnsignedEnum for GenericUnsignedByteField<TYPE> {
|
|||||||
self.value.written_len()
|
self.value.written_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
if buf.len() < self.len() {
|
if buf.len() < self.len() {
|
||||||
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
found: buf.len(),
|
found: buf.len(),
|
||||||
@ -221,7 +222,7 @@ impl<TYPE: ToBeBytes> UnsignedEnum for GenericUnsignedByteField<TYPE> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
buf[0..self.len()].copy_from_slice(self.value.to_be_bytes().as_ref());
|
buf[0..self.len()].copy_from_slice(self.value.to_be_bytes().as_ref());
|
||||||
Ok(())
|
Ok(self.value.written_len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,8 +319,10 @@ pub mod tests {
|
|||||||
let u8 = UnsignedByteFieldU8::new(5);
|
let u8 = UnsignedByteFieldU8::new(5);
|
||||||
assert_eq!(u8.len(), 1);
|
assert_eq!(u8.len(), 1);
|
||||||
let mut buf: [u8; 8] = [0; 8];
|
let mut buf: [u8; 8] = [0; 8];
|
||||||
u8.write_to_be_bytes(&mut buf)
|
let len = u8
|
||||||
|
.write_to_be_bytes(&mut buf)
|
||||||
.expect("writing to raw buffer failed");
|
.expect("writing to raw buffer failed");
|
||||||
|
assert_eq!(len, 1);
|
||||||
assert_eq!(buf[0], 5);
|
assert_eq!(buf[0], 5);
|
||||||
for i in 1..8 {
|
for i in 1..8 {
|
||||||
assert_eq!(buf[i], 0);
|
assert_eq!(buf[i], 0);
|
||||||
@ -331,8 +334,10 @@ pub mod tests {
|
|||||||
let u16 = UnsignedByteFieldU16::new(3823);
|
let u16 = UnsignedByteFieldU16::new(3823);
|
||||||
assert_eq!(u16.len(), 2);
|
assert_eq!(u16.len(), 2);
|
||||||
let mut buf: [u8; 8] = [0; 8];
|
let mut buf: [u8; 8] = [0; 8];
|
||||||
u16.write_to_be_bytes(&mut buf)
|
let len = u16
|
||||||
|
.write_to_be_bytes(&mut buf)
|
||||||
.expect("writing to raw buffer failed");
|
.expect("writing to raw buffer failed");
|
||||||
|
assert_eq!(len, 2);
|
||||||
let raw_val = u16::from_be_bytes(buf[0..2].try_into().unwrap());
|
let raw_val = u16::from_be_bytes(buf[0..2].try_into().unwrap());
|
||||||
assert_eq!(raw_val, 3823);
|
assert_eq!(raw_val, 3823);
|
||||||
for i in 2..8 {
|
for i in 2..8 {
|
||||||
@ -345,8 +350,10 @@ pub mod tests {
|
|||||||
let u32 = UnsignedByteFieldU32::new(80932);
|
let u32 = UnsignedByteFieldU32::new(80932);
|
||||||
assert_eq!(u32.len(), 4);
|
assert_eq!(u32.len(), 4);
|
||||||
let mut buf: [u8; 8] = [0; 8];
|
let mut buf: [u8; 8] = [0; 8];
|
||||||
u32.write_to_be_bytes(&mut buf)
|
let len = u32
|
||||||
|
.write_to_be_bytes(&mut buf)
|
||||||
.expect("writing to raw buffer failed");
|
.expect("writing to raw buffer failed");
|
||||||
|
assert_eq!(len, 4);
|
||||||
let raw_val = u32::from_be_bytes(buf[0..4].try_into().unwrap());
|
let raw_val = u32::from_be_bytes(buf[0..4].try_into().unwrap());
|
||||||
assert_eq!(raw_val, 80932);
|
assert_eq!(raw_val, 80932);
|
||||||
for i in 4..8 {
|
for i in 4..8 {
|
||||||
@ -359,8 +366,10 @@ pub mod tests {
|
|||||||
let u64 = UnsignedByteFieldU64::new(5999999);
|
let u64 = UnsignedByteFieldU64::new(5999999);
|
||||||
assert_eq!(u64.len(), 8);
|
assert_eq!(u64.len(), 8);
|
||||||
let mut buf: [u8; 8] = [0; 8];
|
let mut buf: [u8; 8] = [0; 8];
|
||||||
u64.write_to_be_bytes(&mut buf)
|
let len = u64
|
||||||
|
.write_to_be_bytes(&mut buf)
|
||||||
.expect("writing to raw buffer failed");
|
.expect("writing to raw buffer failed");
|
||||||
|
assert_eq!(len, 8);
|
||||||
let raw_val = u64::from_be_bytes(buf[0..8].try_into().unwrap());
|
let raw_val = u64::from_be_bytes(buf[0..8].try_into().unwrap());
|
||||||
assert_eq!(raw_val, 5999999);
|
assert_eq!(raw_val, 5999999);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user