qobuz_api/api/
response.rs1use std::time::{SystemTime, UNIX_EPOCH};
4
5use {
6 reqwest::Response,
7 serde::de::DeserializeOwned,
8 serde_json::{Value, from_str},
9};
10
11use crate::errors::QobuzApiError::{
12 self, ApiErrorResponse, ApiResponseParseError, ResourceNotFoundError,
13};
14
15pub async fn parse_response<T: DeserializeOwned>(
30 response: Response,
31 endpoint: &str,
32) -> Result<T, QobuzApiError> {
33 let status = response.status();
34 let body = response.text().await?;
35
36 if status.is_success() {
37 return from_str::<T>(&body).map_err(|e| ApiResponseParseError {
38 content: truncate(&body, 500),
39 source_info: Some(format!("{e}")),
40 });
41 }
42
43 if let Ok(err) = from_str::<Value>(&body) {
44 let code = i32::try_from(err.get("code").and_then(Value::as_i64).unwrap_or_default())
45 .unwrap_or_default();
46 let message = err
47 .get("message")
48 .and_then(|v| v.as_str())
49 .unwrap_or("Unknown error");
50
51 if status.as_u16() == 404 {
52 return Err(ResourceNotFoundError {
53 resource_type: endpoint.trim_start_matches('/').to_string(),
54 resource_id: message.to_string(),
55 });
56 }
57
58 return Err(ApiErrorResponse {
59 code,
60 message: message.to_string(),
61 status: status.to_string(),
62 });
63 }
64
65 Err(ApiErrorResponse {
66 code: i32::from(status.as_u16()),
67 message: truncate(&body, 200),
68 status: status.to_string(),
69 })
70}
71
72#[must_use]
78pub fn timestamp() -> String {
79 let now = SystemTime::now()
80 .duration_since(UNIX_EPOCH)
81 .unwrap_or_default();
82 now.as_secs().to_string()
83}
84
85#[must_use]
96pub fn truncate(s: &str, max_len: usize) -> String {
97 if s.len() <= max_len {
98 s.to_string()
99 } else {
100 format!("{}...", &s[..max_len])
101 }
102}