httpio 0.2.4

A transport-agnostic, async HTTP/1.1 client library for any runtime.
Documentation
pub mod traits;

use self::traits::CompressionDecoder;
use crate::enums::content_encoding::ContentEncoding;
use crate::enums::http_error::{HttpError, HttpErrorKind};
use futures::{AsyncBufRead, AsyncReadExt};
use std::sync::OnceLock;

static COMPRESSION_PROVIDER: OnceLock<Box<dyn CompressionDecoder>> = OnceLock::new();

pub fn set_compression_provider(provider: Box<dyn CompressionDecoder>) -> Result<(), HttpError> {
    COMPRESSION_PROVIDER
        .set(provider)
        .map_err(|_| HttpErrorKind::ForbiddenOperation.into())
}

fn get_provider() -> &'static Box<dyn CompressionDecoder> {
    COMPRESSION_PROVIDER.get_or_init(|| {
        struct NoOpDecoder;
        impl CompressionDecoder for NoOpDecoder {
            fn supported_encodings(&self) -> Vec<ContentEncoding> {
                vec![]
            }
        }
        Box::new(NoOpDecoder)
    })
}

pub fn supported_encodings() -> Vec<ContentEncoding> {
    get_provider().supported_encodings()
}

pub async fn gzip_decode<R: AsyncBufRead + Unpin>(
    mut reader: R,
) -> Result<(Vec<u8>, Vec<u8>), HttpError> {
    let mut compressed = Vec::new();
    reader.read_to_end(&mut compressed).await?;

    let decompressed = get_provider().gzip_decode(compressed).await?;
    Ok((Vec::new(), decompressed))
}

pub async fn zlib_decode<R: AsyncBufRead + Unpin>(
    mut reader: R,
    size_hint: Option<usize>,
) -> Result<Vec<u8>, HttpError> {
    let mut compressed = Vec::new();
    reader.read_to_end(&mut compressed).await?;

    get_provider().zlib_decode(compressed, size_hint).await
}

pub async fn brotli_decode<R: AsyncBufRead + Unpin>(mut reader: R) -> Result<Vec<u8>, HttpError> {
    let mut compressed = Vec::new();
    reader.read_to_end(&mut compressed).await?;

    get_provider().brotli_decode(compressed).await
}

pub async fn zstd_decode<R: AsyncBufRead + Unpin>(mut reader: R) -> Result<Vec<u8>, HttpError> {
    let mut compressed = Vec::new();
    reader.read_to_end(&mut compressed).await?;

    get_provider().zstd_decode(compressed).await
}