1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! Stream decoders.

use futures_core::Stream;
use http::header::{HeaderMap, CONTENT_ENCODING};

use super::{
    coder::{Coder, FeaturedCode},
    coding::ContentEncoding,
    error::EncodingError,
};

/// Construct from headers and stream body. Use for decoding.
#[inline]
pub fn try_decoder<Req, S, T, E>(req: Req, body: S) -> Result<Coder<S, FeaturedCode>, EncodingError>
where
    Req: std::borrow::Borrow<http::Request<()>>,
    S: Stream<Item = Result<T, E>>,
    T: AsRef<[u8]> + 'static,
{
    from_headers(req.borrow().headers()).map(|decoder| Coder::new(body, decoder))
}

fn from_headers(headers: &HeaderMap) -> Result<FeaturedCode, EncodingError> {
    let Some(val) = headers.get(&CONTENT_ENCODING) else {
        return Ok(FeaturedCode::default());
    };
    let enc = val.to_str().map_err(|_| EncodingError::ParseAcceptEncoding)?;
    match ContentEncoding::try_parse(enc)? {
        ContentEncoding::Br => {
            #[cfg(feature = "br")]
            {
                Ok(FeaturedCode::DecodeBr(super::brotli::Decoder::new(
                    super::writer::BytesMutWriter::new(),
                )))
            }
            #[cfg(not(feature = "br"))]
            {
                Err(super::error::FeatureError::Br.into())
            }
        }
        ContentEncoding::Gzip => {
            #[cfg(feature = "gz")]
            {
                Ok(FeaturedCode::DecodeGz(super::gzip::Decoder::new(
                    super::writer::BytesMutWriter::new(),
                )))
            }
            #[cfg(not(feature = "gz"))]
            {
                Err(super::error::FeatureError::Gzip.into())
            }
        }
        ContentEncoding::Deflate => {
            #[cfg(feature = "de")]
            {
                Ok(FeaturedCode::DecodeDe(super::deflate::Decoder::new(
                    super::writer::BytesMutWriter::new(),
                )))
            }
            #[cfg(not(feature = "de"))]
            {
                Err(super::error::FeatureError::Deflate.into())
            }
        }
        ContentEncoding::NoOp => Ok(FeaturedCode::default()),
    }
}