continue CFDP handlers
Some checks failed
Rust/sat-rs/pipeline/head There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/head There was a failure building this commit
This commit is contained in:
parent
2afb3de227
commit
f7f1017fed
@ -73,11 +73,11 @@ features = ["all"]
|
||||
optional = true
|
||||
|
||||
[dependencies.spacepackets]
|
||||
version = "0.7.0-beta.2"
|
||||
# version = "0.7.0-beta.2"
|
||||
default-features = false
|
||||
# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||
# rev = "79d26e1a6"
|
||||
# branch = ""
|
||||
branch = "writable_pdu_packet"
|
||||
|
||||
[dependencies.cobs]
|
||||
git = "https://github.com/robamu/cobs.rs.git"
|
||||
|
@ -9,8 +9,10 @@ use crate::cfdp::user::TransactionFinishedParams;
|
||||
|
||||
use super::{
|
||||
user::{CfdpUser, MetadataReceivedParams},
|
||||
PacketInfo, PacketTarget, State, TransactionId, TransactionStep, CRC_32,
|
||||
CheckTimerCreator, PacketInfo, PacketTarget, RemoteEntityConfigProvider, State, TransactionId,
|
||||
TransactionStep, CRC_32,
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use smallvec::SmallVec;
|
||||
use spacepackets::{
|
||||
cfdp::{
|
||||
@ -19,10 +21,10 @@ use spacepackets::{
|
||||
file_data::FileDataPdu,
|
||||
finished::{DeliveryCode, FileStatus, FinishedPdu},
|
||||
metadata::{MetadataGenericParams, MetadataPdu},
|
||||
CommonPduConfig, FileDirectiveType, PduError, PduHeader,
|
||||
CommonPduConfig, FileDirectiveType, PduError, PduHeader, WritablePduPacket,
|
||||
},
|
||||
tlv::{msg_to_user::MsgToUserTlv, EntityIdTlv, TlvType},
|
||||
ConditionCode, PduType, TransmissionMode,
|
||||
ConditionCode, PduType,
|
||||
},
|
||||
util::UnsignedByteField,
|
||||
};
|
||||
@ -34,6 +36,8 @@ pub struct DestinationHandler {
|
||||
state: State,
|
||||
tparams: TransactionParams,
|
||||
packets_to_send_ctx: PacketsToSendContext,
|
||||
remote_cfg_table: Box<dyn RemoteEntityConfigProvider>,
|
||||
check_timer_creator: Box<dyn CheckTimerCreator>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@ -152,25 +156,38 @@ pub enum DestError {
|
||||
}
|
||||
|
||||
impl DestinationHandler {
|
||||
pub fn new(id: impl Into<UnsignedByteField>) -> Self {
|
||||
pub fn new(
|
||||
entity_id: impl Into<UnsignedByteField>,
|
||||
remote_cfg_table: Box<dyn RemoteEntityConfigProvider>,
|
||||
check_timer_creator: Box<dyn CheckTimerCreator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
id: entity_id.into(),
|
||||
step: TransactionStep::Idle,
|
||||
state: State::Idle,
|
||||
tparams: Default::default(),
|
||||
packets_to_send_ctx: Default::default(),
|
||||
remote_cfg_table,
|
||||
check_timer_creator,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn state_machine(&mut self, cfdp_user: &mut impl CfdpUser) -> Result<(), DestError> {
|
||||
pub fn state_machine(
|
||||
&mut self,
|
||||
cfdp_user: &mut impl CfdpUser,
|
||||
packet_to_insert: Option<&PacketInfo>,
|
||||
) -> Result<(), DestError> {
|
||||
if let Some(packet) = packet_to_insert {
|
||||
self.insert_packet(packet)?;
|
||||
}
|
||||
match self.state {
|
||||
State::Idle => todo!(),
|
||||
State::BusyClass1Nacked => self.fsm_nacked(cfdp_user),
|
||||
State::BusyClass2Acked => todo!("acknowledged mode not implemented yet"),
|
||||
State::Busy => self.fsm_busy(cfdp_user),
|
||||
State::Suspended => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_packet(&mut self, packet_info: &PacketInfo) -> Result<(), DestError> {
|
||||
fn insert_packet(&mut self, packet_info: &PacketInfo) -> Result<(), DestError> {
|
||||
if packet_info.target() != PacketTarget::DestEntity {
|
||||
// Unwrap is okay here, a PacketInfo for a file data PDU should always have the
|
||||
// destination as the target.
|
||||
@ -297,11 +314,7 @@ impl DestinationHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.tparams.pdu_conf.trans_mode == TransmissionMode::Unacknowledged {
|
||||
self.state = State::BusyClass1Nacked;
|
||||
} else {
|
||||
self.state = State::BusyClass2Acked;
|
||||
}
|
||||
self.state = State::Busy;
|
||||
self.step = TransactionStep::TransactionStart;
|
||||
Ok(())
|
||||
}
|
||||
@ -338,7 +351,7 @@ impl DestinationHandler {
|
||||
// TODO: Check progress, and implement transfer completion timer as specified in the
|
||||
// standard. This timer protects against out of order arrival of packets.
|
||||
if self.tparams.tstate.progress != self.tparams.file_size() {}
|
||||
if self.state == State::BusyClass1Nacked {
|
||||
if self.state == State::Busy {
|
||||
self.step = TransactionStep::TransferCompletion;
|
||||
} else {
|
||||
self.step = TransactionStep::SendingAckPdu;
|
||||
@ -367,7 +380,7 @@ impl DestinationHandler {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn fsm_nacked(&mut self, cfdp_user: &mut impl CfdpUser) -> Result<(), DestError> {
|
||||
fn fsm_busy(&mut self, cfdp_user: &mut impl CfdpUser) -> Result<(), DestError> {
|
||||
if self.step == TransactionStep::TransactionStart {
|
||||
self.transaction_start(cfdp_user)?;
|
||||
}
|
||||
@ -496,7 +509,10 @@ impl DestinationHandler {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::sync::atomic::{AtomicU8, Ordering};
|
||||
use core::{
|
||||
cell::Cell,
|
||||
sync::atomic::{AtomicU8, Ordering},
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
use std::println;
|
||||
use std::{env::temp_dir, fs};
|
||||
@ -504,10 +520,14 @@ mod tests {
|
||||
use alloc::{format, string::String};
|
||||
use rand::Rng;
|
||||
use spacepackets::{
|
||||
cfdp::{lv::Lv, ChecksumType},
|
||||
cfdp::{lv::Lv, pdu::WritablePduPacket, ChecksumType, TransmissionMode},
|
||||
util::{UbfU16, UnsignedByteFieldU16},
|
||||
};
|
||||
|
||||
use crate::cfdp::{
|
||||
CheckTimer, CheckTimerCreator, RemoteEntityConfig, StdRemoteEntityConfigProvider,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
const LOCAL_ID: UnsignedByteFieldU16 = UnsignedByteFieldU16::new(1);
|
||||
@ -608,6 +628,63 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
struct TestCheckTimer {
|
||||
counter: Cell<u32>,
|
||||
expiry_count: u32,
|
||||
}
|
||||
|
||||
impl CheckTimer for TestCheckTimer {
|
||||
fn has_expired(&self) -> bool {
|
||||
let current_counter = self.counter.get();
|
||||
if self.expiry_count == current_counter {
|
||||
return true;
|
||||
}
|
||||
self.counter.set(current_counter + 1);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl TestCheckTimer {
|
||||
pub fn new(expiry_after_x_calls: u32) -> Self {
|
||||
Self {
|
||||
counter: Cell::new(0),
|
||||
expiry_count: expiry_after_x_calls,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TestCheckTimerCreator {
|
||||
expiry_counter_for_source_entity: u32,
|
||||
expiry_counter_for_dest_entity: u32,
|
||||
}
|
||||
|
||||
impl TestCheckTimerCreator {
|
||||
pub fn new(
|
||||
expiry_counter_for_source_entity: u32,
|
||||
expiry_counter_for_dest_entity: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
expiry_counter_for_source_entity,
|
||||
expiry_counter_for_dest_entity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckTimerCreator for TestCheckTimerCreator {
|
||||
fn get_check_timer_provider(
|
||||
&self,
|
||||
_local_id: &UnsignedByteField,
|
||||
_remote_id: &UnsignedByteField,
|
||||
entity_type: crate::cfdp::EntityType,
|
||||
) -> Box<dyn CheckTimer> {
|
||||
if entity_type == crate::cfdp::EntityType::Sending {
|
||||
Box::new(TestCheckTimer::new(self.expiry_counter_for_source_entity))
|
||||
} else {
|
||||
Box::new(TestCheckTimer::new(self.expiry_counter_for_dest_entity))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_check(handler: &DestinationHandler) {
|
||||
assert_eq!(handler.state(), State::Idle);
|
||||
assert_eq!(handler.step(), TransactionStep::Idle);
|
||||
@ -626,9 +703,31 @@ mod tests {
|
||||
(src_path, file_path)
|
||||
}
|
||||
|
||||
fn basic_remote_cfg_table() -> StdRemoteEntityConfigProvider {
|
||||
let mut table = StdRemoteEntityConfigProvider::default();
|
||||
let remote_entity_cfg = RemoteEntityConfig::new_with_default_values(
|
||||
UnsignedByteFieldU16::new(1).into(),
|
||||
1024,
|
||||
1024,
|
||||
true,
|
||||
true,
|
||||
TransmissionMode::Unacknowledged,
|
||||
ChecksumType::Crc32,
|
||||
);
|
||||
table.add_config(&remote_entity_cfg);
|
||||
table
|
||||
}
|
||||
|
||||
fn default_dest_handler() -> DestinationHandler {
|
||||
DestinationHandler::new(
|
||||
REMOTE_ID,
|
||||
Box::new(basic_remote_cfg_table()),
|
||||
Box::new(TestCheckTimerCreator::new(2, 2)),
|
||||
)
|
||||
}
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
let dest_handler = DestinationHandler::new(REMOTE_ID);
|
||||
let dest_handler = default_dest_handler();
|
||||
init_check(&dest_handler);
|
||||
}
|
||||
|
||||
@ -655,37 +754,20 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
fn insert_metadata_pdu(
|
||||
metadata_pdu: &MetadataPdu,
|
||||
buf: &mut [u8],
|
||||
dest_handler: &mut DestinationHandler,
|
||||
) {
|
||||
let written_len = metadata_pdu
|
||||
fn create_packet_info<'a>(
|
||||
pdu: &'a impl WritablePduPacket,
|
||||
buf: &'a mut [u8],
|
||||
) -> PacketInfo<'a> {
|
||||
let written_len = pdu
|
||||
.write_to_bytes(buf)
|
||||
.expect("writing metadata PDU failed");
|
||||
let packet_info =
|
||||
PacketInfo::new(&buf[..written_len]).expect("generating packet info failed");
|
||||
let insert_result = dest_handler.insert_packet(&packet_info);
|
||||
if let Err(e) = insert_result {
|
||||
panic!("insert result error: {e}");
|
||||
}
|
||||
PacketInfo::new(&buf[..written_len]).expect("generating packet info failed")
|
||||
}
|
||||
|
||||
fn insert_eof_pdu(
|
||||
file_data: &[u8],
|
||||
pdu_header: &PduHeader,
|
||||
buf: &mut [u8],
|
||||
dest_handler: &mut DestinationHandler,
|
||||
) {
|
||||
fn create_no_error_eof(file_data: &[u8], pdu_header: &PduHeader, buf: &mut [u8]) -> EofPdu {
|
||||
let mut digest = CRC_32.digest();
|
||||
digest.update(file_data);
|
||||
let crc32 = digest.finalize();
|
||||
let eof_pdu = EofPdu::new_no_error(*pdu_header, crc32, file_data.len() as u64);
|
||||
let result = eof_pdu.write_to_bytes(buf);
|
||||
assert!(result.is_ok());
|
||||
let packet_info = PacketInfo::new(&buf).expect("generating packet info failed");
|
||||
let result = dest_handler.insert_packet(&packet_info);
|
||||
assert!(result.is_ok());
|
||||
EofPdu::new_no_error(*pdu_header, crc32, file_data.len() as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -700,23 +782,24 @@ mod tests {
|
||||
expected_file_size: 0,
|
||||
};
|
||||
// We treat the destination handler like it is a remote entity.
|
||||
let mut dest_handler = DestinationHandler::new(REMOTE_ID);
|
||||
let mut dest_handler = default_dest_handler();
|
||||
init_check(&dest_handler);
|
||||
|
||||
let seq_num = UbfU16::new(0);
|
||||
let pdu_header = create_pdu_header(seq_num);
|
||||
let metadata_pdu =
|
||||
create_metadata_pdu(&pdu_header, src_name.as_path(), dest_name.as_path(), 0);
|
||||
insert_metadata_pdu(&metadata_pdu, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let packet_info = create_packet_info(&metadata_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
if let Err(e) = result {
|
||||
panic!("dest handler fsm error: {e}");
|
||||
}
|
||||
assert_ne!(dest_handler.state(), State::Idle);
|
||||
assert_eq!(dest_handler.step(), TransactionStep::ReceivingFileDataPdus);
|
||||
|
||||
insert_eof_pdu(&[], &pdu_header, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let eof_pdu = create_no_error_eof(&[], &pdu_header, &mut buf);
|
||||
let packet_info = create_packet_info(&eof_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(dest_handler.state(), State::Idle);
|
||||
assert_eq!(dest_handler.step(), TransactionStep::Idle);
|
||||
@ -740,7 +823,7 @@ mod tests {
|
||||
expected_file_size: file_data.len(),
|
||||
};
|
||||
// We treat the destination handler like it is a remote entity.
|
||||
let mut dest_handler = DestinationHandler::new(REMOTE_ID);
|
||||
let mut dest_handler = default_dest_handler();
|
||||
init_check(&dest_handler);
|
||||
|
||||
let seq_num = UbfU16::new(0);
|
||||
@ -751,8 +834,8 @@ mod tests {
|
||||
dest_name.as_path(),
|
||||
file_data.len() as u64,
|
||||
);
|
||||
insert_metadata_pdu(&metadata_pdu, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let packet_info = create_packet_info(&metadata_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
if let Err(e) = result {
|
||||
panic!("dest handler fsm error: {e}");
|
||||
}
|
||||
@ -769,11 +852,12 @@ mod tests {
|
||||
if let Err(e) = result {
|
||||
panic!("destination handler packet insertion error: {e}");
|
||||
}
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
|
||||
insert_eof_pdu(file_data, &pdu_header, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let eof_pdu = create_no_error_eof(&file_data, &pdu_header, &mut buf);
|
||||
let packet_info = create_packet_info(&eof_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(dest_handler.state(), State::Idle);
|
||||
assert_eq!(dest_handler.step(), TransactionStep::Idle);
|
||||
@ -800,7 +884,7 @@ mod tests {
|
||||
};
|
||||
|
||||
// We treat the destination handler like it is a remote entity.
|
||||
let mut dest_handler = DestinationHandler::new(REMOTE_ID);
|
||||
let mut dest_handler = default_dest_handler();
|
||||
init_check(&dest_handler);
|
||||
|
||||
let seq_num = UbfU16::new(0);
|
||||
@ -811,8 +895,8 @@ mod tests {
|
||||
dest_name.as_path(),
|
||||
random_data.len() as u64,
|
||||
);
|
||||
insert_metadata_pdu(&metadata_pdu, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let packet_info = create_packet_info(&metadata_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
if let Err(e) = result {
|
||||
panic!("dest handler fsm error: {e}");
|
||||
}
|
||||
@ -835,7 +919,7 @@ mod tests {
|
||||
if let Err(e) = result {
|
||||
panic!("destination handler packet insertion error: {e}");
|
||||
}
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
|
||||
// Second file data PDU
|
||||
@ -853,11 +937,12 @@ mod tests {
|
||||
if let Err(e) = result {
|
||||
panic!("destination handler packet insertion error: {e}");
|
||||
}
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
|
||||
insert_eof_pdu(&random_data, &pdu_header, &mut buf, &mut dest_handler);
|
||||
let result = dest_handler.state_machine(&mut test_user);
|
||||
let eof_pdu = create_no_error_eof(&random_data, &pdu_header, &mut buf);
|
||||
let packet_info = create_packet_info(&eof_pdu, &mut buf);
|
||||
let result = dest_handler.state_machine(&mut test_user, Some(&packet_info));
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(dest_handler.state(), State::Idle);
|
||||
assert_eq!(dest_handler.step(), TransactionStep::Idle);
|
||||
|
@ -1,4 +1,7 @@
|
||||
use core::hash::Hash;
|
||||
|
||||
use crc::{Crc, CRC_32_CKSUM};
|
||||
use hashbrown::HashMap;
|
||||
use spacepackets::{
|
||||
cfdp::{
|
||||
pdu::{FileDirectiveType, PduError, PduHeader},
|
||||
@ -35,7 +38,7 @@ pub enum EntityType {
|
||||
/// For the receiving entity, this timer determines the expiry period for incrementing a check
|
||||
/// counter after an EOF PDU is received for an incomplete file transfer. This allows out-of-order
|
||||
/// reception of file data PDUs and EOF PDUs. Also see 4.6.3.3 of the CFDP standard.
|
||||
pub trait CheckTimerProvider {
|
||||
pub trait CheckTimer {
|
||||
fn has_expired(&self) -> bool;
|
||||
}
|
||||
|
||||
@ -50,10 +53,11 @@ pub trait CheckTimerProvider {
|
||||
#[cfg(feature = "alloc")]
|
||||
pub trait CheckTimerCreator {
|
||||
fn get_check_timer_provider(
|
||||
&self,
|
||||
local_id: &UnsignedByteField,
|
||||
remote_id: &UnsignedByteField,
|
||||
entity_type: EntityType,
|
||||
) -> Box<dyn CheckTimerProvider>;
|
||||
) -> Box<dyn CheckTimer>;
|
||||
}
|
||||
|
||||
/// Simple implementation of the [CheckTimerProvider] trait assuming a standard runtime.
|
||||
@ -75,7 +79,7 @@ impl StdCheckTimer {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl CheckTimerProvider for StdCheckTimer {
|
||||
impl CheckTimer for StdCheckTimer {
|
||||
fn has_expired(&self) -> bool {
|
||||
let elapsed_time = self.start_time.elapsed();
|
||||
if elapsed_time.as_secs() > self.expiry_time_seconds {
|
||||
@ -85,22 +89,78 @@ impl CheckTimerProvider for StdCheckTimer {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct RemoteEntityConfig {
|
||||
pub entity_id: UnsignedByteField,
|
||||
pub max_file_segment_len: usize,
|
||||
pub closure_requeted_by_default: bool,
|
||||
pub max_packet_len: usize,
|
||||
pub closure_requested_by_default: bool,
|
||||
pub crc_on_transmission_by_default: bool,
|
||||
pub default_transmission_mode: TransmissionMode,
|
||||
pub default_crc_type: ChecksumType,
|
||||
pub check_limit: u32,
|
||||
}
|
||||
|
||||
pub trait RemoteEntityConfigProvider {
|
||||
fn get_remote_config(&self, remote_id: &UnsignedByteField) -> Option<&RemoteEntityConfig>;
|
||||
impl RemoteEntityConfig {
|
||||
pub fn new_with_default_values(
|
||||
entity_id: UnsignedByteField,
|
||||
max_file_segment_len: usize,
|
||||
max_packet_len: usize,
|
||||
closure_requested_by_default: bool,
|
||||
crc_on_transmission_by_default: bool,
|
||||
default_transmission_mode: TransmissionMode,
|
||||
default_crc_type: ChecksumType,
|
||||
) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
max_file_segment_len,
|
||||
max_packet_len,
|
||||
closure_requested_by_default,
|
||||
crc_on_transmission_by_default,
|
||||
default_transmission_mode,
|
||||
default_crc_type,
|
||||
check_limit: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub trait RemoteEntityConfigProvider {
|
||||
/// Retrieve the remote entity configuration for the given remote ID.
|
||||
fn get_remote_config(&self, remote_id: u64) -> Option<&RemoteEntityConfig>;
|
||||
fn get_remote_config_mut(&mut self, remote_id: u64) -> Option<&mut RemoteEntityConfig>;
|
||||
/// Add a new remote configuration. Return [True] if the configuration was
|
||||
/// inserted successfully, and [False] if a configuration already exists.
|
||||
fn add_config(&mut self, cfg: &RemoteEntityConfig) -> bool;
|
||||
/// Remote a configuration. Returns [True] if the configuration was removed successfully,
|
||||
/// and [False] if no configuration exists for the given remote ID.
|
||||
fn remove_config(&mut self, remote_id: u64) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(Default)]
|
||||
pub struct StdRemoteEntityConfigProvider {
|
||||
remote_cfg_table: HashMap<u64, RemoteEntityConfig>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl RemoteEntityConfigProvider for StdRemoteEntityConfigProvider {
|
||||
fn get_remote_config(&self, remote_id: u64) -> Option<&RemoteEntityConfig> {
|
||||
self.remote_cfg_table.get(&remote_id)
|
||||
}
|
||||
fn get_remote_config_mut(&mut self, remote_id: u64) -> Option<&mut RemoteEntityConfig> {
|
||||
self.remote_cfg_table.get_mut(&remote_id)
|
||||
}
|
||||
fn add_config(&mut self, cfg: &RemoteEntityConfig) -> bool {
|
||||
self.remote_cfg_table
|
||||
.insert(cfg.entity_id.value(), *cfg)
|
||||
.is_some()
|
||||
}
|
||||
fn remove_config(&mut self, remote_id: u64) -> bool {
|
||||
self.remote_cfg_table.remove(&remote_id).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, Copy, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct TransactionId {
|
||||
source_id: UnsignedByteField,
|
||||
@ -121,6 +181,20 @@ impl TransactionId {
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for TransactionId {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.source_id.value().hash(state);
|
||||
self.seq_num.value().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for TransactionId {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.source_id.value() == other.source_id.value()
|
||||
&& self.seq_num.value() == other.seq_num.value()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum TransactionStep {
|
||||
@ -136,8 +210,8 @@ pub enum TransactionStep {
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum State {
|
||||
Idle = 0,
|
||||
BusyClass1Nacked = 2,
|
||||
BusyClass2Acked = 3,
|
||||
Busy = 1,
|
||||
Suspended = 2,
|
||||
}
|
||||
|
||||
pub const CRC_32: Crc<u32> = Crc::<u32>::new(&CRC_32_CKSUM);
|
||||
@ -249,7 +323,7 @@ mod tests {
|
||||
eof::EofPdu,
|
||||
file_data::FileDataPdu,
|
||||
metadata::{MetadataGenericParams, MetadataPdu},
|
||||
CommonPduConfig, FileDirectiveType, PduHeader,
|
||||
CommonPduConfig, FileDirectiveType, PduHeader, WritablePduPacket,
|
||||
},
|
||||
PduType,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user