Skip to main content

nautilus_betfair/stream/
error.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Betfair stream client error types.
17
18use std::fmt::Display;
19
20/// Represents stream client errors for the Betfair adapter.
21#[derive(Debug, Clone)]
22pub enum BetfairStreamError {
23    /// Failed to establish a connection.
24    ConnectionFailed(String),
25    /// Stream authentication failed.
26    AuthenticationFailed(String),
27    /// Stream protocol error (unexpected message format).
28    ProtocolError(String),
29    /// JSON serialization/deserialization error.
30    JsonError(String),
31    /// Connection or read timeout.
32    Timeout(String),
33    /// Connection was lost.
34    Disconnected(String),
35}
36
37impl Display for BetfairStreamError {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        match self {
40            Self::ConnectionFailed(msg) => write!(f, "Connection failed: {msg}"),
41            Self::AuthenticationFailed(msg) => write!(f, "Authentication failed: {msg}"),
42            Self::ProtocolError(msg) => write!(f, "Protocol error: {msg}"),
43            Self::JsonError(msg) => write!(f, "JSON error: {msg}"),
44            Self::Timeout(msg) => write!(f, "Timeout: {msg}"),
45            Self::Disconnected(msg) => write!(f, "Disconnected: {msg}"),
46        }
47    }
48}
49
50impl std::error::Error for BetfairStreamError {}
51
52impl From<serde_json::Error> for BetfairStreamError {
53    fn from(error: serde_json::Error) -> Self {
54        Self::JsonError(error.to_string())
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use rstest::rstest;
61
62    use super::*;
63
64    #[rstest]
65    #[case(
66        BetfairStreamError::ConnectionFailed("refused".to_string()),
67        "Connection failed: refused"
68    )]
69    #[case(
70        BetfairStreamError::AuthenticationFailed("invalid token".to_string()),
71        "Authentication failed: invalid token"
72    )]
73    #[case(
74        BetfairStreamError::ProtocolError("bad frame".to_string()),
75        "Protocol error: bad frame"
76    )]
77    #[case(
78        BetfairStreamError::JsonError("parse error".to_string()),
79        "JSON error: parse error"
80    )]
81    #[case(
82        BetfairStreamError::Timeout("read".to_string()),
83        "Timeout: read"
84    )]
85    #[case(
86        BetfairStreamError::Disconnected("reset".to_string()),
87        "Disconnected: reset"
88    )]
89    fn test_display(#[case] error: BetfairStreamError, #[case] expected: &str) {
90        assert_eq!(error.to_string(), expected);
91    }
92
93    #[rstest]
94    fn test_from_serde_error() {
95        let json_err = serde_json::from_str::<String>("bad").unwrap_err();
96        let err: BetfairStreamError = json_err.into();
97        assert!(matches!(err, BetfairStreamError::JsonError(_)));
98    }
99}