Skip to content

Commit

Permalink
Merge pull request 'add owned TLV type' (#98) from cfdp-tlv-owned-typ…
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Jul 9, 2024
2 parents a399b11 + 81423fc commit c40bc85
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 83 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

# [unreleased]

# [v0.11.3] 2024-06-25
# [v0.12.0]

- Minor documentation build updates.

## Added

- 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 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.
- Replaced `cfdp::tlv::TlvLvError` by `cfdp::tlv::TlvLvDataTooLarge` where applicable.

# [v0.11.2] 2024-05-19

- Bumped MSRV to 1.68.2
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "spacepackets"
version = "0.11.3"
version = "0.12.0"
edition = "2021"
rust-version = "1.68.2"
authors = ["Robin Mueller <[email protected]>"]
Expand Down Expand Up @@ -60,7 +60,7 @@ chrono = "0.4"
default = ["std"]
std = ["chrono/std", "chrono/clock", "alloc", "thiserror"]
serde = ["dep:serde", "chrono/serde"]
alloc = ["postcard/alloc", "chrono/alloc"]
alloc = ["postcard/alloc", "chrono/alloc", "defmt/alloc", "serde/alloc"]
chrono = ["dep:chrono"]
timelib = ["dep:time"]
defmt = ["dep:defmt"]
Expand Down
29 changes: 13 additions & 16 deletions src/cfdp/lv.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
use crate::cfdp::TlvLvError;
use crate::ByteConversionError;
use core::str::Utf8Error;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::string::String;

use super::TlvLvDataTooLarge;

pub const MIN_LV_LEN: usize = 1;

/// Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
Expand Down Expand Up @@ -63,9 +64,9 @@ pub(crate) fn generic_len_check_deserialization(

impl<'data> Lv<'data> {
#[inline]
pub fn new(data: &[u8]) -> Result<Lv, TlvLvError> {
pub fn new(data: &[u8]) -> Result<Lv, TlvLvDataTooLarge> {
if data.len() > u8::MAX as usize {
return Err(TlvLvError::DataTooLarge(data.len()));
return Err(TlvLvDataTooLarge(data.len()));
}
Ok(Lv {
data,
Expand All @@ -85,15 +86,15 @@ 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> {
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvDataTooLarge> {
Self::new(str_slice.as_bytes())
}

/// 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> {
pub fn new_from_string(string: &'data String) -> Result<Lv<'data>, TlvLvDataTooLarge> {
Self::new(string.as_bytes())
}

Expand Down Expand Up @@ -177,10 +178,10 @@ impl<'data> Lv<'data> {

#[cfg(test)]
pub mod tests {
use super::*;
use alloc::string::ToString;

use crate::cfdp::TlvLvError;
use super::*;

use crate::ByteConversionError;
use std::string::String;

Expand Down Expand Up @@ -271,15 +272,11 @@ pub mod tests {
let lv = Lv::new(&data_big);
assert!(lv.is_err());
let error = lv.unwrap_err();
if let TlvLvError::DataTooLarge(size) = error {
assert_eq!(size, u8::MAX as usize + 1);
assert_eq!(
error.to_string(),
"data with size 256 larger than allowed 255 bytes"
);
} else {
panic!("invalid exception {:?}", error)
}
assert_eq!(error.0, u8::MAX as usize + 1);
assert_eq!(
error.to_string(),
"data with size 256 larger than allowed 255 bytes"
);
}

#[test]
Expand Down
37 changes: 29 additions & 8 deletions src/cfdp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,30 @@ impl Default for ChecksumType {

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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TlvLvError {
DataTooLarge(usize),
DataTooLarge(TlvLvDataTooLarge),
ByteConversion(ByteConversionError),
/// First value: Found value. Second value: Expected value if there is one.
InvalidTlvTypeField {
Expand All @@ -197,6 +216,12 @@ pub enum TlvLvError {
InvalidFilestoreActionCode(u8),
}

impl From<TlvLvDataTooLarge> for TlvLvError {
fn from(value: TlvLvDataTooLarge) -> Self {
Self::DataTooLarge(value)
}
}

impl From<ByteConversionError> for TlvLvError {
fn from(value: ByteConversionError) -> Self {
Self::ByteConversion(value)
Expand All @@ -206,13 +231,8 @@ impl From<ByteConversionError> for TlvLvError {
impl Display for TlvLvError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
TlvLvError::DataTooLarge(data_len) => {
write!(
f,
"data with size {} larger than allowed {} bytes",
data_len,
u8::MAX
)
TlvLvError::DataTooLarge(e) => {
write!(f, "{}", e)
}
TlvLvError::ByteConversion(e) => {
write!(f, "tlv or lv byte conversion: {}", e)
Expand Down Expand Up @@ -240,6 +260,7 @@ impl Display for TlvLvError {
impl Error for TlvLvError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
TlvLvError::DataTooLarge(e) => Some(e),
TlvLvError::ByteConversion(e) => Some(e),
_ => None,
}
Expand Down
1 change: 1 addition & 0 deletions src/cfdp/pdu/finished.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::tlv::ReadableTlv;
use super::{CfdpPdu, WritablePduPacket};

#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
Expand Down
3 changes: 2 additions & 1 deletion src/cfdp/pdu/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use super::tlv::ReadableTlv;
use super::{CfdpPdu, WritablePduPacket};

#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -354,7 +355,7 @@ pub mod tests {
};
use crate::cfdp::pdu::{CfdpPdu, PduError, WritablePduPacket};
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
use crate::cfdp::tlv::{Tlv, TlvType};
use crate::cfdp::tlv::{ReadableTlv, Tlv, TlvType};
use crate::cfdp::{
ChecksumType, CrcFlag, Direction, LargeFileFlag, PduType, SegmentMetadataFlag,
SegmentationControl, TransmissionMode,
Expand Down
Loading

0 comments on commit c40bc85

Please sign in to comment.