kutil_transcoding/
reader.rs1use super::encoding::*;
2
3use {
4 ::tokio::io::*,
5 async_compression::{tokio::bufread::*, *},
6 pin_project::*,
7 std::{io, pin::*, task::*},
8};
9
10#[pin_project(project = Projected)]
16pub enum TranscodingReader<ReadT>
17where
18 ReadT: AsyncRead,
19{
20 Passthrough(#[pin] ReadT),
22
23 EncodeBrotli(#[pin] BrotliEncoder<BufReader<ReadT>>),
25
26 DecodeBrotli(#[pin] BrotliDecoder<BufReader<ReadT>>),
28
29 EncodeDeflate(#[pin] DeflateEncoder<BufReader<ReadT>>),
31
32 DecodeDeflate(#[pin] DeflateDecoder<BufReader<ReadT>>),
34
35 EncodeGZip(#[pin] GzipEncoder<BufReader<ReadT>>),
37
38 DecodeGZip(#[pin] GzipDecoder<BufReader<ReadT>>),
40
41 EncodeZstandard(#[pin] ZstdEncoder<BufReader<ReadT>>),
43
44 DecodeZstandard(#[pin] ZstdDecoder<BufReader<ReadT>>),
46}
47
48impl<ReadT> AsyncRead for TranscodingReader<ReadT>
49where
50 ReadT: AsyncRead,
51{
52 fn poll_read(self: Pin<&mut Self>, context: &mut Context<'_>, buffer: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
53 match self.project() {
54 Projected::Passthrough(reader) => reader.poll_read(context, buffer),
55 Projected::EncodeBrotli(reader) => reader.poll_read(context, buffer),
56 Projected::DecodeBrotli(reader) => reader.poll_read(context, buffer),
57 Projected::EncodeGZip(reader) => reader.poll_read(context, buffer),
58 Projected::DecodeGZip(reader) => reader.poll_read(context, buffer),
59 Projected::EncodeDeflate(reader) => reader.poll_read(context, buffer),
60 Projected::DecodeDeflate(reader) => reader.poll_read(context, buffer),
61 Projected::EncodeZstandard(reader) => reader.poll_read(context, buffer),
62 Projected::DecodeZstandard(reader) => reader.poll_read(context, buffer),
63 }
64 }
65}
66
67pub trait IntoTranscodingReader<ReadT>
73where
74 ReadT: AsyncRead,
75{
76 fn into_passthrough_reader(self) -> TranscodingReader<ReadT>;
78
79 fn into_encoding_reader(self, encoding: &Encoding, level: Level) -> TranscodingReader<ReadT>;
81
82 fn into_decoding_reader(self, encoding: &Encoding) -> TranscodingReader<ReadT>;
84}
85
86impl<ReadT> TranscodingReader<ReadT>
87where
88 ReadT: AsyncRead,
89{
90 pub fn inner(&self) -> &ReadT {
92 match self {
93 Self::Passthrough(reader) => reader,
94 Self::EncodeBrotli(reader) => reader.get_ref().get_ref(),
95 Self::DecodeBrotli(reader) => reader.get_ref().get_ref(),
96 Self::EncodeDeflate(reader) => reader.get_ref().get_ref(),
97 Self::DecodeDeflate(reader) => reader.get_ref().get_ref(),
98 Self::EncodeGZip(reader) => reader.get_ref().get_ref(),
99 Self::DecodeGZip(reader) => reader.get_ref().get_ref(),
100 Self::EncodeZstandard(reader) => reader.get_ref().get_ref(),
101 Self::DecodeZstandard(reader) => reader.get_ref().get_ref(),
102 }
103 }
104}
105
106impl<ReadT> IntoTranscodingReader<ReadT> for ReadT
107where
108 ReadT: AsyncRead,
109{
110 fn into_passthrough_reader(self) -> TranscodingReader<ReadT> {
111 TranscodingReader::Passthrough(self)
112 }
113
114 fn into_encoding_reader(self, encoding: &Encoding, level: Level) -> TranscodingReader<ReadT> {
115 if *encoding == Encoding::Identity {
116 tracing::debug!("not encoding");
117 } else {
118 tracing::debug!("encoding to {}", encoding);
119 }
120
121 match encoding {
122 Encoding::Identity => self.into_passthrough_reader(),
123
124 Encoding::Brotli => {
125 TranscodingReader::EncodeBrotli(BrotliEncoder::with_quality(BufReader::new(self), level))
126 }
127
128 Encoding::Deflate => {
129 TranscodingReader::EncodeDeflate(DeflateEncoder::with_quality(BufReader::new(self), level))
130 }
131 Encoding::GZip => TranscodingReader::EncodeGZip(GzipEncoder::with_quality(BufReader::new(self), level)),
132
133 Encoding::Zstandard => {
134 TranscodingReader::EncodeZstandard(ZstdEncoder::with_quality(BufReader::new(self), level))
135 }
136 }
137 }
138
139 fn into_decoding_reader(self, encoding: &Encoding) -> TranscodingReader<ReadT> {
140 if *encoding == Encoding::Identity {
141 tracing::debug!("not decoding");
142 } else {
143 tracing::debug!("decoding from {}", encoding);
144 }
145
146 match encoding {
147 Encoding::Identity => self.into_passthrough_reader(),
148 Encoding::Brotli => TranscodingReader::DecodeBrotli(BrotliDecoder::new(BufReader::new(self))),
149 Encoding::Deflate => TranscodingReader::DecodeDeflate(DeflateDecoder::new(BufReader::new(self))),
150 Encoding::GZip => TranscodingReader::DecodeGZip(GzipDecoder::new(BufReader::new(self))),
151 Encoding::Zstandard => TranscodingReader::DecodeZstandard(ZstdDecoder::new(BufReader::new(self))),
152 }
153 }
154}