Skip to main content

rw_builder/
lib.rs

1//! rw-builder provides a convenient way to build `std::io::Read`ers and
2//! `std::io::Write`rs by chaining transformations. Since readers and writers
3//! are defined simultaneously through the same builder they can be used as
4//! inverses of each other.
5#![deny(
6    future_incompatible,
7    nonstandard_style,
8    rust_2018_compatibility,
9    rust_2018_idioms,
10    unused,
11    warnings
12)]
13#![deny(
14    absolute_paths_not_starting_with_crate,
15    deprecated_in_future,
16    elided_lifetimes_in_paths,
17    explicit_outlives_requirements,
18    keyword_idents,
19    macro_use_extern_crate,
20    meta_variable_misuse,
21    missing_abi,
22    missing_copy_implementations,
23    missing_debug_implementations,
24    missing_docs,
25    non_ascii_idents,
26    noop_method_call,
27    rust_2021_incompatible_or_patterns,
28    semicolon_in_expressions_from_macros,
29    single_use_lifetimes,
30    trivial_casts,
31    trivial_numeric_casts,
32    unreachable_pub,
33    unsafe_code,
34    unsafe_op_in_unsafe_fn,
35    unstable_features,
36    unused_crate_dependencies,
37    unused_extern_crates,
38    unused_import_braces,
39    unused_lifetimes,
40    unused_qualifications,
41    unused_results,
42    variant_size_differences
43)]
44#![deny(
45    clippy::all,
46    clippy::cargo,
47    clippy::nursery,
48    clippy::pedantic,
49    clippy::missing_safety_doc,
50    clippy::missing_docs_in_private_items
51)]
52#![deny(
53    rustdoc::bare_urls,
54    rustdoc::broken_intra_doc_links,
55    rustdoc::invalid_codeblock_attributes,
56    rustdoc::invalid_html_tags,
57    rustdoc::missing_crate_level_docs,
58    rustdoc::private_doc_tests,
59    rustdoc::private_intra_doc_links
60)]
61
62/// Provides the error types used by the library.
63pub mod error;
64pub use error::{Error, Result};
65
66/// Provides the `WincodeBuilder` type which acts as a sink to (de)serialize a
67/// `&[u8]` as wincode.
68#[cfg(feature = "wincode")]
69mod wincode;
70#[cfg(feature = "wincode")]
71pub use crate::wincode::Builder as WincodeBuilder;
72
73/// Provides the `BufferedBuilder` type which helps build `BufReader` and
74/// `BufWriter` instances.
75mod buffered;
76pub use buffered::Builder as BufferedBuilder;
77
78/// Provides the `FileBuilder` type which acts as a source to read from and
79/// write to a file.
80mod file;
81pub use file::Builder as FileBuilder;
82
83/// Provides several wrapper types around the streaming compression algorithms
84/// provided by the flate2 crate.
85#[cfg(feature = "flate2")]
86mod flate2;
87#[cfg(feature = "flate2")]
88pub use ::flate2::Compression;
89
90#[cfg(feature = "flate2")]
91pub use crate::flate2::{CompressionBuilder, Constructor, CrcBuilder};
92
93/// Provides the `ProcessBuilder` type which acts as a source to read from
94/// stdout and write to stdin of a running process.
95mod process;
96pub use process::Builder as ProcessBuilder;
97
98/// Provides several wrapper types around the streaming cipher algorithms
99/// provided by the flate2 crate.
100#[cfg(any(feature = "chacha20", feature = "salsa20", feature = "aes_ctr"))]
101mod stream_cipher;
102#[cfg(feature = "aes_ctr")]
103pub use stream_cipher::{
104    Aes128Ctr, Aes128CtrBuilder, Aes128Key, Aes256Ctr, Aes256CtrBuilder, Aes256Key, AesNonce,
105};
106#[cfg(feature = "chacha20")]
107pub use stream_cipher::{ChaCha20Builder, ChaCha20Key, ChaCha20Nonce};
108#[cfg(feature = "salsa20")]
109pub use stream_cipher::{Salsa20Builder, Salsa20Key, Salsa20Nonce};
110
111/// Provides the `StringBuilder` type which is a sink without serde
112mod string;
113pub use string::AdhocWriter;
114
115/// Provides the `TcpStreamBuilder` type which acts as a source to read from and
116/// write to a TCP stream.
117mod tcp_stream;
118pub use tcp_stream::Builder as TcpStreamBuilder;
119
120/// Provides the `VecBuilder` type which acts as a source to read from and write
121/// to a memory buffer.
122mod vec;
123pub use vec::Builder as VecBuilder;
124
125/// Provides the `ZstdBuilder` wrapper around the `zstd` algorithm.
126#[cfg(feature = "zstd")]
127mod zstd;
128#[cfg(feature = "zstd")]
129pub use crate::zstd::ZstdBuilder;
130
131/// Provides the `BzBuilder` wrapper around the `bzip2` algorithm.
132#[cfg(feature = "bzip2")]
133mod bzip2;
134#[cfg(feature = "bzip2")]
135pub use crate::bzip2::{BzBuilder, Compression as BzCompression};
136
137/// Provides the `Lz4Builder` wrapper around the `lz4_flex` algorithm.
138#[cfg(feature = "lz4_flex")]
139mod lz4_flex;
140#[cfg(feature = "lz4_flex")]
141pub use crate::lz4_flex::Lz4Builder;
142
143/// Provides the `DigestBuilder` wrapper around the `digest` trait.
144#[cfg(feature = "digest")]
145mod digest;
146#[cfg(feature = "digest")]
147pub use crate::digest::{DigestBuilder, DigestReader, DigestWriter};
148#[cfg(feature = "sha2")]
149pub use crate::digest::{Sha256Builder, Sha512Builder};
150#[cfg(feature = "sha3")]
151pub use crate::digest::{Sha3_256Builder, Sha3_512Builder};
152
153/// Provides the `Crc32FastBuilder` wrapper around the `crc32fast` algorithm.
154#[cfg(feature = "crc32fast")]
155mod crc32fast;
156#[cfg(feature = "crc32fast")]
157pub use crate::crc32fast::{Crc32FastBuilder, Crc32FastReader, Crc32FastWriter};
158
159/// Provides the `Builder` for `rmp-serde` (`MessagePack` serialization/deserialization).
160#[cfg(feature = "rmp_serde")]
161pub mod rmp_serde;
162
163/// The trait that can construct readers and writers, but also has chainable
164/// functions to create more complex builders
165pub trait RwBuilder
166where
167    Self: Sized,
168    Self::Reader: std::io::Read,
169    Self::Writer: std::io::Write,
170{
171    /// The reader type that will be constructed by the reader function
172    type Reader;
173
174    /// Construct a reader from this builder
175    /// # Errors
176    /// In case the construction of any of the intermediate readers fails this
177    /// will return the error associated to the first one that failed.
178    fn reader(&self) -> Result<Self::Reader>;
179
180    /// The writer type that will be constructed by the reader function
181    type Writer;
182
183    /// Construct a writer from this builder
184    /// # Errors
185    /// In case the construction of any of the intermediate writers fails this
186    /// will return the error associated to the first one that failed.
187    fn writer(&self) -> Result<Self::Writer>;
188}
189
190/// Extension trait providing combinator methods for `RwBuilder` instances
191pub trait RwBuilderExt: RwBuilder {
192    /// Buffers the underlying readers and writers by wrapping them in a
193    /// `BufReader` or `BufWriter`
194    fn buffered(self) -> BufferedBuilder<Self> {
195        BufferedBuilder::new(self)
196    }
197
198    /// Sink that provides a bridge between `String` instances and underlying
199    /// readers and writers.
200    fn string(self) -> string::Builder<Self> {
201        string::Builder::new(self)
202    }
203
204    /// Sink that provides a bridge between serde and the underlying readers and
205    /// writer by transforming from and to wincode.
206    #[cfg(feature = "wincode")]
207    fn wincode(self) -> WincodeBuilder<Self> {
208        WincodeBuilder::new(self)
209    }
210
211    /// Transformation that decrypts while reading and encrypts while writing
212    /// using the chacha20 cipher
213    #[cfg(feature = "chacha20")]
214    fn chacha20(self, key: ChaCha20Key, nonce: ChaCha20Nonce) -> ChaCha20Builder<Self> {
215        ChaCha20Builder::<Self>::new(self, key, nonce)
216    }
217
218    /// Transformation that decrypts while reading and encrypts while writing
219    /// using the salsa20 cipher
220    #[cfg(feature = "salsa20")]
221    fn salsa20(self, key: Salsa20Key, nonce: Salsa20Nonce) -> Salsa20Builder<Self> {
222        Salsa20Builder::<Self>::new(self, key, nonce)
223    }
224
225    /// Non-commutative transformation that hashes using the CRC algorithm
226    #[cfg(feature = "flate2")]
227    fn crc(self) -> CrcBuilder<Self> {
228        CrcBuilder::new(self)
229    }
230
231    /// Transformation that decompresses while reading and compresses while
232    /// writing using the Deflate algorithm
233    #[cfg(feature = "flate2")]
234    fn deflate(self, compression: Compression) -> CompressionBuilder<Self, flate2::Deflate> {
235        flate2::Deflate::new(self, compression)
236    }
237
238    /// Transformation that decompresses while reading and compresses while
239    /// writing using the Gz algorithm
240    #[cfg(feature = "flate2")]
241    fn gz(self, compression: Compression) -> CompressionBuilder<Self, flate2::Gz> {
242        flate2::Gz::new(self, compression)
243    }
244
245    /// Transformation that decompresses while reading and compresses while
246    /// writing using the Zlib algorithm
247    #[cfg(feature = "flate2")]
248    fn zlib(self, compression: Compression) -> CompressionBuilder<Self, flate2::Zlib> {
249        flate2::Zlib::new(self, compression)
250    }
251
252    /// Transformation that decompresses while reading and compresses while
253    /// writing using the Zstd algorithm
254    #[cfg(feature = "zstd")]
255    fn zstd(self, level: i32) -> ZstdBuilder<Self> {
256        ZstdBuilder::new(self, level)
257    }
258
259    /// Transformation that decompresses while reading and compresses while
260    /// writing using the bzip2 algorithm
261    #[cfg(feature = "bzip2")]
262    fn bzip2(self, compression: BzCompression) -> BzBuilder<Self> {
263        BzBuilder::new(self, compression)
264    }
265
266    /// Transformation that decompresses while reading and compresses while
267    /// writing using the `lz4_flex` algorithm
268    #[cfg(feature = "lz4_flex")]
269    fn lz4_flex(self) -> Lz4Builder<Self> {
270        Lz4Builder::new(self)
271    }
272
273    /// Computes a hash or checksum using the `digest` crate's `Digest` trait while reading and writing.
274    #[cfg(feature = "digest")]
275    fn hash<D: ::digest::Digest>(self) -> DigestBuilder<Self, D> {
276        DigestBuilder::new(self)
277    }
278
279    /// Computes a SHA256 hash while reading and writing.
280    #[cfg(feature = "sha2")]
281    fn sha256(self) -> Sha256Builder<Self> {
282        DigestBuilder::new(self)
283    }
284
285    /// Computes a SHA512 hash while reading and writing.
286    #[cfg(feature = "sha2")]
287    fn sha512(self) -> Sha512Builder<Self> {
288        DigestBuilder::new(self)
289    }
290
291    /// Computes a SHA3-256 hash while reading and writing.
292    #[cfg(feature = "sha3")]
293    fn sha3_256(self) -> Sha3_256Builder<Self> {
294        DigestBuilder::new(self)
295    }
296
297    /// Computes a SHA3-512 hash while reading and writing.
298    #[cfg(feature = "sha3")]
299    fn sha3_512(self) -> Sha3_512Builder<Self> {
300        DigestBuilder::new(self)
301    }
302
303    /// Computes a CRC32 checksum using the `crc32fast` crate while reading and writing.
304    #[cfg(feature = "crc32fast")]
305    fn crc32fast(self) -> Crc32FastBuilder<Self> {
306        Crc32FastBuilder::new(self)
307    }
308
309    /// Sink that loads and saves values using `rmp-serde` (`MessagePack`).
310    #[cfg(feature = "rmp_serde")]
311    fn rmp_serde(self) -> rmp_serde::Builder<Self> {
312        rmp_serde::Builder::new(self)
313    }
314
315    /// Transformation that decrypts while reading and encrypts while writing
316    /// using the AES-128-CTR algorithm
317    #[cfg(feature = "aes_ctr")]
318    fn aes128_ctr(self, key: Aes128Key, nonce: AesNonce) -> Aes128CtrBuilder<Self> {
319        Aes128CtrBuilder::new(self, key, nonce)
320    }
321
322    /// Transformation that decrypts while reading and encrypts while writing
323    /// using the AES-256-CTR algorithm
324    #[cfg(feature = "aes_ctr")]
325    fn aes256_ctr(self, key: Aes256Key, nonce: AesNonce) -> Aes256CtrBuilder<Self> {
326        Aes256CtrBuilder::new(self, key, nonce)
327    }
328}
329
330impl<T: RwBuilder> RwBuilderExt for T {}
331
332/// Trait to wrap serialization and deserialization functionality behind uniform
333/// load and save functions
334#[cfg(feature = "wincode")]
335pub trait SerDe {
336    /// Deserialize into a specified type
337    /// # Errors
338    /// In case the deserialization or the reading fails the return value will
339    /// contain the first error that occurred.
340    fn load<T>(&self) -> Result<T>
341    where
342        T: for<'de> serde::de::Deserialize<'de>;
343
344    /// Serialize into the type of the last sink specified
345    /// # Errors
346    /// In case the serialization or the writing fails the return value will
347    /// contain the first error that occurred.
348    fn save<T>(&self, value: &T) -> Result<()>
349    where
350        T: serde::ser::Serialize;
351}
352
353#[cfg(test)]
354mod tests;