ffsend_api/pipe/
traits.rs

1//! Pipe traits.
2
3use std::io::{Read, Write};
4
5/// Something that can pipe given data.
6///
7/// A pipe may monitor, but also transform data flowing through it.
8///
9/// From this pipe, a reader or writer can be created using the corresponding `reader` and `writer`
10/// functions to wrap an existing reader or writer.
11pub trait Pipe: Sized {
12    /// The wrapping reader type used for this pipe.
13    type Reader: PipeRead<Self>;
14
15    /// The wrapping writer type used for this pipe.
16    type Writer: PipeWrite<Self>;
17
18    /// Wrap the `inner` reader, bytes that are read are transformed through this pipe.
19    fn reader(self, inner: Box<dyn Read>) -> Self::Reader {
20        Self::Reader::new(self, inner)
21    }
22
23    /// Wrap the `inner` writer, bytes that are read are transformed through this pipe.
24    fn writer(self, inner: Box<dyn Write>) -> Self::Writer {
25        Self::Writer::new(self, inner)
26    }
27
28    /// Pipe bytes from `input`, monitor/transform it, return the output.
29    ///
30    /// This should not be used directly, and is automatically used by a `PipeRead` or `PipeWrite`
31    /// object for the actual piping.
32    ///
33    /// This returns a tuple with the number of bytes read from the `input`, along with transformed
34    /// data if available in the following format: `(read_bytes, transformed_data)`.
35    ///
36    /// Pipes that just monitor data, immediately return the input.
37    /// The `pipe_transparent` helper function can be used for this inside the implementation.
38    fn pipe(&mut self, input: &[u8]) -> (usize, Option<Vec<u8>>);
39
40    /// Transparently pipe `input` by immediately returning it.
41    ///
42    /// This should not be used directly, and is automatically used by a `PipeRead` or `PipeWrite`
43    /// object for the actual piping.
44    ///
45    /// This can be used as helper function inside the `pipe` function if data is only monitored
46    /// and not transformed.
47    #[inline(always)]
48    fn pipe_transparent(&self, input: &[u8]) -> (usize, Option<Vec<u8>>) {
49        (input.len(), Some(input.to_vec()))
50    }
51}
52
53/// A reader wrapping another reader, to encrypt or decrypt data read from it.
54pub trait PipeRead<P>: Read
55where
56    P: Pipe,
57{
58    /// Wrap the given `inner` reader, transform data using `crypt`.
59    fn new(pipe: P, inner: Box<dyn Read>) -> Self;
60}
61
62/// A writer wrapping another writher, to encrypt or decrypt data it is writen to.
63pub trait PipeWrite<P>: Write
64where
65    P: Pipe,
66{
67    /// Wrap the given `inner` writer, transform data using `crypt`.
68    fn new(pipe: P, inner: Box<dyn Write>) -> Self;
69}
70
71/// Defines number of bytes transformed into/out of pipe if fixed.
72///
73/// For example, the AES-GCM cryptography pipe adds 16 bytes to the encrypted payload for the
74/// verification tag. When transforming a file the length is known.
75/// Then, the `len_out` for an AES-GCM encrypter is 16 bytes larger than `len_in`.
76/// For a decrypter this is the other way around.
77pub trait PipeLen {
78    /// The number of bytes that are transfered into the pipe if fixed.
79    fn len_in(&self) -> usize;
80
81    /// The number of bytes that are transfered out of the pipe if fixed.
82    fn len_out(&self) -> usize;
83}
84
85pub trait ReadLen: Read + PipeLen + Send {}
86pub trait WriteLen: Write + PipeLen + Send {}
87
88// TODO: use automatic implementation for crypt reader and writer wrapping crypt having pipelen
89// impl<R, C> PipeLen for R
90//     where R: CryptRead<C>,
91//           C: Crypt + PipeLen,
92// {
93//     fn len_in(&self) -> usize {
94//         self.crypt.len_in()
95//     }
96//
97//     fn len_out(&self) -> usize {
98//         self.crypt.len_out()
99//     }
100// }