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
}