#![allow(unused_assignments)]
use crate::engine::EngineAction;
use crate::packet::{Frame, Handshake, Packet};
use bytestring::ByteString;
use miette::Diagnostic;
use thiserror::Error;
use tokio::sync::{mpsc, oneshot};
use tokio::task::JoinError;
use tokio::time::error::Elapsed;
pub type BoxedError = Box<dyn std::error::Error + Send + Sync + 'static>;
#[derive(Debug, Error, Diagnostic)]
#[error(transparent)]
#[diagnostic(transparent)]
pub enum Error {
Transport(#[from] TransportError),
Engine(#[from] EngineError),
}
#[derive(Debug, Error, Diagnostic)]
pub enum EngineError {
#[error("outbound frame channel closed")]
#[diagnostic(
code(eioc::engine::send_transport),
help("the transport task exited; check for prior transport errors")
)]
SendTransport(#[from] mpsc::error::SendError<Frame>),
#[error("inbound message sink closed")]
#[diagnostic(
code(eioc::engine::send_sink),
help("the consumer of inbound messages was dropped")
)]
SendSink(#[source] BoxedError),
#[error("failed to receive Engine.IO handshake")]
#[diagnostic(
code(eioc::engine::recv_handshake),
help(
"the transport task exited before completing the handshake; check the transport for prior errors"
)
)]
RecvHandshake(#[from] oneshot::error::RecvError),
#[error("background task failed")]
#[diagnostic(code(eioc::engine::join))]
Join(#[from] JoinError),
#[error("heartbeat timeout")]
#[diagnostic(
code(eioc::engine::heartbeat_timeout),
help("the server stopped responding; check the network or server load")
)]
HeartbeatTimeout(#[from] Elapsed),
#[error("unexpected packet {0:?}")]
#[diagnostic(
code(eioc::engine::server),
help(
"the server sent a packet that violates the Engine.IO state machine; likely a server bug or version mismatch"
)
)]
Server(Packet),
}
#[derive(Debug, Error, Diagnostic)]
pub enum TransportError {
#[error(transparent)]
#[diagnostic(transparent)]
WebSocket(#[from] WebSocketError),
#[error(transparent)]
#[diagnostic(transparent)]
Polling(#[from] PollingError),
#[error("engine action channel closed")]
#[diagnostic(
code(eioc::transport::send_engine),
help("the engine task exited; check for prior engine errors")
)]
SendEngine(#[from] mpsc::error::SendError<EngineAction>),
#[error("failed to send handshake to engine task")]
#[diagnostic(
code(eioc::transport::send_handshake),
help(
"the engine task exited before the handshake arrived; check the engine for prior errors"
)
)]
SendHandshake(Handshake),
#[error("background transport task failed")]
#[diagnostic(code(eioc::transport::join))]
Join(#[from] JoinError),
#[error("expected Open packet as first frame")]
#[diagnostic(
code(eioc::transport::open),
help(
"the server did not send the expected Open packet; check the server implementation and Engine.IO version"
)
)]
Open(Frame),
}
#[derive(Debug, Error, Diagnostic)]
pub enum WebSocketError {
#[error(transparent)]
#[diagnostic(code(eioc::transport::websocket::tungstenite))]
Tungstenite(#[from] tokio_tungstenite::tungstenite::Error),
#[error("WebSocket stream closed unexpectedly")]
#[diagnostic(
code(eioc::transport::websocket::closed),
help("the server closed the TCP connection without sending a WebSocket close frame")
)]
Closed,
#[error("probe Pong not received")]
#[diagnostic(
code(eioc::transport::websocket::probe),
help(
"the server did not respond to the probe Ping with a Pong; check the server implementation and Engine.IO version"
)
)]
Probe(Frame),
#[error(transparent)]
#[diagnostic(transparent)]
Packet(#[from] PacketError),
}
#[derive(Debug, Error, Diagnostic)]
pub enum PollingError {
#[error(transparent)]
#[diagnostic(code(eioc::transport::polling::reqwest))]
Reqwest(#[from] reqwest::Error),
#[error("failed to decode base64 attachment")]
#[diagnostic(code(eioc::transport::polling::base64))]
Base64(#[from] base64::DecodeError),
#[error("unexpected polling response: {0}")]
#[diagnostic(
code(eioc::transport::polling::response),
help(
"the server returned an unexpected body; verify the server implementation and Engine.IO version"
)
)]
Response(String),
#[error(transparent)]
#[diagnostic(transparent)]
Packet(#[from] PacketError),
}
#[derive(Debug, Error, Diagnostic)]
pub enum PacketError {
#[error("empty packet")]
#[diagnostic(code(eioc::packet::empty))]
Empty,
#[error("invalid type id {id}")]
#[diagnostic(code(eioc::packet::invalid_id))]
InvalidId { id: char },
#[error("failed to parse Open payload")]
#[diagnostic(code(eioc::packet::handshake))]
Handshake(#[from] serde_json::Error),
#[error("unexpected payload for type id {id}")]
#[diagnostic(code(eioc::packet::payload))]
Payload { id: char, payload: ByteString },
}