use std::collections::HashMap;
use slab::Slab;
use crate::{
StreamId,
codec::RammuxCodec,
connection::{downgrade::Downgraded, pings::OutboundPings},
error::ErrorKind,
header::PingPayload,
rr_bus::{Node, RoundRobinBus},
stream::StreamHandle,
};
#[allow(clippy::large_enum_variant)]
pub enum ConnState<IO> {
Active(Active<IO>),
Poisoned,
Downgraded,
}
impl<IO> ConnState<IO> {
pub fn active_mut(&mut self) -> Result<&mut Active<IO>, ErrorKind> {
match self {
Self::Active(active) => Ok(active),
Self::Poisoned => Err(ErrorKind::Poisoned),
Self::Downgraded => Err(ErrorKind::AlreadyDowngraded),
}
}
pub fn active(&self) -> Result<&Active<IO>, ErrorKind> {
match self {
Self::Active(active) => Ok(active),
Self::Poisoned => Err(ErrorKind::Poisoned),
Self::Downgraded => Err(ErrorKind::AlreadyDowngraded),
}
}
pub fn downgrade(&mut self, term_received: bool) -> Result<Downgraded<IO>, ErrorKind> {
match std::mem::replace(self, Self::Downgraded) {
Self::Active(active) => Ok(Downgraded::new(active.codec, term_received)),
Self::Poisoned => {
*self = Self::Poisoned;
Err(ErrorKind::Poisoned)
},
Self::Downgraded => Err(ErrorKind::AlreadyDowngraded),
}
}
}
pub struct Active<IO> {
pub codec: RammuxCodec<IO>,
pub streams: ActiveStreams,
pub bus: RoundRobinBus<StreamHandle>,
pub out_pings: OutboundPings,
pub in_ping: Option<PingPayload>,
}
#[derive(Default)]
pub struct ActiveStreams {
pub outbound: Slab<Node<StreamHandle>>,
pub inbound: HashMap<StreamId, Node<StreamHandle>>,
}
impl Drop for ActiveStreams {
fn drop(&mut self) {
for stream in self.outbound.drain() {
stream.modify(StreamHandle::abort);
}
for (_, stream) in self.inbound.drain() {
stream.modify(StreamHandle::abort);
}
}
}