#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CloseCode(pub u16);
impl CloseCode {
pub const NORMAL: Self = Self(1000);
pub const GOING_AWAY: Self = Self(1001);
pub const PROTOCOL_ERROR: Self = Self(1002);
pub const UNSUPPORTED_DATA: Self = Self(1003);
pub const RESERVED: Self = Self(1004);
pub const NO_STATUS_RECEIVED: Self = Self(1005);
pub const ABNORMAL_CLOSURE: Self = Self(1006);
pub const INVALID_PAYLOAD: Self = Self(1007);
pub const POLICY_VIOLATION: Self = Self(1008);
pub const MESSAGE_TOO_BIG: Self = Self(1009);
pub const MANDATORY_EXTENSION: Self = Self(1010);
pub const INTERNAL_ERROR: Self = Self(1011);
pub const TLS_HANDSHAKE: Self = Self(1015);
pub fn new(code: u16) -> Self {
Self(code)
}
pub fn as_u16(self) -> u16 {
self.0
}
pub fn is_valid(self) -> bool {
matches!(self.0, 1000..=1004 | 1007..=1014 | 1016..=4999)
}
pub fn is_sendable(self) -> bool {
!matches!(self.0, 0..=999 | 1004 | 1005 | 1006 | 1015 | 2000..=2999 | 5000..)
}
}
impl From<u16> for CloseCode {
fn from(code: u16) -> Self {
Self(code)
}
}
impl From<CloseCode> for u16 {
fn from(code: CloseCode) -> Self {
code.0
}
}
impl std::fmt::Display for CloseCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let description = match self.0 {
1000 => "Normal Closure",
1001 => "Going Away",
1002 => "Protocol Error",
1003 => "Unsupported Data",
1004 => "Reserved",
1005 => "No Status Received",
1006 => "Abnormal Closure",
1007 => "Invalid Payload Data",
1008 => "Policy Violation",
1009 => "Message Too Big",
1010 => "Mandatory Extension",
1011 => "Internal Error",
1015 => "TLS Handshake",
3000..=3999 => "Library/Framework",
4000..=4999 => "Application",
_ => "Unknown",
};
write!(f, "{} ({})", self.0, description)
}
}