use core::task::{Context, Poll};
use crate::{eff::EffIndex, session::types::SessionId, transport::wire::Payload};
mod labels;
pub use labels::FrameLabel;
pub(crate) use labels::{FrameLabelMask, LogicalLabel};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct SendMeta {
pub(crate) eff_index: EffIndex,
pub(crate) logical_label: LogicalLabel,
pub(crate) frame_label: FrameLabel,
pub(crate) target_role: u8,
pub(crate) lane: u8,
}
#[derive(Clone, Copy, Debug)]
pub struct Outgoing<'f> {
pub(crate) meta: SendMeta,
pub(crate) payload: Payload<'f>,
}
impl<'f> Outgoing<'f> {
#[inline]
pub const fn frame_label(&self) -> FrameLabel {
self.meta.frame_label
}
#[inline]
pub const fn target_role(&self) -> u8 {
self.meta.target_role
}
#[inline]
pub const fn lane(&self) -> u8 {
self.meta.lane
}
#[inline]
pub const fn payload(&self) -> Payload<'f> {
self.payload
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum TransportError {
Offline,
Deadline,
Capacity,
Failed,
}
impl core::fmt::Debug for TransportError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let name = match self {
Self::Offline => "O",
Self::Deadline => "D",
Self::Capacity => "C",
Self::Failed => "F",
};
f.write_str(name)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FrameHeader([u8; 8]);
impl FrameHeader {
#[inline]
pub const fn from_bytes(bytes: [u8; 8]) -> Self {
Self(bytes)
}
#[inline]
pub const fn bytes(self) -> [u8; 8] {
self.0
}
#[inline]
pub(crate) const fn from_parts(
session: SessionId,
carrier: u8,
source_role: u8,
target_role: u8,
label: FrameLabel,
) -> Self {
let session = session.raw().to_be_bytes();
Self([
session[0],
session[1],
session[2],
session[3],
carrier,
source_role,
target_role,
label.raw(),
])
}
#[inline]
pub(crate) const fn session(self) -> SessionId {
SessionId::new(u32::from_be_bytes([
self.0[0], self.0[1], self.0[2], self.0[3],
]))
}
#[inline]
pub(crate) const fn lane(self) -> u8 {
self.0[4]
}
#[inline]
pub(crate) const fn source_role(self) -> u8 {
self.0[5]
}
#[inline]
pub(crate) const fn target_role(self) -> u8 {
self.0[6]
}
#[inline]
pub(crate) const fn label(self) -> FrameLabel {
FrameLabel::new(self.0[7])
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum IngressEvidence {
Deterministic,
Framed {
session: SessionId,
carrier: u8,
source: u8,
target: u8,
label: FrameLabel,
},
}
impl IngressEvidence {
#[inline]
pub const fn from_header(header: FrameHeader) -> Self {
Self::Framed {
session: header.session(),
carrier: header.lane(),
source: header.source_role(),
target: header.target_role(),
label: header.label(),
}
}
#[inline]
pub(crate) const fn frame_header(self) -> Option<FrameHeader> {
match self {
Self::Deterministic => None,
Self::Framed {
session,
carrier,
source,
target,
label,
} => Some(FrameHeader::from_parts(
session, carrier, source, target, label,
)),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ReceivedFrame<'f> {
evidence: IngressEvidence,
payload: Payload<'f>,
}
impl<'f> ReceivedFrame<'f> {
#[inline]
pub const fn deterministic(payload: Payload<'f>) -> Self {
Self {
evidence: IngressEvidence::Deterministic,
payload,
}
}
#[inline]
pub const fn framed(header: FrameHeader, payload: Payload<'f>) -> Self {
Self {
evidence: IngressEvidence::from_header(header),
payload,
}
}
#[inline]
pub(crate) const fn evidence(&self) -> IngressEvidence {
self.evidence
}
#[inline]
pub const fn payload(self) -> Payload<'f> {
self.payload
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PortOpen {
local_role: u8,
session_id: crate::session::types::SessionId,
lane: crate::session::types::Lane,
}
impl PortOpen {
#[inline]
pub(crate) const fn from_descriptor(
local_role: u8,
session_id: crate::session::types::SessionId,
lane: crate::session::types::Lane,
) -> Self {
Self {
local_role,
session_id,
lane,
}
}
#[inline]
pub const fn local_role(self) -> u8 {
self.local_role
}
#[inline]
pub const fn session_id(self) -> crate::session::types::SessionId {
self.session_id
}
#[inline]
pub const fn lane(self) -> u8 {
self.lane.as_wire()
}
}
pub trait Transport {
type Tx<'a>: 'a
where
Self: 'a;
type Rx<'a>: 'a
where
Self: 'a;
fn open<'a>(&'a self, port: PortOpen) -> (Self::Tx<'a>, Self::Rx<'a>);
fn poll_send<'a, 'f>(
&self,
tx: &'a mut Self::Tx<'a>,
outgoing: Outgoing<'f>,
cx: &mut Context<'_>,
) -> Poll<Result<(), TransportError>>
where
'a: 'f;
fn cancel_send<'a>(&self, tx: &'a mut Self::Tx<'a>);
fn poll_recv<'a>(
&'a self,
rx: &'a mut Self::Rx<'a>,
cx: &mut Context<'_>,
) -> Poll<Result<ReceivedFrame<'a>, TransportError>>;
fn requeue<'a>(&self, rx: &mut Self::Rx<'a>) -> Result<(), TransportError>;
}
pub(crate) mod trace;
pub(crate) mod wire;
#[cfg(all(test, hibana_repo_tests))]
mod tests;