Skip to main content

http_encoding/
decode.rs

1//! Stream decoders.
2
3use http::header::{CONTENT_ENCODING, HeaderMap};
4use http_body_alt::Body;
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>(headers: &HeaderMap, body: S) -> Result<Coder<S, FeaturedCode>, EncodingError>
15where
16    S: Body,
17    S::Data: 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 mut err = None;
24
25    for enc in headers
26        .get_all(&CONTENT_ENCODING)
27        .iter()
28        .filter_map(|v| v.to_str().ok())
29        .flat_map(|s| s.split(','))
30        .map(str::trim)
31        .filter(|s| !s.is_empty())
32    {
33        match ContentEncoding::try_parse(enc) {
34            Ok(encoding) => match encoding {
35                ContentEncoding::Identity => break,
36                ContentEncoding::Br => {
37                    #[cfg(feature = "br")]
38                    return Ok(FeaturedCode::DecodeBr(super::brotli::Decoder::new()));
39                }
40                ContentEncoding::Gzip => {
41                    #[cfg(feature = "gz")]
42                    return Ok(FeaturedCode::DecodeGz(super::gzip::Decoder::new(
43                        super::writer::BytesMutWriter::new(),
44                    )));
45                }
46                ContentEncoding::Deflate => {
47                    #[cfg(feature = "de")]
48                    return Ok(FeaturedCode::DecodeDe(super::deflate::Decoder::new(
49                        super::writer::BytesMutWriter::new(),
50                    )));
51                }
52                ContentEncoding::Zstd => {
53                    #[cfg(feature = "zs")]
54                    return Ok(FeaturedCode::DecodeZs(super::zstandard::Decoder::new()));
55                }
56            },
57            Err(e) => err = Some(e),
58        };
59    }
60
61    if let Some(e) = err {
62        Err(e.into())
63    } else {
64        Ok(FeaturedCode::default())
65    }
66}