Add ACK and NAK PDU abstractions #41
@ -9,10 +9,182 @@ use super::{
|
|||||||
add_pdu_crc, generic_length_checks_pdu_deserialization, CfdpPdu, FileDirectiveType, PduError,
|
add_pdu_crc, generic_length_checks_pdu_deserialization, CfdpPdu, FileDirectiveType, PduError,
|
||||||
PduHeader, WritablePduPacket,
|
PduHeader, WritablePduPacket,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Special iterator type for the NAK PDU which allows to iterator over both normal and large file
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
pub enum SegmentRequests<'a> {
|
||||||
|
U32Pairs(&'a [(u32, u32)]),
|
||||||
|
U64Pairs(&'a [(u64, u64)]),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NAK PDU abstraction specialized in the creation of NAK PDUs.
|
||||||
|
///
|
||||||
|
/// It exposes a specialized API which simplifies to generate these NAK PDUs with the
|
||||||
|
/// format according to CFDP chapter 5.2.6.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct NakPduCreator<'seg_reqs> {
|
||||||
|
pdu_header: PduHeader,
|
||||||
|
start_of_scope: u64,
|
||||||
|
end_of_scope: u64,
|
||||||
|
segment_requests: Option<SegmentRequests<'seg_reqs>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'seg_reqs> NakPduCreator<'seg_reqs> {
|
||||||
|
/// This constructor will set the PDU header [LargeFileFlag] field to the correct value if
|
||||||
|
/// segment requests are passed to it. If the segment request field is [None], it will remain
|
||||||
|
/// to whatever was configured for the PDU header.
|
||||||
|
pub fn new(
|
||||||
|
mut pdu_header: PduHeader,
|
||||||
|
start_of_scope: u64,
|
||||||
|
end_of_scope: u64,
|
||||||
|
segment_requests: Option<SegmentRequests<'seg_reqs>>,
|
||||||
|
) -> Result<NakPduCreator, PduError> {
|
||||||
|
// Force correct direction flag.
|
||||||
|
pdu_header.pdu_conf.direction = Direction::TowardsSender;
|
||||||
|
if let Some(ref seg_reqs) = segment_requests {
|
||||||
|
match seg_reqs {
|
||||||
|
SegmentRequests::U32Pairs(_) => {
|
||||||
|
if start_of_scope > u32::MAX as u64 || end_of_scope > u32::MAX as u64 {
|
||||||
|
return Err(PduError::InvalidStartOrEndOfScopeValue);
|
||||||
|
}
|
||||||
|
pdu_header.pdu_conf.file_flag = LargeFileFlag::Normal;
|
||||||
|
}
|
||||||
|
SegmentRequests::U64Pairs(_) => {
|
||||||
|
pdu_header.pdu_conf.file_flag = LargeFileFlag::Large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut nak_pdu = Self {
|
||||||
|
pdu_header,
|
||||||
|
start_of_scope,
|
||||||
|
end_of_scope,
|
||||||
|
segment_requests,
|
||||||
|
};
|
||||||
|
nak_pdu.pdu_header.pdu_datafield_len = nak_pdu.calc_pdu_datafield_len() as u16;
|
||||||
|
Ok(nak_pdu)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_of_scope(&self) -> u64 {
|
||||||
|
self.start_of_scope
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_of_scope(&self) -> u64 {
|
||||||
|
self.end_of_scope
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn segment_requests(&self) -> Option<&SegmentRequests> {
|
||||||
|
self.segment_requests.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_segment_reqs(&self) -> usize {
|
||||||
|
match &self.segment_requests {
|
||||||
|
Some(seg_reqs) => match seg_reqs {
|
||||||
|
SegmentRequests::U32Pairs(pairs) => pairs.len(),
|
||||||
|
SegmentRequests::U64Pairs(pairs) => pairs.len(),
|
||||||
|
},
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pdu_header(&self) -> &PduHeader {
|
||||||
|
&self.pdu_header
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_pdu_datafield_len(&self) -> usize {
|
||||||
|
let mut datafield_len = 1;
|
||||||
|
if self.file_flag() == LargeFileFlag::Normal {
|
||||||
|
datafield_len += 8;
|
||||||
|
datafield_len += self.num_segment_reqs() * 8;
|
||||||
|
} else {
|
||||||
|
datafield_len += 16;
|
||||||
|
datafield_len += self.num_segment_reqs() * 16;
|
||||||
|
}
|
||||||
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
datafield_len += 2;
|
||||||
|
}
|
||||||
|
datafield_len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CfdpPdu for NakPduCreator<'_> {
|
||||||
|
fn pdu_header(&self) -> &PduHeader {
|
||||||
|
&self.pdu_header
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||||
|
Some(FileDirectiveType::NakPdu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WritablePduPacket for NakPduCreator<'_> {
|
||||||
|
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||||
|
let expected_len = self.len_written();
|
||||||
|
if buf.len() < expected_len {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: expected_len,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let mut current_idx = self.pdu_header.write_to_bytes(buf)?;
|
||||||
|
buf[current_idx] = FileDirectiveType::NakPdu as u8;
|
||||||
|
current_idx += 1;
|
||||||
|
|
||||||
|
if let Some(ref seg_reqs) = self.segment_requests {
|
||||||
|
match seg_reqs {
|
||||||
|
SegmentRequests::U32Pairs(pairs) => {
|
||||||
|
// Unwrap is okay here, the API should prevent invalid values which would trigger a
|
||||||
|
// panic here.
|
||||||
|
let start_of_scope = u32::try_from(self.start_of_scope).unwrap();
|
||||||
|
let end_of_scope = u32::try_from(self.end_of_scope).unwrap();
|
||||||
|
buf[current_idx..current_idx + 4]
|
||||||
|
.copy_from_slice(&start_of_scope.to_be_bytes());
|
||||||
|
current_idx += 4;
|
||||||
|
buf[current_idx..current_idx + 4].copy_from_slice(&end_of_scope.to_be_bytes());
|
||||||
|
current_idx += 4;
|
||||||
|
for (next_start_offset, next_end_offset) in *pairs {
|
||||||
|
buf[current_idx..current_idx + 4]
|
||||||
|
.copy_from_slice(&next_start_offset.to_be_bytes());
|
||||||
|
current_idx += 4;
|
||||||
|
buf[current_idx..current_idx + 4]
|
||||||
|
.copy_from_slice(&next_end_offset.to_be_bytes());
|
||||||
|
current_idx += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SegmentRequests::U64Pairs(pairs) => {
|
||||||
|
buf[current_idx..current_idx + 8]
|
||||||
|
.copy_from_slice(&self.start_of_scope.to_be_bytes());
|
||||||
|
current_idx += 8;
|
||||||
|
buf[current_idx..current_idx + 8]
|
||||||
|
.copy_from_slice(&self.end_of_scope.to_be_bytes());
|
||||||
|
current_idx += 8;
|
||||||
|
for (next_start_offset, next_end_offset) in *pairs {
|
||||||
|
buf[current_idx..current_idx + 8]
|
||||||
|
.copy_from_slice(&next_start_offset.to_be_bytes());
|
||||||
|
current_idx += 8;
|
||||||
|
buf[current_idx..current_idx + 8]
|
||||||
|
.copy_from_slice(&next_end_offset.to_be_bytes());
|
||||||
|
current_idx += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
|
}
|
||||||
|
Ok(current_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len_written(&self) -> usize {
|
||||||
|
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Special iterator type for the NAK PDU which allows to iterate over both normal and large file
|
||||||
/// segment requests.
|
/// segment requests.
|
||||||
pub struct SegmentRequestIter<'a, T> {
|
pub struct SegmentRequestIter<'a, T> {
|
||||||
seq_req_start: &'a [u8],
|
seq_req_start: &'a [u8],
|
||||||
@ -61,107 +233,31 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NAK PDU abstraction.
|
/// NAK PDU abstraction specialized in the reading NAK PDUs from a raw bytestream.
|
||||||
///
|
///
|
||||||
/// For more information, refer to CFDP chapter 5.2.6.
|
/// This is a zero-copy class where the segment requests can be read using a special iterator
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
/// API without the need to copy them.
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
///
|
||||||
pub struct NakPdu<'seg_reqs> {
|
/// The NAK format is expected to be conforming to CFDP chapter 5.2.6.
|
||||||
|
pub struct NakPduReader<'seg_reqs> {
|
||||||
pdu_header: PduHeader,
|
pdu_header: PduHeader,
|
||||||
start_of_scope: u64,
|
start_of_scope: u64,
|
||||||
end_of_scope: u64,
|
end_of_scope: u64,
|
||||||
seg_reqs_raw: &'seg_reqs [u8],
|
seg_reqs_raw: &'seg_reqs [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'seg_reqs> NakPdu<'seg_reqs> {
|
impl CfdpPdu for NakPduReader<'_> {
|
||||||
pub fn new(
|
fn pdu_header(&self) -> &PduHeader {
|
||||||
mut pdu_header: PduHeader,
|
|
||||||
start_of_scope: u64,
|
|
||||||
end_of_scope: u64,
|
|
||||||
seg_reqs_raw: &'seg_reqs [u8],
|
|
||||||
) -> Result<NakPdu, PduError> {
|
|
||||||
// Force correct direction flag.
|
|
||||||
pdu_header.pdu_conf.direction = Direction::TowardsSender;
|
|
||||||
if pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
|
||||||
if seg_reqs_raw.len() % 16 != 0 {
|
|
||||||
return Err(PduError::InvalidSegmentRequestFormat);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if seg_reqs_raw.len() % 8 != 0 {
|
|
||||||
return Err(PduError::InvalidSegmentRequestFormat);
|
|
||||||
}
|
|
||||||
if start_of_scope > u32::MAX as u64 || end_of_scope > u32::MAX as u64 {
|
|
||||||
return Err(PduError::InvalidStartOrEndOfScopeValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut nak_pdu = Self {
|
|
||||||
pdu_header,
|
|
||||||
start_of_scope,
|
|
||||||
end_of_scope,
|
|
||||||
seg_reqs_raw,
|
|
||||||
};
|
|
||||||
nak_pdu.pdu_header.pdu_datafield_len = nak_pdu.calc_pdu_datafield_len() as u16;
|
|
||||||
Ok(nak_pdu)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_of_scope(&self) -> u64 {
|
|
||||||
self.start_of_scope
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn end_of_scope(&self) -> u64 {
|
|
||||||
self.end_of_scope
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_normal_segment_requests_iterator(&self) -> Option<SegmentRequestIter<'_, u32>> {
|
|
||||||
if self.file_flag() == LargeFileFlag::Large {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(SegmentRequestIter {
|
|
||||||
seq_req_start: self.seg_reqs_raw,
|
|
||||||
current_idx: 0,
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_large_segment_requests_iterator(&self) -> Option<SegmentRequestIter<'_, u64>> {
|
|
||||||
if self.file_flag() == LargeFileFlag::Normal {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(SegmentRequestIter {
|
|
||||||
seq_req_start: self.seg_reqs_raw,
|
|
||||||
current_idx: 0,
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn num_segment_reqs(&self) -> usize {
|
|
||||||
if self.file_flag() == LargeFileFlag::Large {
|
|
||||||
self.seg_reqs_raw.len() / 16
|
|
||||||
} else {
|
|
||||||
self.seg_reqs_raw.len() / 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pdu_header(&self) -> &PduHeader {
|
|
||||||
&self.pdu_header
|
&self.pdu_header
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_pdu_datafield_len(&self) -> usize {
|
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||||
let mut datafield_len = 1;
|
Some(FileDirectiveType::NakPdu)
|
||||||
if self.file_flag() == LargeFileFlag::Normal {
|
|
||||||
datafield_len += 8;
|
|
||||||
datafield_len += self.num_segment_reqs() * 8;
|
|
||||||
} else {
|
|
||||||
datafield_len += 16;
|
|
||||||
datafield_len += self.num_segment_reqs() * 16;
|
|
||||||
}
|
|
||||||
if self.crc_flag() == CrcFlag::WithCrc {
|
|
||||||
datafield_len += 2;
|
|
||||||
}
|
|
||||||
datafield_len
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_bytes(buf: &'seg_reqs [u8]) -> Result<NakPdu, PduError> {
|
impl<'seg_reqs> NakPduReader<'seg_reqs> {
|
||||||
|
pub fn from_bytes(buf: &'seg_reqs [u8]) -> Result<NakPduReader, PduError> {
|
||||||
let (pdu_header, mut current_idx) = PduHeader::from_bytes(buf)?;
|
let (pdu_header, mut current_idx) = PduHeader::from_bytes(buf)?;
|
||||||
let full_len_without_crc = pdu_header.verify_length_and_checksum(buf)?;
|
let full_len_without_crc = pdu_header.verify_length_and_checksum(buf)?;
|
||||||
// Minimum length of 9: 1 byte directive field and start and end of scope for normal file
|
// Minimum length of 9: 1 byte directive field and start and end of scope for normal file
|
||||||
@ -205,81 +301,84 @@ impl<'seg_reqs> NakPdu<'seg_reqs> {
|
|||||||
u64::from_be_bytes(buf[current_idx..current_idx + 4].try_into().unwrap());
|
u64::from_be_bytes(buf[current_idx..current_idx + 4].try_into().unwrap());
|
||||||
current_idx += 4;
|
current_idx += 4;
|
||||||
}
|
}
|
||||||
Self::new(
|
Ok(Self {
|
||||||
pdu_header,
|
pdu_header,
|
||||||
start_of_scope,
|
start_of_scope,
|
||||||
end_of_scope,
|
end_of_scope,
|
||||||
&buf[current_idx..full_len_without_crc],
|
seg_reqs_raw: &buf[current_idx..full_len_without_crc],
|
||||||
)
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CfdpPdu for NakPdu<'_> {
|
|
||||||
fn pdu_header(&self) -> &PduHeader {
|
|
||||||
&self.pdu_header
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
pub fn start_of_scope(&self) -> u64 {
|
||||||
Some(FileDirectiveType::NakPdu)
|
self.start_of_scope
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl WritablePduPacket for NakPdu<'_> {
|
pub fn end_of_scope(&self) -> u64 {
|
||||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
self.end_of_scope
|
||||||
let expected_len = self.len_written();
|
|
||||||
if buf.len() < expected_len {
|
|
||||||
return Err(ByteConversionError::ToSliceTooSmall {
|
|
||||||
found: buf.len(),
|
|
||||||
expected: expected_len,
|
|
||||||
}
|
}
|
||||||
.into());
|
|
||||||
}
|
|
||||||
let mut current_idx = self.pdu_header.write_to_bytes(buf)?;
|
|
||||||
buf[current_idx] = FileDirectiveType::NakPdu as u8;
|
|
||||||
current_idx += 1;
|
|
||||||
|
|
||||||
|
/// This function returns [None] if this NAK PDUs contains segment requests for a large file.
|
||||||
|
pub fn get_normal_segment_requests_iterator(&self) -> Option<SegmentRequestIter<'_, u32>> {
|
||||||
if self.file_flag() == LargeFileFlag::Large {
|
if self.file_flag() == LargeFileFlag::Large {
|
||||||
buf[current_idx..current_idx + 8].copy_from_slice(&self.start_of_scope.to_be_bytes());
|
return None;
|
||||||
current_idx += 8;
|
|
||||||
buf[current_idx..current_idx + 8].copy_from_slice(&self.end_of_scope.to_be_bytes());
|
|
||||||
current_idx += 8;
|
|
||||||
// Unwrap is okay here, we checked the file flag.
|
|
||||||
let segments_iter = self.get_large_segment_requests_iterator().unwrap();
|
|
||||||
for (next_start_offset, next_end_offset) in segments_iter {
|
|
||||||
buf[current_idx..current_idx + 8].copy_from_slice(&next_start_offset.to_be_bytes());
|
|
||||||
current_idx += 8;
|
|
||||||
buf[current_idx..current_idx + 8].copy_from_slice(&next_end_offset.to_be_bytes());
|
|
||||||
current_idx += 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unwrap is okay here, the API should prevent invalid values which would trigger a
|
|
||||||
// panic here.
|
|
||||||
let start_of_scope = u32::try_from(self.start_of_scope).unwrap();
|
|
||||||
let end_of_scope = u32::try_from(self.end_of_scope).unwrap();
|
|
||||||
buf[current_idx..current_idx + 4].copy_from_slice(&start_of_scope.to_be_bytes());
|
|
||||||
current_idx += 4;
|
|
||||||
buf[current_idx..current_idx + 4].copy_from_slice(&end_of_scope.to_be_bytes());
|
|
||||||
current_idx += 4;
|
|
||||||
// Unwrap is okay here, we checked the file flag.
|
|
||||||
let segments_iter = self.get_normal_segment_requests_iterator().unwrap();
|
|
||||||
for (next_start_offset, next_end_offset) in segments_iter {
|
|
||||||
buf[current_idx..current_idx + 4].copy_from_slice(&next_start_offset.to_be_bytes());
|
|
||||||
current_idx += 4;
|
|
||||||
buf[current_idx..current_idx + 4].copy_from_slice(&next_end_offset.to_be_bytes());
|
|
||||||
current_idx += 4;
|
|
||||||
}
|
}
|
||||||
|
Some(SegmentRequestIter {
|
||||||
|
seq_req_start: self.seg_reqs_raw,
|
||||||
|
current_idx: 0,
|
||||||
|
phantom: PhantomData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.crc_flag() == CrcFlag::WithCrc {
|
/// This function returns [None] if this NAK PDUs contains segment requests for a normal file.
|
||||||
current_idx = add_pdu_crc(buf, current_idx);
|
pub fn get_large_segment_requests_iterator(&self) -> Option<SegmentRequestIter<'_, u64>> {
|
||||||
|
if self.file_flag() == LargeFileFlag::Normal {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
Ok(current_idx)
|
Some(SegmentRequestIter {
|
||||||
}
|
seq_req_start: self.seg_reqs_raw,
|
||||||
|
current_idx: 0,
|
||||||
fn len_written(&self) -> usize {
|
phantom: PhantomData,
|
||||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use crate::cfdp::{
|
||||||
|
pdu::tests::{common_pdu_conf, TEST_DEST_ID, TEST_SEQ_NUM, TEST_SRC_ID},
|
||||||
|
PduType, TransmissionMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basic_creator() {
|
||||||
|
let pdu_conf = common_pdu_conf(CrcFlag::NoCrc, LargeFileFlag::Normal);
|
||||||
|
let pdu_header = PduHeader::new_no_file_data(pdu_conf, 0);
|
||||||
|
let nak_pdu =
|
||||||
|
NakPduCreator::new(pdu_header, 0, 0, None).expect("creating NAK PDU creator failed");
|
||||||
|
assert_eq!(nak_pdu.start_of_scope(), 0);
|
||||||
|
assert_eq!(nak_pdu.end_of_scope(), 0);
|
||||||
|
assert_eq!(nak_pdu.segment_requests(), None);
|
||||||
|
assert_eq!(nak_pdu.num_segment_reqs(), 0);
|
||||||
|
|
||||||
|
assert_eq!(nak_pdu.crc_flag(), CrcFlag::NoCrc);
|
||||||
|
assert_eq!(nak_pdu.file_flag(), LargeFileFlag::Normal);
|
||||||
|
assert_eq!(nak_pdu.pdu_type(), PduType::FileDirective);
|
||||||
|
assert_eq!(
|
||||||
|
nak_pdu.file_directive_type(),
|
||||||
|
Some(FileDirectiveType::NakPdu),
|
||||||
|
);
|
||||||
|
assert_eq!(nak_pdu.transmission_mode(), TransmissionMode::Acknowledged);
|
||||||
|
assert_eq!(nak_pdu.direction(), Direction::TowardsSender);
|
||||||
|
assert_eq!(nak_pdu.source_id(), TEST_SRC_ID.into());
|
||||||
|
assert_eq!(nak_pdu.dest_id(), TEST_DEST_ID.into());
|
||||||
|
assert_eq!(nak_pdu.transaction_seq_num(), TEST_SEQ_NUM.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialization_empty() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialization_one_segment() {}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user