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