base line EOF model
This commit is contained in:
parent
0b714b7426
commit
912c03b5c7
@ -140,6 +140,10 @@ pub const NULL_CHECKSUM_U32: [u8; 4] = [0; 4];
|
|||||||
pub enum TlvLvError {
|
pub enum TlvLvError {
|
||||||
DataTooLarge(usize),
|
DataTooLarge(usize),
|
||||||
ByteConversionError(ByteConversionError),
|
ByteConversionError(ByteConversionError),
|
||||||
|
/// First value: Found value. Second value: Expected value.
|
||||||
|
InvalidTlvTypeField((u8, u8)),
|
||||||
|
/// Logically invalid value length detected.
|
||||||
|
InvalidValueLength(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ByteConversionError> for TlvLvError {
|
impl From<ByteConversionError> for TlvLvError {
|
||||||
@ -162,6 +166,15 @@ impl Display for TlvLvError {
|
|||||||
TlvLvError::ByteConversionError(e) => {
|
TlvLvError::ByteConversionError(e) => {
|
||||||
write!(f, "{}", e)
|
write!(f, "{}", e)
|
||||||
}
|
}
|
||||||
|
TlvLvError::InvalidTlvTypeField((found, expected)) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"invalid TLV type field, found {found}, expected {expected}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TlvLvError::InvalidValueLength(len) => {
|
||||||
|
write!(f, "invalid value length {len} detected")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
use crate::cfdp::tlv::EntityIdTlv;
|
||||||
|
use crate::cfdp::ConditionCode;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct EofPdu {
|
||||||
|
condition_code: ConditionCode,
|
||||||
|
file_checksum: u32,
|
||||||
|
file_size: u64,
|
||||||
|
fault_location: Option<EntityIdTlv>,
|
||||||
|
}
|
@ -32,7 +32,7 @@ pub fn build_metadata_opts_from_slice(
|
|||||||
) -> Result<usize, ByteConversionError> {
|
) -> Result<usize, ByteConversionError> {
|
||||||
let mut written = 0;
|
let mut written = 0;
|
||||||
for tlv in tlvs {
|
for tlv in tlvs {
|
||||||
written += tlv.write_to_be_bytes(&mut buf[written..])?;
|
written += tlv.write_to_bytes(&mut buf[written..])?;
|
||||||
}
|
}
|
||||||
Ok(written)
|
Ok(written)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use core::fmt::{Display, Formatter};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub mod eof;
|
||||||
pub mod file_data;
|
pub mod file_data;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ use crate::cfdp::lv::{
|
|||||||
generic_len_check_data_serialization, generic_len_check_deserialization, Lv, MIN_LV_LEN,
|
generic_len_check_data_serialization, generic_len_check_deserialization, Lv, MIN_LV_LEN,
|
||||||
};
|
};
|
||||||
use crate::cfdp::TlvLvError;
|
use crate::cfdp::TlvLvError;
|
||||||
use crate::ByteConversionError;
|
use crate::util::{UnsignedByteField, UnsignedByteFieldError, UnsignedEnum};
|
||||||
|
use crate::{ByteConversionError, SizeMissmatch};
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -81,7 +82,7 @@ impl<'data> Tlv<'data> {
|
|||||||
self.tlv_type_field
|
self.tlv_type_field
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
generic_len_check_data_serialization(buf, self.len_value(), MIN_TLV_LEN)?;
|
generic_len_check_data_serialization(buf, self.len_value(), MIN_TLV_LEN)?;
|
||||||
buf[0] = self.tlv_type_field.into();
|
buf[0] = self.tlv_type_field.into();
|
||||||
self.lv.write_to_be_bytes_no_len_check(&mut buf[1..]);
|
self.lv.write_to_be_bytes_no_len_check(&mut buf[1..]);
|
||||||
@ -120,6 +121,85 @@ impl<'data> Tlv<'data> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct EntityIdTlv {
|
||||||
|
entity_id: UnsignedByteField,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityIdTlv {
|
||||||
|
pub fn new(entity_id: UnsignedByteField) -> Self {
|
||||||
|
Self { entity_id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len_check(buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
||||||
|
if buf.len() < 2 {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: 2,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
|
||||||
|
Self::len_check(buf)?;
|
||||||
|
buf[0] = TlvType::EntityId as u8;
|
||||||
|
buf[1] = self.entity_id.len() as u8;
|
||||||
|
self.entity_id.write_to_be_bytes(&mut buf[2..])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_tlv(self, buf: &mut [u8]) -> Result<Tlv, ByteConversionError> {
|
||||||
|
Self::len_check(buf)?;
|
||||||
|
self.entity_id
|
||||||
|
.write_to_be_bytes(&mut buf[2..2 + self.entity_id.len()])?;
|
||||||
|
Tlv::new(TlvType::EntityId, &buf[2..2 + self.entity_id.len()]).map_err(|e| match e {
|
||||||
|
TlvLvError::ByteConversionError(e) => e,
|
||||||
|
// All other errors are impossible.
|
||||||
|
_ => panic!("unexpected TLV error"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'data> TryFrom<Tlv<'data>> for EntityIdTlv {
|
||||||
|
type Error = TlvLvError;
|
||||||
|
|
||||||
|
fn try_from(value: Tlv) -> Result<Self, Self::Error> {
|
||||||
|
match value.tlv_type_field {
|
||||||
|
TlvTypeField::Standard(tlv_type) => {
|
||||||
|
if tlv_type != TlvType::EntityId {
|
||||||
|
return Err(TlvLvError::InvalidTlvTypeField((
|
||||||
|
tlv_type as u8,
|
||||||
|
TlvType::EntityId as u8,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TlvTypeField::Custom(val) => {
|
||||||
|
return Err(TlvLvError::InvalidTlvTypeField((
|
||||||
|
val,
|
||||||
|
TlvType::EntityId as u8,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if value.len_value() != 1
|
||||||
|
&& value.len_value() != 2
|
||||||
|
&& value.len_value() != 4
|
||||||
|
&& value.len_value() != 8
|
||||||
|
{
|
||||||
|
return Err(TlvLvError::InvalidValueLength(value.len_value() as u8));
|
||||||
|
}
|
||||||
|
Ok(Self::new(
|
||||||
|
UnsignedByteField::new_from_be_bytes(value.len_value(), value.value().unwrap())
|
||||||
|
.map_err(|e| match e {
|
||||||
|
UnsignedByteFieldError::ByteConversionError(e) => e,
|
||||||
|
// This can not happen, we checked for the length validity, and the data is always smaller than
|
||||||
|
// 255 bytes.
|
||||||
|
_ => panic!("unexpected error"),
|
||||||
|
})?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::cfdp::tlv::{Tlv, TlvType, TlvTypeField};
|
use crate::cfdp::tlv::{Tlv, TlvType, TlvTypeField};
|
||||||
@ -154,7 +234,7 @@ mod tests {
|
|||||||
assert!(tlv_res.is_ok());
|
assert!(tlv_res.is_ok());
|
||||||
let tlv_res = tlv_res.unwrap();
|
let tlv_res = tlv_res.unwrap();
|
||||||
let mut ser_buf: [u8; 4] = [0; 4];
|
let mut ser_buf: [u8; 4] = [0; 4];
|
||||||
assert!(tlv_res.write_to_be_bytes(&mut ser_buf).is_ok());
|
assert!(tlv_res.write_to_bytes(&mut ser_buf).is_ok());
|
||||||
assert_eq!(ser_buf[0], TlvType::EntityId as u8);
|
assert_eq!(ser_buf[0], TlvType::EntityId as u8);
|
||||||
assert_eq!(ser_buf[1], 1);
|
assert_eq!(ser_buf[1], 1);
|
||||||
assert_eq!(ser_buf[2], 5);
|
assert_eq!(ser_buf[2], 5);
|
||||||
@ -197,7 +277,7 @@ mod tests {
|
|||||||
fn test_empty_serialization() {
|
fn test_empty_serialization() {
|
||||||
let tlv_empty = Tlv::new_empty(TlvType::MsgToUser);
|
let tlv_empty = Tlv::new_empty(TlvType::MsgToUser);
|
||||||
let mut buf: [u8; 4] = [0; 4];
|
let mut buf: [u8; 4] = [0; 4];
|
||||||
assert!(tlv_empty.write_to_be_bytes(&mut buf).is_ok());
|
assert!(tlv_empty.write_to_bytes(&mut buf).is_ok());
|
||||||
assert_eq!(buf[0], TlvType::MsgToUser as u8);
|
assert_eq!(buf[0], TlvType::MsgToUser as u8);
|
||||||
assert_eq!(buf[1], 0);
|
assert_eq!(buf[1], 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user