use std::fmt;
use crate::error::{DisconnectReason, Error};
use crate::message::Message;
pub trait Protocol: Send + Sync {
fn subprotocol(&self) -> &str;
fn encode(&self, command: &Command) -> Result<Vec<u8>, Error>;
fn decode(&self, payload: &[u8]) -> Result<Incoming, Error>;
}
pub const SUBPROTOCOL_UNSUPPORTED: &str = "actioncable-unsupported";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CommandName {
Subscribe,
Unsubscribe,
Message,
}
impl CommandName {
pub fn as_str(self) -> &'static str {
match self {
CommandName::Subscribe => "subscribe",
CommandName::Unsubscribe => "unsubscribe",
CommandName::Message => "message",
}
}
}
impl fmt::Display for CommandName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Command {
pub name: CommandName,
pub identifier: String,
pub data: Option<String>,
}
impl Command {
pub fn subscribe(identifier: impl Into<String>) -> Command {
Command {
name: CommandName::Subscribe,
identifier: identifier.into(),
data: None,
}
}
pub fn unsubscribe(identifier: impl Into<String>) -> Command {
Command {
name: CommandName::Unsubscribe,
identifier: identifier.into(),
data: None,
}
}
pub fn message(identifier: impl Into<String>, data: impl Into<String>) -> Command {
Command {
name: CommandName::Message,
identifier: identifier.into(),
data: Some(data.into()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kind {
Welcome,
Ping,
Disconnect,
Confirmation,
Rejection,
Message,
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Kind::Welcome => "welcome",
Kind::Ping => "ping",
Kind::Disconnect => "disconnect",
Kind::Confirmation => "confirm_subscription",
Kind::Rejection => "reject_subscription",
Kind::Message => "message",
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Incoming {
pub kind: Kind,
pub identifier: String,
pub message: Option<Message>,
pub reason: Option<DisconnectReason>,
pub reconnect: bool,
}
impl Incoming {
pub fn new(kind: Kind) -> Incoming {
Incoming {
kind,
identifier: String::new(),
message: None,
reason: None,
reconnect: false,
}
}
}