use crate::core::{ChannelId, MessageId};
use crate::integrity::IntegrityConfig;
use crate::reliability::{ChannelReliability, ReliabilityMode};
pub(crate) const MAX_WIRE_BYTES: usize = 128;
pub(crate) const MAX_INGRESS_BYTES: usize = MAX_WIRE_BYTES * MAX_EVENTS;
pub(crate) const MAX_MESSAGE_BYTES: usize = 256;
pub(crate) const MAX_EVENTS: usize = 16;
pub(crate) const MAX_MESSAGE_EVENTS: usize = 16;
pub(crate) const MAX_IN_FLIGHT_PACKETS: usize = 16;
pub(crate) const MAX_PENDING_ACKS: usize = 16;
pub(crate) const MAX_REASSEMBLY_MESSAGES: usize = 4;
pub(crate) const MAX_CHANNEL_POLICIES: usize = 4;
pub(crate) const MAX_CHANNEL_SPECS: usize = 4;
pub(crate) const DEFAULT_FRAGMENT_BYTES: usize = 64;
pub(crate) const DEFAULT_MAX_RETRANSMIT_ATTEMPTS: u8 = 10;
pub(crate) const DEFAULT_RETRANSMIT_TIMEOUT_MS: u64 = 250;
pub(crate) const DEFAULT_REASSEMBLY_TIMEOUT_MS: u64 = 2_000;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ChannelProfile {
Data,
Log,
}
impl ChannelProfile {
#[must_use]
pub const fn default_for(channel_id: ChannelId) -> Self {
if channel_id.is_log() {
Self::Log
} else {
Self::Data
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ChannelSpec {
pub channel_id: ChannelId,
pub profile: ChannelProfile,
pub reliability_mode: ReliabilityMode,
}
impl ChannelSpec {
#[must_use]
pub const fn new(
channel_id: ChannelId,
profile: ChannelProfile,
reliability_mode: ReliabilityMode,
) -> Self {
Self {
channel_id,
profile,
reliability_mode,
}
}
#[must_use]
pub const fn data(channel_id: ChannelId) -> Self {
Self::new(channel_id, ChannelProfile::Data, ReliabilityMode::Reliable)
}
#[must_use]
pub const fn log(channel_id: ChannelId) -> Self {
Self::new(channel_id, ChannelProfile::Log, ReliabilityMode::BestEffort)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EngineConfig {
pub initial_message_id: MessageId,
pub fragment_bytes: usize,
pub max_retransmit_attempts: u8,
pub retransmit_timeout_ms: u64,
pub reassembly_timeout_ms: u64,
pub integrity: IntegrityConfig,
pub channel_specs: [Option<ChannelSpec>; 4],
pub channel_policies: [Option<ChannelReliability>; 4],
}
impl Default for EngineConfig {
fn default() -> Self {
Self {
initial_message_id: MessageId::ZERO,
fragment_bytes: DEFAULT_FRAGMENT_BYTES,
max_retransmit_attempts: DEFAULT_MAX_RETRANSMIT_ATTEMPTS,
retransmit_timeout_ms: DEFAULT_RETRANSMIT_TIMEOUT_MS,
reassembly_timeout_ms: DEFAULT_REASSEMBLY_TIMEOUT_MS,
integrity: IntegrityConfig::DEFAULT,
channel_specs: [None; MAX_CHANNEL_SPECS],
channel_policies: [None; MAX_CHANNEL_POLICIES],
}
}
}
impl EngineConfig {
pub(crate) fn reliability_mode(&self, channel_id: ChannelId) -> ReliabilityMode {
let mut spec_index = 0;
while spec_index < MAX_CHANNEL_SPECS {
if let Some(spec) = self.channel_specs[spec_index]
&& spec.channel_id.get() == channel_id.get()
{
return spec.reliability_mode;
}
spec_index += 1;
}
if channel_id.is_log() {
return ReliabilityMode::BestEffort;
}
let mut index = 0;
while index < MAX_CHANNEL_POLICIES {
if let Some(policy) = self.channel_policies[index]
&& policy.channel_id.get() == channel_id.get()
{
return policy.mode;
}
index += 1;
}
ReliabilityMode::Reliable
}
pub(crate) fn channel_profile(&self, channel_id: ChannelId) -> ChannelProfile {
let mut index = 0;
while index < MAX_CHANNEL_SPECS {
if let Some(spec) = self.channel_specs[index]
&& spec.channel_id.get() == channel_id.get()
{
return spec.profile;
}
index += 1;
}
ChannelProfile::default_for(channel_id)
}
}