ribbit_client/
error.rs

1//! Error types for the Ribbit client
2//!
3//! This module defines the error types that can occur when using the Ribbit client.
4//!
5//! # Example
6//!
7//! ```
8//! use ribbit_client::{Error, Result, Region};
9//! use std::str::FromStr;
10//!
11//! fn example() -> Result<()> {
12//!     // This would return an InvalidRegion error
13//!     match Region::from_str("invalid") {
14//!         Ok(region) => Ok(()),
15//!         Err(e) => Err(e),
16//!     }
17//! }
18//!
19//! // Example of error handling
20//! let result = example();
21//! assert!(result.is_err());
22//! ```
23
24use thiserror::Error;
25
26/// Error types that can occur when using the Ribbit client
27#[derive(Debug, Error)]
28pub enum Error {
29    /// IO error occurred during network operations
30    #[error("IO error: {0}")]
31    Io(#[from] std::io::Error),
32
33    /// Invalid region string provided
34    #[error("Invalid region: {0}")]
35    InvalidRegion(String),
36
37    /// Failed to connect to the Ribbit server
38    #[error("Connection failed to {host}:{port}")]
39    ConnectionFailed {
40        /// The hostname that failed to connect
41        host: String,
42        /// The port number that failed to connect
43        port: u16,
44    },
45
46    /// Connection timed out
47    #[error("Connection timed out after {timeout_secs}s to {host}:{port}")]
48    ConnectionTimeout {
49        /// The hostname that timed out
50        host: String,
51        /// The port number that timed out
52        port: u16,
53        /// The timeout duration in seconds
54        timeout_secs: u64,
55    },
56
57    /// Failed to send request to the server
58    #[error("Failed to send request")]
59    SendFailed,
60
61    /// Failed to receive response from the server
62    #[error("Failed to receive response")]
63    ReceiveFailed,
64
65    /// Response format is invalid or unexpected
66    #[error("Invalid response format")]
67    InvalidResponse,
68
69    /// MIME parsing failed for V1 protocol responses
70    #[error("MIME parsing error: {0}")]
71    MimeParseError(String),
72
73    /// Checksum validation failed for V1 protocol responses
74    #[error("Checksum validation failed")]
75    ChecksumMismatch,
76
77    /// ASN.1 parsing failed for signature data
78    #[error("ASN.1 parsing error: {0}")]
79    Asn1Error(String),
80
81    /// General parsing error for response data
82    #[error("Parse error: {0}")]
83    ParseError(String),
84}
85
86/// Result type alias using the Ribbit Error type
87pub type Result<T> = std::result::Result<T, Error>;
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn test_error_display() {
95        let err = Error::InvalidRegion("xyz".to_string());
96        assert_eq!(err.to_string(), "Invalid region: xyz");
97
98        let err = Error::ConnectionFailed {
99            host: "test.battle.net".to_string(),
100            port: 1119,
101        };
102        assert_eq!(err.to_string(), "Connection failed to test.battle.net:1119");
103
104        let err = Error::ConnectionTimeout {
105            host: "test.battle.net".to_string(),
106            port: 1119,
107            timeout_secs: 10,
108        };
109        assert_eq!(
110            err.to_string(),
111            "Connection timed out after 10s to test.battle.net:1119"
112        );
113
114        let err = Error::SendFailed;
115        assert_eq!(err.to_string(), "Failed to send request");
116
117        let err = Error::ReceiveFailed;
118        assert_eq!(err.to_string(), "Failed to receive response");
119
120        let err = Error::InvalidResponse;
121        assert_eq!(err.to_string(), "Invalid response format");
122
123        let err = Error::MimeParseError("bad format".to_string());
124        assert_eq!(err.to_string(), "MIME parsing error: bad format");
125
126        let err = Error::ChecksumMismatch;
127        assert_eq!(err.to_string(), "Checksum validation failed");
128
129        let err = Error::Asn1Error("invalid ASN.1".to_string());
130        assert_eq!(err.to_string(), "ASN.1 parsing error: invalid ASN.1");
131
132        let err = Error::ParseError("invalid BPSV".to_string());
133        assert_eq!(err.to_string(), "Parse error: invalid BPSV");
134    }
135
136    #[test]
137    fn test_error_from_io() {
138        use std::io::{Error as IoError, ErrorKind};
139
140        let io_err = IoError::new(ErrorKind::ConnectionRefused, "refused");
141        let err: Error = io_err.into();
142
143        match err {
144            Error::Io(_) => {}
145            _ => panic!("Expected Error::Io variant"),
146        }
147    }
148}