Skip to main content

bitrouter_core/
errors.rs

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<Box<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<Box<JsonValue>>,
45    },
46    #[error("invalid response: {message}")]
47    InvalidResponse {
48        provider: Option<String>,
49        message: String,
50        body: Option<Box<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<Box<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: body.map(Box::new),
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: body.map(Box::new),
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: body.map(Box::new),
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: chunk.map(Box::new),
152        }
153    }
154}