Skip to main content

signal_fish_client/
error.rs

1//! Error types for the Signal Fish client.
2
3use crate::error_codes::ErrorCode;
4use thiserror::Error;
5
6/// Errors that can occur when using the Signal Fish client.
7#[derive(Debug, Error)]
8pub enum SignalFishError {
9    /// Failed to send a message through the transport.
10    #[error("transport send error: {0}")]
11    TransportSend(String),
12
13    /// Failed to receive a message from the transport.
14    #[error("transport receive error: {0}")]
15    TransportReceive(String),
16
17    /// The transport connection was closed unexpectedly.
18    #[error("transport connection closed")]
19    TransportClosed,
20
21    /// Failed to serialize or deserialize a protocol message.
22    #[error("serialization error: {0}")]
23    Serialization(#[from] serde_json::Error),
24
25    /// Attempted an operation that requires an active connection, but the client is not connected.
26    #[error("not connected to server")]
27    NotConnected,
28
29    /// Attempted a room operation but the client is not in a room.
30    #[error("not in a room")]
31    NotInRoom,
32
33    /// The server returned an error message.
34    #[error("server error: {message}")]
35    ServerError {
36        /// Human-readable error message from the server.
37        message: String,
38        /// Structured error code, if provided by the server.
39        error_code: Option<ErrorCode>,
40    },
41
42    /// An operation timed out.
43    #[error("operation timed out")]
44    Timeout,
45
46    /// An I/O error occurred.
47    #[error("I/O error: {0}")]
48    Io(#[from] std::io::Error),
49}
50
51/// A specialized [`Result`] type for Signal Fish client operations.
52pub type Result<T> = std::result::Result<T, SignalFishError>;
53
54#[cfg(test)]
55#[allow(
56    clippy::unwrap_used,
57    clippy::expect_used,
58    clippy::panic,
59    clippy::todo,
60    clippy::unimplemented,
61    clippy::indexing_slicing
62)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn server_error_uses_typed_error_code() {
68        let err = SignalFishError::ServerError {
69            message: "room full".into(),
70            error_code: Some(ErrorCode::RoomFull),
71        };
72
73        if let SignalFishError::ServerError {
74            message,
75            error_code,
76        } = err
77        {
78            assert_eq!(message, "room full");
79            assert_eq!(error_code, Some(ErrorCode::RoomFull));
80        } else {
81            panic!("expected ServerError");
82        }
83    }
84}