rw_builder/
flate2.rs

1use anyhow::Result;
2use flate2::{Compression, CrcReader, CrcWriter};
3
4use crate::RwBuilder;
5
6/// Type returned by the `deflate`, `gz` and `zlib` functions on the `RwBuilder`
7/// trait. It is itself an `RwBuilder` so can be chained further.
8#[derive(Debug)]
9pub struct CompressionBuilder<B, C>
10where
11    B: RwBuilder,
12    C: CoderBuilder<B::Reader, B::Writer>,
13{
14    /// The inner builder it wraps
15    builder: B,
16    /// The compression used for the encoder
17    compression: Compression,
18    /// The builder for the encoder and decoder
19    coder: C,
20}
21
22impl<B, C> RwBuilder for CompressionBuilder<B, C>
23where
24    B: RwBuilder,
25    B::Reader: std::io::Read,
26    B::Writer: std::io::Write,
27    C: CoderBuilder<B::Reader, B::Writer>,
28    C::Decoder: std::io::Read,
29    C::Encoder: std::io::Write,
30{
31    type Reader = C::Decoder;
32    type Writer = C::Encoder;
33
34    fn reader(&self) -> Result<Self::Reader> {
35        let reader = self.builder.reader()?;
36        Ok(self.coder.decoder(reader))
37    }
38
39    fn writer(&self) -> Result<Self::Writer> {
40        let writer = self.builder.writer()?;
41        Ok(self.coder.encoder(writer, self.compression))
42    }
43}
44
45/// Implementors like `Deflate`, `Gz` and `Zlib` create the associated encoders
46/// and decoders.
47pub trait CoderBuilder<R, W> {
48    /// The type of encoder created
49    type Encoder;
50
51    /// Create an encoder on top of a writer
52    fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder;
53
54    /// The type of decoder created
55    type Decoder;
56
57    /// Create a decoder on top of a reader
58    fn decoder(&self, reader: R) -> Self::Decoder;
59}
60
61/// The Zlib encoder and decoder builder
62#[derive(Default, Debug, Copy, Clone)]
63pub struct Zlib;
64
65impl<R, W> CoderBuilder<R, W> for Zlib
66where
67    R: std::io::Read,
68    W: std::io::Write,
69{
70    type Decoder = flate2::read::ZlibDecoder<R>;
71    type Encoder = flate2::write::ZlibEncoder<W>;
72
73    fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
74        flate2::write::ZlibEncoder::new(writer, compression)
75    }
76
77    fn decoder(&self, reader: R) -> Self::Decoder {
78        flate2::read::ZlibDecoder::new(reader)
79    }
80}
81
82/// Convenience trait for creating a new encoder/decoder builder
83pub trait Constructor<B>
84where
85    Self: Sized + CoderBuilder<B::Reader, B::Writer> + Default,
86    B: RwBuilder,
87{
88    /// Create the encoder/decoder builder
89    fn new(builder: B, compression: Compression) -> CompressionBuilder<B, Self> {
90        CompressionBuilder { builder, compression, coder: Self::default() }
91    }
92}
93
94impl<B> Constructor<B> for Zlib where B: RwBuilder {}
95
96/// The Gz encoder and decoder builder
97#[derive(Default, Debug, Copy, Clone)]
98pub struct Gz;
99
100impl<R, W> CoderBuilder<R, W> for Gz
101where
102    R: std::io::Read,
103    W: std::io::Write,
104{
105    type Decoder = flate2::read::GzDecoder<R>;
106    type Encoder = flate2::write::GzEncoder<W>;
107
108    fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
109        flate2::write::GzEncoder::new(writer, compression)
110    }
111
112    fn decoder(&self, reader: R) -> Self::Decoder {
113        flate2::read::GzDecoder::new(reader)
114    }
115}
116
117impl<B> Constructor<B> for Gz where B: RwBuilder {}
118
119/// The Deflate encoder and decoder builder
120#[derive(Default, Debug, Copy, Clone)]
121pub struct Deflate;
122
123impl<R, W> CoderBuilder<R, W> for Deflate
124where
125    R: std::io::Read,
126    W: std::io::Write,
127{
128    type Decoder = flate2::read::DeflateDecoder<R>;
129    type Encoder = flate2::write::DeflateEncoder<W>;
130
131    fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
132        flate2::write::DeflateEncoder::new(writer, compression)
133    }
134
135    fn decoder(&self, reader: R) -> Self::Decoder {
136        flate2::read::DeflateDecoder::new(reader)
137    }
138}
139
140impl<B> Constructor<B> for Deflate where B: RwBuilder {}
141
142/// Type returned by the `crc` function on the `RwBuilder` trait.
143/// It is itself an `RwBuilder` so can be chained further, although this is an
144/// uncommon scenario
145#[derive(Debug)]
146pub struct CrcBuilder<B>
147where
148    B: RwBuilder,
149{
150    /// The inner builder it wraps
151    builder: B,
152}
153
154impl<B> CrcBuilder<B>
155where
156    B: RwBuilder,
157{
158    /// Factory function to wrap an inner builder
159    #[must_use]
160    pub const fn new(builder: B) -> Self {
161        Self { builder }
162    }
163}
164
165impl<B> RwBuilder for CrcBuilder<B>
166where
167    B: RwBuilder,
168    B::Reader: std::io::Read,
169    B::Writer: std::io::Write,
170{
171    type Reader = CrcReader<B::Reader>;
172    type Writer = CrcWriter<B::Writer>;
173
174    fn reader(&self) -> Result<Self::Reader> {
175        Ok(CrcReader::new(self.builder.reader()?))
176    }
177
178    fn writer(&self) -> Result<Self::Writer> {
179        Ok(CrcWriter::new(self.builder.writer()?))
180    }
181}