1use 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#[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}