cloudflare-kv-proxy 0.2.0

Cloudflare KV Proxy SDK.
Documentation
use serde::{de::DeserializeOwned, Deserialize};

pub type Result<T> = std::result::Result<T, Error>;

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("key not found")]
    NotFound,
    #[error("unauthorized")]
    Unauthorized,
    #[error("bad request")]
    BadRequest,
    #[error("api error code {0}: {1}")]
    Api(u16, String),

    #[error("reqwest error")]
    Reqwest(reqwest::Error),
}

impl From<reqwest::Error> for Error {
    fn from(e: reqwest::Error) -> Self {
        match e.status() {
            Some(code) if code == 400 => Self::BadRequest,
            Some(code) if code == 401 => Self::Unauthorized,
            Some(code) if code == 404 => Self::NotFound,
            _ => Self::Reqwest(e),
        }
    }
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub(crate) enum ApiResult<T>
where
    T: DeserializeOwned,
{
    Ok {
        #[serde(with = "serde_with::json::nested")]
        result: T,
    },
    Err {
        code: u16,
        error: String,
    },
}

impl<T> From<ApiResult<T>> for Result<T>
where
    T: DeserializeOwned,
{
    fn from(r: ApiResult<T>) -> Self {
        match r {
            ApiResult::Ok { result } => Ok(result),
            ApiResult::Err { code, error } => Err(Error::Api(code, error)),
        }
    }
}

pub trait NotFoundMapping<T> {
    fn map_not_found_to_option(self) -> Result<Option<T>>;
}

impl<T> NotFoundMapping<T> for Result<T> {
    fn map_not_found_to_option(self) -> Result<Option<T>> {
        self.map(Some).or_else(|e| match e {
            Error::NotFound => Ok(None),
            _ => Err(e),
        })
    }
}