cloudflare_kv_proxy/
types.rs

1use serde::{de::DeserializeOwned, Deserialize};
2
3pub type Result<T> = std::result::Result<T, Error>;
4
5#[derive(thiserror::Error, Debug)]
6pub enum Error {
7    #[error("key not found")]
8    NotFound,
9    #[error("unauthorized")]
10    Unauthorized,
11    #[error("bad request")]
12    BadRequest,
13    #[error("api error code {0}: {1}")]
14    Api(u16, String),
15
16    #[error("reqwest error")]
17    Reqwest(reqwest::Error),
18}
19
20impl From<reqwest::Error> for Error {
21    fn from(e: reqwest::Error) -> Self {
22        match e.status() {
23            Some(code) if code == 400 => Self::BadRequest,
24            Some(code) if code == 401 => Self::Unauthorized,
25            Some(code) if code == 404 => Self::NotFound,
26            _ => Self::Reqwest(e),
27        }
28    }
29}
30
31#[derive(Debug, Deserialize)]
32#[serde(untagged)]
33pub(crate) enum ApiResult<T>
34where
35    T: DeserializeOwned,
36{
37    Ok {
38        #[serde(with = "serde_with::json::nested")]
39        result: T,
40    },
41    Err {
42        code: u16,
43        error: String,
44    },
45}
46
47impl<T> From<ApiResult<T>> for Result<T>
48where
49    T: DeserializeOwned,
50{
51    fn from(r: ApiResult<T>) -> Self {
52        match r {
53            ApiResult::Ok { result } => Ok(result),
54            ApiResult::Err { code, error } => Err(Error::Api(code, error)),
55        }
56    }
57}
58
59pub trait NotFoundMapping<T> {
60    fn map_not_found_to_option(self) -> Result<Option<T>>;
61}
62
63impl<T> NotFoundMapping<T> for Result<T> {
64    fn map_not_found_to_option(self) -> Result<Option<T>> {
65        self.map(Some).or_else(|e| match e {
66            Error::NotFound => Ok(None),
67            _ => Err(e),
68        })
69    }
70}