alibabacloud-imm 0.1.0

A modern, easy-to-use, and reqwest-powered Rust SDK for Alibaba Cloud Intelligent Media Management (IMM)
Documentation
use std::fmt;
use std::marker::PhantomData;

use serde::Deserialize;
use serde::de::DeserializeOwned;

use crate::{Error, Result};

#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ErrorResponse {
    pub code: String,
    pub message: String,
    pub request_id: String,
    #[serde(default)]
    pub host_id: String,
    #[serde(default)]
    pub recommend: String,
}

impl fmt::Display for ErrorResponse {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "code={}, message={}, request_id={}",
            self.code, self.message, self.request_id
        )
    }
}

impl std::error::Error for ErrorResponse {}

async fn process_response_error(resp: reqwest::Response) -> Result<Error> {
    let status = resp.status();
    let text = resp.text().await?;
    let error = if text.trim().is_empty() {
        None
    } else {
        Some(Box::new(serde_json::from_str::<ErrorResponse>(&text)?))
    };
    Ok(Error::ApiError {
        status_code: status,
        message: error,
    })
}

pub trait ResponseProcessor {
    type Output;

    fn from_response(response: reqwest::Response) -> impl Future<Output = Result<Self::Output>>;
}

pub struct EmptyResponseProcessor;

impl ResponseProcessor for EmptyResponseProcessor {
    type Output = ();

    async fn from_response(resp: reqwest::Response) -> Result<()> {
        let status = resp.status();
        if status.is_success() {
            Ok(())
        } else {
            Err(process_response_error(resp).await?)
        }
    }
}

pub struct BodyResponseProcessor<T>(PhantomData<T>);

impl<T> ResponseProcessor for BodyResponseProcessor<T>
where
    T: DeserializeOwned,
{
    type Output = T;

    async fn from_response(resp: reqwest::Response) -> Result<Self::Output> {
        let status = resp.status();
        if status.is_success() {
            let text = resp.text().await?;
            Ok(serde_json::from_str(&text)?)
        } else {
            Err(process_response_error(resp).await?)
        }
    }
}