use crate::{
error::ConnectionError,
id::*,
model::{CloseCode as VoiceCloseCode, FromPrimitive},
ws::Error as WsError,
};
#[cfg(feature = "tungstenite")]
use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
#[derive(Debug)]
#[non_exhaustive]
pub struct DisconnectData<'a> {
pub kind: DisconnectKind,
pub reason: Option<DisconnectReason>,
pub channel_id: ChannelId,
pub guild_id: GuildId,
pub session_id: &'a str,
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum DisconnectKind {
Connect,
Reconnect,
Runtime,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum DisconnectReason {
AttemptDiscarded,
Internal,
Io,
ProtocolViolation,
TimedOut,
Requested,
WsClosed(Option<VoiceCloseCode>),
}
impl From<&ConnectionError> for DisconnectReason {
fn from(e: &ConnectionError) -> Self {
match e {
ConnectionError::AttemptDiscarded => Self::AttemptDiscarded,
ConnectionError::CryptoInvalidLength
| ConnectionError::CryptoModeInvalid
| ConnectionError::CryptoModeUnavailable
| ConnectionError::DaveCreateKeyPackageError(_)
| ConnectionError::DaveInitializationError(_)
| ConnectionError::EndpointUrl
| ConnectionError::IllegalDiscoveryResponse
| ConnectionError::IllegalIp
| ConnectionError::Json(_) => Self::ProtocolViolation,
ConnectionError::Io(_) => Self::Io,
ConnectionError::Crypto(_) | ConnectionError::InterconnectFailure(_) => Self::Internal,
ConnectionError::Ws(ws) => ws.into(),
ConnectionError::TimedOut => Self::TimedOut,
}
}
}
impl From<&WsError> for DisconnectReason {
fn from(e: &WsError) -> Self {
Self::WsClosed(match e {
#[cfg(feature = "tungstenite")]
WsError::WsClosed(Some(frame)) => match frame.code {
CloseCode::Library(l) => VoiceCloseCode::from_u16(l),
_ => None,
},
#[cfg(feature = "tws")]
WsError::WsClosed(Some(code)) => match (*code).into() {
code @ 4000..=4999_u16 => VoiceCloseCode::from_u16(code),
_ => None,
},
_ => None,
})
}
}