http_encoding/
lib.rs

1//! Content-Encoding support on top of `http` crate
2
3#![forbid(unsafe_code)]
4
5pub mod error;
6
7#[macro_use]
8mod coder;
9mod coding;
10mod decode;
11mod encode;
12
13#[cfg(any(feature = "br", feature = "gz", feature = "de"))]
14mod writer;
15
16#[cfg(feature = "br")]
17mod brotli {
18    use std::io::{self, Write};
19
20    use brotli2::write::{BrotliDecoder, BrotliEncoder};
21    use bytes::Bytes;
22
23    use super::{coder::Code, writer::BytesMutWriter};
24
25    pub type Decoder = BrotliDecoder<BytesMutWriter>;
26    pub struct Encoder(Option<BrotliEncoder<BytesMutWriter>>);
27
28    impl Encoder {
29        pub(crate) fn new(level: u32) -> Self {
30            Self(Some(BrotliEncoder::new(BytesMutWriter::new(), level)))
31        }
32    }
33
34    impl<T> Code<T> for BrotliDecoder<BytesMutWriter>
35    where
36        T: AsRef<[u8]>,
37    {
38        type Item = Bytes;
39
40        fn code(&mut self, item: T) -> io::Result<Option<Self::Item>> {
41            self.write_all(item.as_ref())?;
42            self.flush()?;
43            let b = self.get_mut().take();
44            if !b.is_empty() {
45                Ok(Some(b))
46            } else {
47                Ok(None)
48            }
49        }
50
51        fn code_eof(&mut self) -> io::Result<Option<Self::Item>> {
52            let b = self.finish()?.take_owned();
53            if !b.is_empty() {
54                Ok(Some(b))
55            } else {
56                Ok(None)
57            }
58        }
59    }
60
61    impl<T> Code<T> for Encoder
62    where
63        T: AsRef<[u8]>,
64    {
65        type Item = Bytes;
66
67        fn code(&mut self, item: T) -> io::Result<Option<Self::Item>> {
68            let encoder = self.0.as_mut().unwrap();
69            encoder.write_all(item.as_ref())?;
70            encoder.flush()?;
71            let b = encoder.get_mut().take();
72            if !b.is_empty() {
73                Ok(Some(b))
74            } else {
75                Ok(None)
76            }
77        }
78
79        fn code_eof(&mut self) -> io::Result<Option<Self::Item>> {
80            match self.0.take() {
81                Some(encoder) => {
82                    let b = encoder.finish()?.take_owned();
83                    assert!(!b.is_empty());
84                    Ok(Some(b))
85                }
86                None => Ok(None),
87            }
88        }
89    }
90}
91
92#[cfg(feature = "gz")]
93mod gzip {
94    use super::writer::BytesMutWriter;
95
96    use flate2::write::{GzDecoder, GzEncoder};
97
98    pub type Decoder = GzDecoder<BytesMutWriter>;
99    pub type Encoder = GzEncoder<BytesMutWriter>;
100
101    code_impl!(GzDecoder);
102    code_impl!(GzEncoder);
103}
104#[cfg(feature = "de")]
105mod deflate {
106    use super::writer::BytesMutWriter;
107
108    use flate2::write::{DeflateDecoder, DeflateEncoder};
109
110    pub type Decoder = DeflateDecoder<BytesMutWriter>;
111    pub type Encoder = DeflateEncoder<BytesMutWriter>;
112
113    code_impl!(DeflateDecoder);
114    code_impl!(DeflateEncoder);
115}
116
117pub use self::coder::{Code, Coder, FeaturedCode};
118pub use self::coding::ContentEncoding;
119pub use self::decode::try_decoder;
120pub use self::encode::encoder;