use std::{fmt, sync::Arc};
#[derive(Debug, Clone)]
pub struct DisconnectReason {
pub message: String,
pub code: Option<u16>,
}
impl DisconnectReason {
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
code: None,
}
}
pub fn with_code(message: impl Into<String>, code: u16) -> Self {
Self {
message: message.into(),
code: Some(code),
}
}
}
impl fmt::Display for DisconnectReason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(code) = self.code {
write!(f, "{} (code: {})", self.message, code)
} else {
write!(f, "{}", self.message)
}
}
}
#[derive(Debug, Clone)]
pub struct ConnectionError {
pub message: String,
pub recoverable: bool,
pub url: Option<String>,
pub auth_user: Option<String>,
pub hint: Option<String>,
}
impl ConnectionError {
pub fn new(message: impl Into<String>, recoverable: bool) -> Self {
Self {
message: message.into(),
recoverable,
url: None,
auth_user: None,
hint: None,
}
}
pub fn with_url(mut self, url: impl Into<String>) -> Self {
self.url = Some(url.into());
self
}
pub fn with_auth_user(mut self, auth_user: impl Into<String>) -> Self {
self.auth_user = Some(auth_user.into());
self
}
pub fn with_hint(mut self, hint: impl Into<String>) -> Self {
self.hint = Some(hint.into());
self
}
}
impl fmt::Display for ConnectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageDirection {
Inbound,
Outbound,
}
impl fmt::Display for MessageDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MessageDirection::Inbound => write!(f, "inbound"),
MessageDirection::Outbound => write!(f, "outbound"),
}
}
}
pub type OnConnectCallback = Arc<dyn Fn() + Send + Sync>;
pub type OnDisconnectCallback = Arc<dyn Fn(DisconnectReason) + Send + Sync>;
pub type OnErrorCallback = Arc<dyn Fn(ConnectionError) + Send + Sync>;
pub type OnReceiveCallback = Arc<dyn Fn(&str) + Send + Sync>;
pub type OnSendCallback = Arc<dyn Fn(&str) + Send + Sync>;
#[derive(Clone, Default)]
pub struct EventHandlers {
pub(crate) on_connect: Option<OnConnectCallback>,
pub(crate) on_disconnect: Option<OnDisconnectCallback>,
pub(crate) on_error: Option<OnErrorCallback>,
pub(crate) on_receive: Option<OnReceiveCallback>,
pub(crate) on_send: Option<OnSendCallback>,
}
impl fmt::Debug for EventHandlers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventHandlers")
.field("on_connect", &self.on_connect.is_some())
.field("on_disconnect", &self.on_disconnect.is_some())
.field("on_error", &self.on_error.is_some())
.field("on_receive", &self.on_receive.is_some())
.field("on_send", &self.on_send.is_some())
.finish()
}
}
impl EventHandlers {
pub fn new() -> Self {
Self::default()
}
pub fn on_connect(mut self, f: impl Fn() + Send + Sync + 'static) -> Self {
self.on_connect = Some(Arc::new(f));
self
}
pub fn on_disconnect(mut self, f: impl Fn(DisconnectReason) + Send + Sync + 'static) -> Self {
self.on_disconnect = Some(Arc::new(f));
self
}
pub fn on_error(mut self, f: impl Fn(ConnectionError) + Send + Sync + 'static) -> Self {
self.on_error = Some(Arc::new(f));
self
}
pub fn on_receive(mut self, f: impl Fn(&str) + Send + Sync + 'static) -> Self {
self.on_receive = Some(Arc::new(f));
self
}
pub fn on_send(mut self, f: impl Fn(&str) + Send + Sync + 'static) -> Self {
self.on_send = Some(Arc::new(f));
self
}
pub fn has_any(&self) -> bool {
self.on_connect.is_some()
|| self.on_disconnect.is_some()
|| self.on_error.is_some()
|| self.on_receive.is_some()
|| self.on_send.is_some()
}
#[cfg(feature = "tokio-runtime")]
pub(crate) fn emit_connect(&self) {
if let Some(cb) = &self.on_connect {
cb();
}
}
#[cfg(feature = "tokio-runtime")]
pub(crate) fn emit_disconnect(&self, reason: DisconnectReason) {
if let Some(cb) = &self.on_disconnect {
cb(reason);
}
}
#[cfg(feature = "tokio-runtime")]
pub(crate) fn emit_error(&self, error: ConnectionError) {
if let Some(cb) = &self.on_error {
cb(error);
}
}
#[cfg(feature = "tokio-runtime")]
pub(crate) fn emit_receive(&self, raw: &str) {
if let Some(cb) = &self.on_receive {
cb(raw);
}
}
#[cfg(feature = "tokio-runtime")]
pub(crate) fn emit_send(&self, raw: &str) {
if let Some(cb) = &self.on_send {
cb(raw);
}
}
}