reach_websocket/
error.rs

1// SPDX-FileCopyrightText: 2025 Michael Goldenberg <m@mgoldenberg.net>
2// SPDX-License-Identifier: EUPL-1.2
3
4use futures::channel::mpsc;
5use futures::channel::oneshot::Canceled;
6use thiserror::Error;
7use tokio_tungstenite::tungstenite::Error as TungsteniteError;
8
9use reach_core::error::GenericWebSocketError;
10
11#[derive(Debug, Error)]
12pub enum WebSocketStreamError {
13    #[error("web socket: {0}")]
14    WebSocket(#[from] TungsteniteError),
15    #[error("unsupported web socket message")]
16    UnsupportedWebSocketMessage,
17    #[error("decoder: {0}")]
18    Decoder(#[from] reach_core::error::DecodeError),
19}
20
21pub type WebSocketStreamResult<T> = Result<T, WebSocketStreamError>;
22
23impl From<&WebSocketStreamError> for GenericWebSocketError {
24    fn from(value: &WebSocketStreamError) -> Self {
25        match value {
26            WebSocketStreamError::WebSocket(_) => Self::WebSocket,
27            WebSocketStreamError::UnsupportedWebSocketMessage => Self::Unsupported,
28            WebSocketStreamError::Decoder(_) => Self::Decode,
29        }
30    }
31}
32
33#[derive(Debug, Error)]
34pub enum WebSocketError {
35    #[error("web socket sink: {0}")]
36    WebSocketSink(#[from] TungsteniteError),
37    #[error("web socket stream: {0}")]
38    WebSocketStream(#[from] WebSocketStreamError),
39    #[error("incoming sink: {0}")]
40    IncomingSink(#[from] mpsc::SendError),
41    #[error("outgoing receiver closed: {0}")]
42    OutgoingReceiverClosed(#[from] Canceled),
43}
44
45impl From<&WebSocketError> for GenericWebSocketError {
46    fn from(value: &WebSocketError) -> Self {
47        match value {
48            WebSocketError::WebSocketSink(_) => Self::WebSocket,
49            WebSocketError::WebSocketStream(web_socket_stream_error) => {
50                web_socket_stream_error.into()
51            }
52            WebSocketError::IncomingSink(_) => Self::Internal,
53            WebSocketError::OutgoingReceiverClosed(_) => Self::Internal,
54        }
55    }
56}