1use crate::models::shared::types::JsonValue;
2use thiserror::Error;
3
4pub type Result<T> = std::result::Result<T, BitrouterError>;
5
6#[derive(Debug, Clone)]
7pub struct ProviderErrorContext {
8 pub status_code: Option<u16>,
9 pub error_type: Option<String>,
10 pub code: Option<String>,
11 pub param: Option<String>,
12 pub request_id: Option<String>,
13 pub body: Option<JsonValue>,
14}
15
16#[derive(Debug, Clone, Error)]
17pub enum BitrouterError {
18 #[error("{provider} does not support {feature}")]
19 UnsupportedFeature {
20 provider: String,
21 feature: String,
22 details: Option<String>,
23 },
24 #[error("request cancelled: {message}")]
25 Cancelled {
26 provider: Option<String>,
27 message: String,
28 },
29 #[error("invalid request: {message}")]
30 InvalidRequest {
31 provider: Option<String>,
32 message: String,
33 body: Option<JsonValue>,
34 },
35 #[error("transport failure: {message}")]
36 Transport {
37 provider: Option<String>,
38 message: String,
39 },
40 #[error("response decode failure: {message}")]
41 ResponseDecode {
42 provider: Option<String>,
43 message: String,
44 body: Option<JsonValue>,
45 },
46 #[error("invalid response: {message}")]
47 InvalidResponse {
48 provider: Option<String>,
49 message: String,
50 body: Option<JsonValue>,
51 },
52 #[error("provider error: {message}")]
53 Provider {
54 provider: String,
55 message: String,
56 context: Box<ProviderErrorContext>,
57 },
58 #[error("stream protocol failure: {message}")]
59 StreamProtocol {
60 provider: Option<String>,
61 message: String,
62 chunk: Option<JsonValue>,
63 },
64 #[error("access denied: {message}")]
65 AccessDenied { message: String },
66}
67
68impl BitrouterError {
69 pub fn cancelled(provider: Option<&str>, message: impl Into<String>) -> Self {
70 Self::Cancelled {
71 provider: provider.map(str::to_owned),
72 message: message.into(),
73 }
74 }
75
76 pub fn unsupported(
77 provider: impl Into<String>,
78 feature: impl Into<String>,
79 details: Option<String>,
80 ) -> Self {
81 Self::UnsupportedFeature {
82 provider: provider.into(),
83 feature: feature.into(),
84 details,
85 }
86 }
87
88 pub fn invalid_request(
89 provider: Option<&str>,
90 message: impl Into<String>,
91 body: Option<JsonValue>,
92 ) -> Self {
93 Self::InvalidRequest {
94 provider: provider.map(str::to_owned),
95 message: message.into(),
96 body,
97 }
98 }
99
100 pub fn transport(provider: Option<&str>, message: impl Into<String>) -> Self {
101 Self::Transport {
102 provider: provider.map(str::to_owned),
103 message: message.into(),
104 }
105 }
106
107 pub fn response_decode(
108 provider: Option<&str>,
109 message: impl Into<String>,
110 body: Option<JsonValue>,
111 ) -> Self {
112 Self::ResponseDecode {
113 provider: provider.map(str::to_owned),
114 message: message.into(),
115 body,
116 }
117 }
118
119 pub fn invalid_response(
120 provider: Option<&str>,
121 message: impl Into<String>,
122 body: Option<JsonValue>,
123 ) -> Self {
124 Self::InvalidResponse {
125 provider: provider.map(str::to_owned),
126 message: message.into(),
127 body,
128 }
129 }
130
131 pub fn provider_error(
132 provider: impl Into<String>,
133 message: impl Into<String>,
134 context: ProviderErrorContext,
135 ) -> Self {
136 Self::Provider {
137 provider: provider.into(),
138 message: message.into(),
139 context: Box::new(context),
140 }
141 }
142
143 pub fn stream_protocol(
144 provider: Option<&str>,
145 message: impl Into<String>,
146 chunk: Option<JsonValue>,
147 ) -> Self {
148 Self::StreamProtocol {
149 provider: provider.map(str::to_owned),
150 message: message.into(),
151 chunk,
152 }
153 }
154}