use core::iter::Fuse;
use arrayvec::ArrayVec;
use crate::{
datastructures::common::{PortIdentity, Tlv, TlvSetIterator},
filters::FilterUpdate,
};
#[derive(Debug, Clone)]
pub struct ForwardedTLV<'a> {
pub(super) tlv: Tlv<'a>,
pub(super) sender_identity: PortIdentity,
}
impl ForwardedTLV<'_> {
pub fn size(&self) -> usize {
self.tlv.wire_size()
}
#[cfg(feature = "std")]
pub fn into_owned(self) -> ForwardedTLV<'static> {
ForwardedTLV {
tlv: self.tlv.into_owned(),
sender_identity: self.sender_identity,
}
}
}
pub trait ForwardedTLVProvider {
fn next_if_smaller(&mut self, max_size: usize) -> Option<ForwardedTLV>;
}
#[derive(Debug, Copy, Clone)]
pub struct NoForwardedTLVs;
impl ForwardedTLVProvider for NoForwardedTLVs {
fn next_if_smaller(&mut self, _max_size: usize) -> Option<ForwardedTLV> {
None
}
}
#[derive(Debug)]
pub struct TimestampContext {
pub(super) inner: TimestampContextInner,
}
#[derive(Debug)]
pub(super) enum TimestampContextInner {
Sync {
id: u16,
},
DelayReq {
id: u16,
},
PDelayReq {
id: u16,
},
PDelayResp {
id: u16,
requestor_identity: PortIdentity,
},
}
#[derive(Debug)]
#[must_use]
#[allow(missing_docs)] pub enum PortAction<'a> {
SendEvent {
context: TimestampContext,
data: &'a [u8],
link_local: bool,
},
SendGeneral { data: &'a [u8], link_local: bool },
ResetAnnounceTimer { duration: core::time::Duration },
ResetSyncTimer { duration: core::time::Duration },
ResetDelayRequestTimer { duration: core::time::Duration },
ResetAnnounceReceiptTimer { duration: core::time::Duration },
ResetFilterUpdateTimer { duration: core::time::Duration },
ForwardTLV { tlv: ForwardedTLV<'a> },
}
const MAX_ACTIONS: usize = 2;
#[derive(Debug)]
#[must_use]
pub struct PortActionIterator<'a> {
internal: Fuse<<ArrayVec<PortAction<'a>, MAX_ACTIONS> as IntoIterator>::IntoIter>,
tlvs: TlvSetIterator<'a>,
sender_identity: PortIdentity,
}
impl<'a> PortActionIterator<'a> {
pub fn empty() -> Self {
Self {
internal: ArrayVec::new().into_iter().fuse(),
tlvs: TlvSetIterator::empty(),
sender_identity: Default::default(),
}
}
pub(super) fn from(list: ArrayVec<PortAction<'a>, MAX_ACTIONS>) -> Self {
Self {
internal: list.into_iter().fuse(),
tlvs: TlvSetIterator::empty(),
sender_identity: Default::default(),
}
}
pub(super) fn from_filter(update: FilterUpdate) -> Self {
if let Some(duration) = update.next_update {
actions![PortAction::ResetFilterUpdateTimer { duration }]
} else {
actions![]
}
}
pub(super) fn with_forward_tlvs(
self,
tlvs: TlvSetIterator<'a>,
sender_identity: PortIdentity,
) -> Self {
Self {
internal: self.internal,
tlvs,
sender_identity,
}
}
}
impl<'a> Iterator for PortActionIterator<'a> {
type Item = PortAction<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.internal.next().or_else(|| loop {
let tlv = self.tlvs.next()?;
if tlv.tlv_type.announce_propagate() {
return Some(PortAction::ForwardTLV {
tlv: ForwardedTLV {
tlv,
sender_identity: self.sender_identity,
},
});
}
})
}
}