#![doc(html_logo_url = "https://cdn.worldvectorlogo.com/logos/websocket.svg")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
mod frame;
mod ws;
#[doc(hidden)]
pub use frame::Frame;
pub use ws::WebSocket;
#[derive(Debug)]
pub enum Role {
Server,
Client,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageType {
Text = 1,
Binary = 2,
}
impl MessageType {
#[inline]
pub fn is_text(&self) -> bool {
matches!(self, MessageType::Text)
}
#[inline]
pub fn is_binary(&self) -> bool {
matches!(self, MessageType::Binary)
}
}
#[derive(Debug, Clone)]
pub enum Stream {
Start(MessageType),
Next(MessageType),
End(MessageType),
}
impl Stream {
#[inline]
pub fn ty(&self) -> MessageType {
match *self {
Stream::Start(ty) => ty,
Stream::Next(ty) => ty,
Stream::End(ty) => ty,
}
}
}
#[derive(Debug, Clone)]
pub enum DataType {
Stream(Stream),
Complete(MessageType),
}
#[derive(Debug)]
pub enum Event {
Data {
ty: DataType,
data: Box<[u8]>,
},
Ping(Box<[u8]>),
Pong(Box<[u8]>),
Error(&'static str),
Close {
code: u16,
reason: Box<str>,
},
}
#[derive(Debug, Clone, Copy)]
pub enum CloseCode {
Normal = 1000,
Away = 1001,
ProtocolError = 1002,
Unsupported = 1003,
NoStatusRcvd = 1005,
Abnormal = 1006,
InvalidPayload = 1007,
PolicyViolation = 1008,
MessageTooBig = 1009,
MandatoryExt = 1010,
InternalError = 1011,
TLSHandshake = 1015,
}
impl From<CloseCode> for u16 {
#[inline]
fn from(code: CloseCode) -> Self {
code as u16
}
}
impl From<u16> for CloseCode {
#[inline]
fn from(value: u16) -> Self {
match value {
1000 => CloseCode::Normal,
1001 => CloseCode::Away,
1002 => CloseCode::ProtocolError,
1003 => CloseCode::Unsupported,
1005 => CloseCode::NoStatusRcvd,
1006 => CloseCode::Abnormal,
1007 => CloseCode::InvalidPayload,
1009 => CloseCode::MessageTooBig,
1010 => CloseCode::MandatoryExt,
1011 => CloseCode::InternalError,
1015 => CloseCode::TLSHandshake,
_ => CloseCode::PolicyViolation,
}
}
}
impl PartialEq<u16> for CloseCode {
#[inline]
fn eq(&self, other: &u16) -> bool {
(*self as u16) == *other
}
}
pub trait CloseReason {
type Bytes;
fn to_bytes(self) -> Self::Bytes;
}
impl CloseReason for () {
type Bytes = [u8; 0];
fn to_bytes(self) -> Self::Bytes {
[0; 0]
}
}
impl CloseReason for u16 {
type Bytes = [u8; 2];
fn to_bytes(self) -> Self::Bytes {
self.to_be_bytes()
}
}
impl CloseReason for CloseCode {
type Bytes = [u8; 2];
fn to_bytes(self) -> Self::Bytes {
(self as u16).to_be_bytes()
}
}
impl CloseReason for &str {
type Bytes = Vec<u8>;
fn to_bytes(self) -> Self::Bytes {
CloseReason::to_bytes((CloseCode::Normal, self))
}
}
impl<Code, Msg> CloseReason for (Code, Msg)
where
Code: Into<u16>,
Msg: AsRef<[u8]>,
{
type Bytes = Vec<u8>;
fn to_bytes(self) -> Self::Bytes {
let (code, reason) = (self.0.into(), self.1.as_ref());
let mut data = Vec::with_capacity(2 + reason.len());
data.extend_from_slice(&code.to_be_bytes());
data.extend_from_slice(reason);
data
}
}