improve error handling, add as_tlv method for TlvOwned
This commit is contained in:
parent
e0cd096460
commit
2a4dc666d8
@ -13,11 +13,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Added new `cfdp::tlv::TlvOwned` type which erases the lifetime and is clonable.
|
- Added new `cfdp::tlv::TlvOwned` type which erases the lifetime and is clonable.
|
||||||
|
- Dedicated `cfdp::tlv::TlvLvDataTooLarge` error struct for APIs where this is the only possible
|
||||||
|
API error.
|
||||||
|
|
||||||
## Added and Changed
|
## Added and Changed
|
||||||
|
|
||||||
- Added new `ReadableTlv` to avoid some boilerplate code and have a common abstraction implemented
|
- Added new `ReadableTlv` to avoid some boilerplate code and have a common abstraction implemented
|
||||||
for both `Tlv` and `TlvOwned` to read the raw TLV data field and its length.
|
for both `Tlv` and `TlvOwned` to read the raw TLV data field and its length.
|
||||||
|
- Replaced `cfdp::tlv::TlvLvError` by `cfdp::tlv::TlvLvDataTooLarge` where applicable.
|
||||||
|
|
||||||
# [v0.11.2] 2024-05-19
|
# [v0.11.2] 2024-05-19
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
//! Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
|
//! Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
|
||||||
use crate::cfdp::TlvLvError;
|
|
||||||
use crate::ByteConversionError;
|
use crate::ByteConversionError;
|
||||||
use core::str::Utf8Error;
|
use core::str::Utf8Error;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -7,6 +6,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
|
|
||||||
|
use super::TlvLvDataTooLarge;
|
||||||
|
|
||||||
pub const MIN_LV_LEN: usize = 1;
|
pub const MIN_LV_LEN: usize = 1;
|
||||||
|
|
||||||
/// Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
|
/// Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
|
||||||
@ -63,9 +64,9 @@ pub(crate) fn generic_len_check_deserialization(
|
|||||||
|
|
||||||
impl<'data> Lv<'data> {
|
impl<'data> Lv<'data> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(data: &[u8]) -> Result<Lv, TlvLvError> {
|
pub fn new(data: &[u8]) -> Result<Lv, TlvLvDataTooLarge> {
|
||||||
if data.len() > u8::MAX as usize {
|
if data.len() > u8::MAX as usize {
|
||||||
return Err(TlvLvError::DataTooLarge(data.len()));
|
return Err(TlvLvDataTooLarge(data.len()));
|
||||||
}
|
}
|
||||||
Ok(Lv {
|
Ok(Lv {
|
||||||
data,
|
data,
|
||||||
@ -85,7 +86,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]
|
#[inline]
|
||||||
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvError> {
|
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvDataTooLarge> {
|
||||||
Self::new(str_slice.as_bytes())
|
Self::new(str_slice.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ impl<'data> Lv<'data> {
|
|||||||
/// path LVs
|
/// path LVs
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvError> {
|
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvDataTooLarge> {
|
||||||
Self::new(string.as_bytes())
|
Self::new(string.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +179,6 @@ impl<'data> Lv<'data> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
use crate::cfdp::TlvLvError;
|
use crate::cfdp::TlvLvError;
|
||||||
use crate::ByteConversionError;
|
use crate::ByteConversionError;
|
||||||
@ -271,7 +271,7 @@ pub mod tests {
|
|||||||
let lv = Lv::new(&data_big);
|
let lv = Lv::new(&data_big);
|
||||||
assert!(lv.is_err());
|
assert!(lv.is_err());
|
||||||
let error = lv.unwrap_err();
|
let error = lv.unwrap_err();
|
||||||
if let TlvLvError::DataTooLarge(size) = error {
|
if let TlvLvDataTooLarge(size) = error {
|
||||||
assert_eq!(size, u8::MAX as usize + 1);
|
assert_eq!(size, u8::MAX as usize + 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.to_string(),
|
error.to_string(),
|
||||||
|
@ -176,11 +176,30 @@ impl Default for ChecksumType {
|
|||||||
|
|
||||||
pub const NULL_CHECKSUM_U32: [u8; 4] = [0; 4];
|
pub const NULL_CHECKSUM_U32: [u8; 4] = [0; 4];
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub struct TlvLvDataTooLarge(pub usize);
|
||||||
|
|
||||||
|
impl Display for TlvLvDataTooLarge {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"data with size {} larger than allowed {} bytes",
|
||||||
|
self.0,
|
||||||
|
u8::MAX
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Error for TlvLvDataTooLarge {}
|
||||||
|
|
||||||
#[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))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum TlvLvError {
|
pub enum TlvLvError {
|
||||||
DataTooLarge(usize),
|
DataTooLarge(TlvLvDataTooLarge),
|
||||||
ByteConversion(ByteConversionError),
|
ByteConversion(ByteConversionError),
|
||||||
/// First value: Found value. Second value: Expected value if there is one.
|
/// First value: Found value. Second value: Expected value if there is one.
|
||||||
InvalidTlvTypeField {
|
InvalidTlvTypeField {
|
||||||
@ -197,6 +216,12 @@ pub enum TlvLvError {
|
|||||||
InvalidFilestoreActionCode(u8),
|
InvalidFilestoreActionCode(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TlvLvDataTooLarge> for TlvLvError {
|
||||||
|
fn from(value: TlvLvDataTooLarge) -> Self {
|
||||||
|
Self::DataTooLarge(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<ByteConversionError> for TlvLvError {
|
impl From<ByteConversionError> for TlvLvError {
|
||||||
fn from(value: ByteConversionError) -> Self {
|
fn from(value: ByteConversionError) -> Self {
|
||||||
Self::ByteConversion(value)
|
Self::ByteConversion(value)
|
||||||
@ -206,13 +231,8 @@ impl From<ByteConversionError> for TlvLvError {
|
|||||||
impl Display for TlvLvError {
|
impl Display for TlvLvError {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
TlvLvError::DataTooLarge(data_len) => {
|
TlvLvError::DataTooLarge(e) => {
|
||||||
write!(
|
write!(f, "{}", e)
|
||||||
f,
|
|
||||||
"data with size {} larger than allowed {} bytes",
|
|
||||||
data_len,
|
|
||||||
u8::MAX
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TlvLvError::ByteConversion(e) => {
|
TlvLvError::ByteConversion(e) => {
|
||||||
write!(f, "tlv or lv byte conversion: {}", e)
|
write!(f, "tlv or lv byte conversion: {}", e)
|
||||||
@ -240,6 +260,7 @@ impl Display for TlvLvError {
|
|||||||
impl Error for TlvLvError {
|
impl Error for TlvLvError {
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
match self {
|
match self {
|
||||||
|
TlvLvError::DataTooLarge(e) => Some(e),
|
||||||
TlvLvError::ByteConversion(e) => Some(e),
|
TlvLvError::ByteConversion(e) => Some(e),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::TlvLvDataTooLarge;
|
||||||
|
|
||||||
pub mod msg_to_user;
|
pub mod msg_to_user;
|
||||||
|
|
||||||
pub const MIN_TLV_LEN: usize = 2;
|
pub const MIN_TLV_LEN: usize = 2;
|
||||||
@ -151,14 +153,14 @@ pub struct Tlv<'data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> Tlv<'data> {
|
impl<'data> Tlv<'data> {
|
||||||
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv, TlvLvError> {
|
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv, TlvLvDataTooLarge> {
|
||||||
Ok(Tlv {
|
Ok(Tlv {
|
||||||
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
||||||
lv: Lv::new(data)?,
|
lv: Lv::new(data)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_custom_type(tlv_type: u8, data: &[u8]) -> Result<Tlv, TlvLvError> {
|
pub fn new_with_custom_type(tlv_type: u8, data: &[u8]) -> Result<Tlv, TlvLvDataTooLarge> {
|
||||||
Ok(Tlv {
|
Ok(Tlv {
|
||||||
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
||||||
lv: Lv::new(data)?,
|
lv: Lv::new(data)?,
|
||||||
@ -237,6 +239,8 @@ impl GenericTlv for Tlv<'_> {
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub mod alloc_mod {
|
pub mod alloc_mod {
|
||||||
|
use crate::cfdp::TlvLvDataTooLarge;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Owned variant of [Tlv] which is consequently [Clone]able and does not have a lifetime
|
/// Owned variant of [Tlv] which is consequently [Clone]able and does not have a lifetime
|
||||||
@ -250,18 +254,24 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TlvOwned {
|
impl TlvOwned {
|
||||||
pub fn new(tlv_type: TlvType, data: &[u8]) -> Self {
|
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Self, TlvLvDataTooLarge> {
|
||||||
Self {
|
if data.len() > u8::MAX as usize {
|
||||||
|
return Err(TlvLvDataTooLarge(data.len()));
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
||||||
data: data.to_vec(),
|
data: data.to_vec(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_custom_type(tlv_type: u8, data: &[u8]) -> Self {
|
pub fn new_with_custom_type(tlv_type: u8, data: &[u8]) -> Result<Self, TlvLvDataTooLarge> {
|
||||||
Self {
|
if data.len() > u8::MAX as usize {
|
||||||
|
return Err(TlvLvDataTooLarge(data.len()));
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
||||||
data: data.to_vec(),
|
data: data.to_vec(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a TLV with an empty value field.
|
/// Creates a TLV with an empty value field.
|
||||||
@ -271,6 +281,15 @@ pub mod alloc_mod {
|
|||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_tlv(&self) -> Tlv<'_> {
|
||||||
|
Tlv {
|
||||||
|
tlv_type_field: self.tlv_type_field,
|
||||||
|
// The API should ensure that the data length is never to large, so the unwrap for the
|
||||||
|
// LV creation should never be an issue.
|
||||||
|
lv: Lv::new(&self.data).expect("lv creation failed unexpectedly"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadableTlv for TlvOwned {
|
impl ReadableTlv for TlvOwned {
|
||||||
@ -324,7 +343,7 @@ impl EntityIdTlv {
|
|||||||
Self { entity_id }
|
Self { entity_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len_check(buf: &[u8]) -> Result<(), ByteConversionError> {
|
fn check_min_len(buf: &[u8]) -> Result<(), ByteConversionError> {
|
||||||
if buf.len() < 2 {
|
if buf.len() < 2 {
|
||||||
return Err(ByteConversionError::ToSliceTooSmall {
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
found: buf.len(),
|
found: buf.len(),
|
||||||
@ -347,7 +366,7 @@ impl EntityIdTlv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_bytes(buf: &[u8]) -> Result<Self, TlvLvError> {
|
pub fn from_bytes(buf: &[u8]) -> Result<Self, TlvLvError> {
|
||||||
Self::len_check(buf)?;
|
Self::check_min_len(buf)?;
|
||||||
verify_tlv_type(buf[0], TlvType::EntityId)?;
|
verify_tlv_type(buf[0], TlvType::EntityId)?;
|
||||||
let len = buf[1];
|
let len = buf[1];
|
||||||
if len != 1 && len != 2 && len != 4 && len != 8 {
|
if len != 1 && len != 2 && len != 4 && len != 8 {
|
||||||
@ -360,25 +379,29 @@ impl EntityIdTlv {
|
|||||||
|
|
||||||
/// Convert to a generic [Tlv], which also erases the type information.
|
/// Convert to a generic [Tlv], which also erases the type information.
|
||||||
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::check_min_len(buf)?;
|
||||||
self.entity_id
|
self.entity_id
|
||||||
.write_to_be_bytes(&mut buf[2..2 + self.entity_id.size()])?;
|
.write_to_be_bytes(&mut buf[2..2 + self.entity_id.size()])?;
|
||||||
Tlv::new(TlvType::EntityId, &buf[2..2 + self.entity_id.size()]).map_err(|e| match e {
|
if buf.len() < self.len_value() {
|
||||||
TlvLvError::ByteConversion(e) => e,
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
// All other errors are impossible.
|
found: buf.len(),
|
||||||
_ => panic!("unexpected TLV error"),
|
expected: self.len_value(),
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
// We performed all checks necessary to ensure this call never panics.
|
||||||
|
Ok(Tlv::new(TlvType::EntityId, &buf[2..2 + self.entity_id.size()]).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn to_owned(&self) -> TlvOwned {
|
pub fn to_owned(&self) -> TlvOwned {
|
||||||
TlvOwned::new(TlvType::EntityId, &self.entity_id.to_vec())
|
// Unwrap is okay here, entity ID should never be larger than maximum allowed size.
|
||||||
|
TlvOwned::new(TlvType::EntityId, &self.entity_id.to_vec()).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WritableTlv for EntityIdTlv {
|
impl WritableTlv for EntityIdTlv {
|
||||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
Self::len_check(buf)?;
|
Self::check_min_len(buf)?;
|
||||||
buf[0] = TlvType::EntityId as u8;
|
buf[0] = TlvType::EntityId as u8;
|
||||||
buf[1] = self.entity_id.size() as u8;
|
buf[1] = self.entity_id.size() as u8;
|
||||||
Ok(2 + self.entity_id.write_to_be_bytes(&mut buf[2..])?)
|
Ok(2 + self.entity_id.write_to_be_bytes(&mut buf[2..])?)
|
||||||
@ -620,7 +643,8 @@ impl<'first_name, 'second_name> FilestoreRequestTlv<'first_name, 'second_name> {
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn to_owned(&self) -> TlvOwned {
|
pub fn to_owned(&self) -> TlvOwned {
|
||||||
TlvOwned::new(TlvType::FilestoreRequest, &self.to_vec()[2..])
|
// The API should ensure the data field is never too large, so unwrapping here is okay.
|
||||||
|
TlvOwned::new(TlvType::FilestoreRequest, &self.to_vec()[2..]).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,7 +834,8 @@ impl<'first_name, 'second_name, 'fs_msg> FilestoreResponseTlv<'first_name, 'seco
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn to_owned(&self) -> TlvOwned {
|
pub fn to_owned(&self) -> TlvOwned {
|
||||||
TlvOwned::new(TlvType::FilestoreResponse, &self.to_vec()[2..])
|
// The API should ensure the data field is never too large, so unwrap is okay here.
|
||||||
|
TlvOwned::new(TlvType::FilestoreResponse, &self.to_vec()[2..]).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1054,15 +1079,11 @@ mod tests {
|
|||||||
let tlv_res = Tlv::new(TlvType::MsgToUser, &buf_too_large);
|
let tlv_res = Tlv::new(TlvType::MsgToUser, &buf_too_large);
|
||||||
assert!(tlv_res.is_err());
|
assert!(tlv_res.is_err());
|
||||||
let error = tlv_res.unwrap_err();
|
let error = tlv_res.unwrap_err();
|
||||||
if let TlvLvError::DataTooLarge(size) = error {
|
assert_eq!(error.0, u8::MAX as usize + 1);
|
||||||
assert_eq!(size, u8::MAX as usize + 1);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.to_string(),
|
error.to_string(),
|
||||||
"data with size 256 larger than allowed 255 bytes"
|
"data with size 256 larger than allowed 255 bytes"
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
panic!("unexpected error {:?}", error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1436,7 +1457,7 @@ mod tests {
|
|||||||
let entity_id = UbfU8::new(5);
|
let entity_id = UbfU8::new(5);
|
||||||
let mut buf: [u8; 4] = [0; 4];
|
let mut buf: [u8; 4] = [0; 4];
|
||||||
assert!(entity_id.write_to_be_bytes(&mut buf).is_ok());
|
assert!(entity_id.write_to_be_bytes(&mut buf).is_ok());
|
||||||
let tlv_res = TlvOwned::new(TlvType::EntityId, &buf[0..1]);
|
let tlv_res = TlvOwned::new(TlvType::EntityId, &buf[0..1]).expect("creating TLV failed");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tlv_res.tlv_type_field(),
|
tlv_res.tlv_type_field(),
|
||||||
TlvTypeField::Standard(TlvType::EntityId)
|
TlvTypeField::Standard(TlvType::EntityId)
|
||||||
@ -1463,7 +1484,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_owned_tlv_custom_type() {
|
fn test_owned_tlv_custom_type() {
|
||||||
let tlv_res = TlvOwned::new_with_custom_type(32, &[]);
|
let tlv_res = TlvOwned::new_with_custom_type(32, &[]).unwrap();
|
||||||
assert_eq!(tlv_res.tlv_type_field(), TlvTypeField::Custom(32));
|
assert_eq!(tlv_res.tlv_type_field(), TlvTypeField::Custom(32));
|
||||||
assert_eq!(tlv_res.len_full(), 2);
|
assert_eq!(tlv_res.len_full(), 2);
|
||||||
assert_eq!(tlv_res.value().len(), 0);
|
assert_eq!(tlv_res.value().len(), 0);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use super::TlvOwned;
|
use super::TlvOwned;
|
||||||
use super::{GenericTlv, ReadableTlv, Tlv, TlvLvError, TlvType, TlvTypeField, WritableTlv};
|
use super::{GenericTlv, ReadableTlv, Tlv, TlvLvError, TlvType, TlvTypeField, WritableTlv};
|
||||||
use crate::ByteConversionError;
|
use crate::{cfdp::TlvLvDataTooLarge, ByteConversionError};
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -12,7 +12,7 @@ pub struct MsgToUserTlv<'data> {
|
|||||||
|
|
||||||
impl<'data> MsgToUserTlv<'data> {
|
impl<'data> MsgToUserTlv<'data> {
|
||||||
/// Create a new message to user TLV where the type field is set correctly.
|
/// Create a new message to user TLV where the type field is set correctly.
|
||||||
pub fn new(value: &'data [u8]) -> Result<MsgToUserTlv<'data>, TlvLvError> {
|
pub fn new(value: &'data [u8]) -> Result<MsgToUserTlv<'data>, TlvLvDataTooLarge> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tlv: Tlv::new(TlvType::MsgToUser, value)?,
|
tlv: Tlv::new(TlvType::MsgToUser, value)?,
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user