cratestack_client_rust/subscription/
frames.rs1use cratestack_core::CratestackErrorResponse;
4use cratestack_core::rpc::{RpcErrorBody, rpc_code_to_cratestack_error_code};
5use reqwest::StatusCode;
6use serde::de::DeserializeOwned;
7
8use crate::error::ClientError;
9use crate::remote_refusal::Challenges;
10
11pub fn rpc_error_to_client(body: RpcErrorBody) -> ClientError {
14 let status = match body.code.as_str() {
15 "invalid_argument" => StatusCode::BAD_REQUEST,
16 "unauthenticated" => StatusCode::UNAUTHORIZED,
17 "permission_denied" => StatusCode::FORBIDDEN,
18 "not_found" => StatusCode::NOT_FOUND,
19 "conflict" | "aborted" => StatusCode::CONFLICT,
20 "failed_precondition" => StatusCode::PRECONDITION_FAILED,
21 "resource_exhausted" => StatusCode::TOO_MANY_REQUESTS,
22 "unavailable" => StatusCode::SERVICE_UNAVAILABLE,
23 _ => StatusCode::INTERNAL_SERVER_ERROR,
24 };
25 let message = body.message.clone();
26 let error = serde_json::to_value(&body)
32 .map(|mut value| {
33 value["code"] = rpc_code_to_cratestack_error_code(&body.code).into();
34 value
35 })
36 .and_then(serde_json::from_value::<CratestackErrorResponse>)
37 .ok()
38 .map(Box::new);
39 ClientError::Remote {
40 status,
41 error,
42 message,
43 challenges: Challenges::default(),
44 }
45}
46
47pub(super) fn item<T: DeserializeOwned>(value: serde_json::Value) -> Result<T, ClientError> {
49 serde_json::from_value(value)
50 .map_err(|error| ClientError::InvalidResponse(format!("subscription item: {error}")))
51}
52
53#[cfg(test)]
54mod tests;