1use futures_core::Stream;
4use http::header::{HeaderMap, CONTENT_ENCODING};
5
6use super::{
7 coder::{Coder, FeaturedCode},
8 coding::ContentEncoding,
9 error::EncodingError,
10};
11
12#[inline]
14pub fn try_decoder<S, T, E>(headers: &HeaderMap, body: S) -> Result<Coder<S, FeaturedCode>, EncodingError>
15where
16 S: Stream<Item = Result<T, E>>,
17 T: AsRef<[u8]> + 'static,
18{
19 from_headers(headers).map(|decoder| Coder::new(body, decoder))
20}
21
22fn from_headers(headers: &HeaderMap) -> Result<FeaturedCode, EncodingError> {
23 let Some(val) = headers.get(&CONTENT_ENCODING) else {
24 return Ok(FeaturedCode::default());
25 };
26 let enc = val.to_str().map_err(|_| EncodingError::ParseAcceptEncoding)?;
27 match ContentEncoding::try_parse(enc)? {
28 ContentEncoding::Br => {
29 #[cfg(feature = "br")]
30 {
31 Ok(FeaturedCode::DecodeBr(super::brotli::Decoder::new(
32 super::writer::BytesMutWriter::new(),
33 )))
34 }
35 #[cfg(not(feature = "br"))]
36 {
37 Err(super::error::FeatureError::Br.into())
38 }
39 }
40 ContentEncoding::Gzip => {
41 #[cfg(feature = "gz")]
42 {
43 Ok(FeaturedCode::DecodeGz(super::gzip::Decoder::new(
44 super::writer::BytesMutWriter::new(),
45 )))
46 }
47 #[cfg(not(feature = "gz"))]
48 {
49 Err(super::error::FeatureError::Gzip.into())
50 }
51 }
52 ContentEncoding::Deflate => {
53 #[cfg(feature = "de")]
54 {
55 Ok(FeaturedCode::DecodeDe(super::deflate::Decoder::new(
56 super::writer::BytesMutWriter::new(),
57 )))
58 }
59 #[cfg(not(feature = "de"))]
60 {
61 Err(super::error::FeatureError::Deflate.into())
62 }
63 }
64 ContentEncoding::NoOp => Ok(FeaturedCode::default()),
65 }
66}