use std::collections::HashMap;
use async_selector::selector::Selector;
use slab::Slab;
use crate::{
StreamId,
codec::RammuxCodec,
connection::{downgrade::Downgraded, pings::OutboundPings},
error::ErrorKind,
header::PingPayload,
stream::{handle::StreamHandle, updates::StreamUpdates},
};
#[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 selector: Selector<StreamUpdates>,
pub out_pings: OutboundPings,
pub in_ping: Option<PingPayload>,
}
#[derive(Default)]
pub struct ActiveStreams {
pub outbound: Slab<StreamHandle>,
pub inbound: HashMap<StreamId, StreamHandle>,
}
impl Drop for ActiveStreams {
fn drop(&mut self) {
for stream in self.outbound.drain() {
stream.try_abort();
}
for (_, stream) in self.inbound.drain() {
stream.try_abort();
}
}
}