1use std::fmt::Display;
2
3use reqwest_eventsource::CannotCloneRequestError;
4use serde::Deserialize;
5
6#[derive(Debug, thiserror::Error)]
7pub enum DashScopeError {
8 #[error("http error: {0}")]
9 Reqwest(#[from] reqwest::Error),
10
11 #[error("event source error: {0}")]
12 EventSource(#[from] CannotCloneRequestError),
13
14 #[error("failed to deserialize api response: {source}")]
15 JSONDeserialize {
16 source: serde_json::Error,
17 raw_response: Vec<u8>,
18 },
19 #[error("{0}")]
20 ElementError(String),
21 #[error("{0}")]
22 ApiError(ApiError),
23 #[error("invalid argument:{0}")]
24 InvalidArgument(String),
25 #[error("stream error:{0}")]
26 StreamError(String),
27 #[error("response body contains invalid UTF-8: {0}")]
28 InvalidUtf8(#[from] std::string::FromUtf8Error),
29
30 #[error("upload error: {0}")]
31 UploadError(String),
32
33 #[error("timeout error: {0}")]
34 TimeoutError(String),
35}
36
37#[derive(Debug, Deserialize, Clone)]
38pub struct ApiError {
39 pub message: String,
40 pub request_id: Option<String>,
41 pub code: Option<String>,
42}
43
44impl Display for ApiError {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 let mut parts = Vec::new();
47 if let Some(code) = &self.code {
48 parts.push(format!("code: {code}"));
49 }
50 if let Some(request_id) = &self.request_id {
51 parts.push(format!("request_id: {request_id}"));
52 }
53 write!(f, "{}", parts.join(" "))
54 }
55}
56
57impl From<crate::operation::common::ParametersBuilderError> for DashScopeError {
58 fn from(error: crate::operation::common::ParametersBuilderError) -> Self {
59 DashScopeError::InvalidArgument(error.to_string())
60 }
61}
62
63pub(crate) fn map_deserialization_error(e: serde_json::Error, bytes: &[u8]) -> DashScopeError {
64 tracing::error!(
65 "failed deserialization of: {}",
66 String::from_utf8_lossy(bytes)
67 );
68 DashScopeError::JSONDeserialize {
69 source: e,
70 raw_response: bytes.to_vec(),
71 }
72}
73
74pub type Result<T> = std::result::Result<T, DashScopeError>;