use serde::de::DeserializeOwned;
use crate::error::HttpError;
pub type Response<R, E = HttpError> = Result<R, E>;
#[derive(Debug)]
pub struct RawResponse {
status: u16,
pub(crate) body: Vec<u8>,
}
impl RawResponse {
pub fn new(status: u16, body: Vec<u8>) -> Self {
Self { status, body }
}
pub fn status(&self) -> u16 {
self.status
}
pub fn is_success(&self) -> bool {
(200..300).contains(&self.status)
}
pub fn is_client_error(&self) -> bool {
(400..500).contains(&self.status)
}
pub fn is_server_error(&self) -> bool {
(500..600).contains(&self.status)
}
pub fn body_lossy(&self) -> String {
String::from_utf8_lossy(&self.body).into_owned()
}
pub fn json_or_status_error<T: DeserializeOwned>(self) -> Response<T> {
if !self.is_success() {
return Err(HttpError::Status {
status: self.status,
message: self.body_lossy(),
});
}
serde_json::from_slice(&self.body).map_err(HttpError::from)
}
pub async fn text(self) -> Response<String> {
String::from_utf8(self.body).map_err(|e| HttpError::Other(e.to_string()))
}
pub async fn json<T: DeserializeOwned>(self) -> Response<T> {
serde_json::from_slice(&self.body).map_err(HttpError::from)
}
pub async fn bytes(self) -> Response<Vec<u8>> {
Ok(self.body)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_response_type_is_result() {
let success: Response<i32> = Ok(42);
assert!(success.is_ok());
assert!(matches!(success, Ok(42)));
let error: Response<i32> = Err(HttpError::Timeout);
assert!(error.is_err());
assert!(matches!(error, Err(HttpError::Timeout)));
}
}