http_encoding/
decode.rs

1//! Stream decoders.
2
3use 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/// Construct from headers and stream body. Use for decoding.
13#[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}