Skip to main content

boj_client/
error.rs

1use thiserror::Error;
2
3/// Error type returned by the BOJ client.
4///
5/// # Examples
6///
7/// ```
8/// use boj_client::error::BojError;
9///
10/// let error = BojError::validation("invalid parameter");
11/// assert!(matches!(error, BojError::ValidationError(_)));
12/// ```
13#[derive(Debug, Clone, PartialEq, Eq, Error)]
14pub enum BojError {
15    /// Input validation failed before sending a request.
16    #[error("validation error: {0}")]
17    ValidationError(String),
18
19    /// Response decoding failed for JSON/CSV payloads.
20    #[error("decode error: {0}")]
21    DecodeError(String),
22
23    /// Transport-level failure (network, HTTP client, invalid request shape).
24    #[error("transport error: {0}")]
25    TransportError(String),
26
27    /// API-level error represented by BOJ status and message fields.
28    #[error("api error: status={status}, message_id={message_id}, message={message}")]
29    ApiError {
30        /// BOJ `STATUS` value.
31        status: u16,
32        /// BOJ `MESSAGE-ID` value.
33        message_id: String,
34        /// BOJ `MESSAGE` value.
35        message: String,
36    },
37}
38
39impl BojError {
40    /// Creates [`BojError::ValidationError`].
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use boj_client::error::BojError;
46    ///
47    /// let error = BojError::validation("invalid db");
48    /// assert!(matches!(error, BojError::ValidationError(_)));
49    /// ```
50    pub fn validation(message: impl Into<String>) -> Self {
51        Self::ValidationError(message.into())
52    }
53
54    /// Creates [`BojError::DecodeError`].
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use boj_client::error::BojError;
60    ///
61    /// let error = BojError::decode("invalid JSON");
62    /// assert!(matches!(error, BojError::DecodeError(_)));
63    /// ```
64    pub fn decode(message: impl Into<String>) -> Self {
65        Self::DecodeError(message.into())
66    }
67
68    /// Creates [`BojError::TransportError`].
69    ///
70    /// # Examples
71    ///
72    /// ```
73    /// use boj_client::error::BojError;
74    ///
75    /// let error = BojError::transport("timeout");
76    /// assert!(matches!(error, BojError::TransportError(_)));
77    /// ```
78    pub fn transport(message: impl Into<String>) -> Self {
79        Self::TransportError(message.into())
80    }
81
82    /// Creates [`BojError::ApiError`].
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use boj_client::error::BojError;
88    ///
89    /// let error = BojError::api(500, "M181090S", "internal");
90    /// assert!(matches!(error, BojError::ApiError { status: 500, .. }));
91    /// ```
92    pub fn api(status: u16, message_id: impl Into<String>, message: impl Into<String>) -> Self {
93        Self::ApiError {
94            status,
95            message_id: message_id.into(),
96            message: message.into(),
97        }
98    }
99}