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}