use serde::{Deserialize, Serialize};
use strum::{EnumCount, VariantArray};
use super::messages::Message;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, derive_more::TryFrom)]
pub enum Channel {
Control,
Logical(LogicalChannel),
}
impl Channel {
pub const COUNT: usize = LogicalChannel::COUNT + 1;
pub fn all() -> [Channel; LogicalChannel::COUNT + 1] {
[Self::Control]
.into_iter()
.chain(LogicalChannel::VARIANTS.iter().copied().map(Self::Logical))
.collect::<Vec<_>>()
.try_into()
.expect("static length")
}
pub fn fmt_short(&self) -> &'static str {
match self {
Channel::Control => "Ctl",
Channel::Logical(ch) => ch.fmt_short(),
}
}
pub fn id(&self) -> u8 {
match self {
Channel::Control => 0,
Channel::Logical(ch) => ch.id(),
}
}
pub fn from_id(id: u8) -> Result<Self, InvalidChannelId> {
match id {
0 => Ok(Self::Control),
_ => {
let ch = LogicalChannel::from_id(id)?;
Ok(Self::Logical(ch))
}
}
}
}
#[derive(
Debug,
Serialize,
Deserialize,
Copy,
Clone,
Eq,
PartialEq,
Hash,
strum::EnumIter,
strum::VariantArray,
strum::EnumCount,
)]
pub enum LogicalChannel {
Intersection,
Capability,
AreaOfInterest,
StaticToken,
Reconciliation,
Data,
}
#[derive(Debug, thiserror::Error)]
#[error("invalid channel id")]
pub struct InvalidChannelId;
impl LogicalChannel {
pub fn all() -> [LogicalChannel; LogicalChannel::COUNT] {
LogicalChannel::VARIANTS
.try_into()
.expect("statically checked")
}
pub fn fmt_short(&self) -> &'static str {
match self {
LogicalChannel::Intersection => "Pai",
LogicalChannel::Reconciliation => "Rec",
LogicalChannel::StaticToken => "StT",
LogicalChannel::Capability => "Cap",
LogicalChannel::AreaOfInterest => "AoI",
LogicalChannel::Data => "Dat",
}
}
pub fn from_id(id: u8) -> Result<Self, InvalidChannelId> {
match id {
2 => Ok(Self::Intersection),
3 => Ok(Self::AreaOfInterest),
4 => Ok(Self::Capability),
5 => Ok(Self::StaticToken),
6 => Ok(Self::Reconciliation),
7 => Ok(Self::Data),
_ => Err(InvalidChannelId),
}
}
pub fn id(&self) -> u8 {
match self {
LogicalChannel::Intersection => 2,
LogicalChannel::AreaOfInterest => 3,
LogicalChannel::Capability => 4,
LogicalChannel::StaticToken => 5,
LogicalChannel::Reconciliation => 6,
LogicalChannel::Data => 7,
}
}
}
impl Message {
pub fn channel(&self) -> Channel {
match self {
Message::PaiBindFragment(_) | Message::PaiReplyFragment(_) => {
Channel::Logical(LogicalChannel::Intersection)
}
Message::SetupBindReadCapability(_) => Channel::Logical(LogicalChannel::Capability),
Message::SetupBindAreaOfInterest(_) => Channel::Logical(LogicalChannel::AreaOfInterest),
Message::SetupBindStaticToken(_) => Channel::Logical(LogicalChannel::StaticToken),
Message::ReconciliationSendFingerprint(_)
| Message::ReconciliationAnnounceEntries(_)
| Message::ReconciliationSendEntry(_)
| Message::ReconciliationSendPayload(_)
| Message::ReconciliationTerminatePayload(_) => {
Channel::Logical(LogicalChannel::Reconciliation)
}
Message::DataSendEntry(_)
| Message::DataSendPayload(_)
| Message::DataSetMetadata(_) => Channel::Logical(LogicalChannel::Data),
Message::CommitmentReveal(_)
| Message::PaiRequestSubspaceCapability(_)
| Message::PaiReplySubspaceCapability(_)
| Message::ControlIssueGuarantee(_)
| Message::ControlAbsolve(_)
| Message::ControlPlead(_)
| Message::ControlAnnounceDropping(_)
| Message::ControlApologise(_)
| Message::ControlFreeHandle(_) => Channel::Control,
}
}
}