use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("WATASU_API_KEY is required")]
MissingApiKey,
#[error("authentication failed: {0}")]
Authentication(String),
#[error("not found: {0}")]
NotFound(String),
#[error("conflict: {0}")]
Conflict(String),
#[error("request timed out")]
Timeout,
#[error("invalid argument: {0}")]
InvalidArgument(String),
#[error("rate limit exceeded: {0}")]
RateLimit(String),
#[error("not enough space: {0}")]
NotEnoughSpace(String),
#[error("file not found: {0}")]
FileNotFound(String),
#[error(
"{stream} exceeded configured byte limit of {max_bytes} bytes (saw {actual_bytes} bytes)"
)]
ByteLimitExceeded {
stream: &'static str,
max_bytes: usize,
actual_bytes: usize,
},
#[error("command exited with code {}", result.exit_code)]
CommandExit {
result: crate::CommandResult,
},
#[error("{0}")]
Sandbox(String),
#[error(transparent)]
Http(#[from] reqwest::Error),
#[error(transparent)]
Url(#[from] url::ParseError),
#[error(transparent)]
Json(#[from] serde_json::Error),
#[error(transparent)]
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
#[error(transparent)]
HttpHeader(#[from] http::header::InvalidHeaderValue),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
HttpBuild(#[from] http::Error),
}
impl Error {
pub(crate) fn from_status(status: reqwest::StatusCode, payload: &serde_json::Value) -> Self {
let code = payload
.get("error")
.and_then(|v| v.as_str())
.unwrap_or_default();
let message = payload
.get("message")
.and_then(|v| v.as_str())
.map(ToOwned::to_owned)
.or_else(|| {
payload
.get("errors")
.and_then(|v| v.as_array())
.map(|items| {
items
.iter()
.map(|item| item.as_str().unwrap_or_default())
.collect::<Vec<_>>()
.join(", ")
})
})
.unwrap_or_else(|| code.to_string());
match status.as_u16() {
401 | 403 => Self::Authentication(message),
404 => Self::NotFound(message),
409 => Self::Conflict(message),
408 | 504 => Self::Timeout,
400 | 422 => Self::InvalidArgument(message),
429 => Self::RateLimit(message),
_ if code == "not_enough_space" => Self::NotEnoughSpace(message),
_ if code == "file_not_found" => Self::FileNotFound(message),
_ => Self::Sandbox(message),
}
}
}