openai_dive 1.4.3

OpenAI Dive is an unofficial async Rust library that allows you to interact with the OpenAI API.
Documentation
use crate::v1::error::APIError;
use reqwest::{Response, StatusCode};
use serde::de::DeserializeOwned;
use serde_json::Value;
#[cfg(feature = "download")]
use std::time::{SystemTime, UNIX_EPOCH};

pub(crate) async fn check_status_code(
    result: reqwest::Result<Response>,
) -> Result<Response, APIError> {
    match result {
        Ok(response) => {
            if response.status().is_client_error() {
                let status = response.status();
                let text = response
                    .text()
                    .await
                    .map_err(|error| APIError::ParseError(error.to_string()))?;

                match status {
                    StatusCode::BAD_REQUEST => {
                        return Err(APIError::BadRequestError(text));
                    }
                    StatusCode::UNAUTHORIZED => {
                        return Err(APIError::AuthenticationError(text));
                    }
                    StatusCode::FORBIDDEN => {
                        return Err(APIError::PermissionError(text));
                    }
                    StatusCode::NOT_FOUND => {
                        return Err(APIError::NotFoundError(text));
                    }
                    StatusCode::GONE => {
                        return Err(APIError::GoneError(text));
                    }
                    StatusCode::TOO_MANY_REQUESTS => {
                        return Err(APIError::RateLimitError(text));
                    }
                    _ => {
                        return Err(APIError::UnknownError(status.as_u16(), text));
                    }
                }
            }

            Ok(response)
        }
        Err(error) => Err(APIError::ServerError(error.to_string())),
    }
}

pub(crate) fn validate_response(response: String) -> Result<Value, APIError> {
    let value: Value =
        serde_json::from_str(&response).map_err(|error| APIError::ParseError(error.to_string()))?;

    if let Some(object) = value.as_object() {
        if object.len() == 1 && object.contains_key("error") {
            return Err(APIError::InvalidRequestError(value["error"].to_string()));
        }
    }

    Ok(value)
}

pub(crate) fn format_response<R: DeserializeOwned>(response: String) -> Result<R, APIError> {
    let value = validate_response(response)?;

    let value: R =
        serde_json::from_value(value).map_err(|error| APIError::ParseError(error.to_string()))?;

    Ok(value)
}

#[cfg(feature = "download")]
pub fn generate_file_name(path: &str, length: u32, file_type: &str) -> String {
    const ALPHABET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    let alphabet_len = ALPHABET.len();

    let start = SystemTime::now();
    let since_the_epoch = start.duration_since(UNIX_EPOCH).unwrap();
    let mut seed = since_the_epoch.as_nanos();

    let mut random_str = String::with_capacity(length as usize);

    for _ in 0..length {
        let index = (seed % alphabet_len as u128) as usize;
        random_str.push(ALPHABET[index] as char);
        seed /= alphabet_len as u128;
    }

    format!("{path}/{random_str}.{file_type}")
}