vitaminc_aead/ciphertext/
write_monads.rs

1use super::LocalCipherText;
2use crate::Nonce;
3use bytes::BytesMut;
4use vitaminc_protected::{Controlled, Protected};
5
6#[derive(Default)]
7pub struct CipherTextBuilder();
8
9impl CipherTextBuilder {
10    pub fn new() -> Self {
11        Default::default()
12    }
13
14    pub fn append_nonce<const N: usize>(self, nonce: Nonce<N>) -> NonceWritten<N> {
15        NonceWritten(nonce)
16    }
17}
18
19pub struct NonceWritten<const N: usize>(Nonce<N>);
20
21impl<const N: usize> NonceWritten<N> {
22    pub fn append_target_plaintext(
23        self,
24        plaintext: impl Into<Protected<Vec<u8>>>,
25    ) -> PlaintextWritten<N> {
26        PlaintextWritten::new(self.0, plaintext.into())
27    }
28}
29
30pub struct PlaintextWritten<const N: usize>(Nonce<N>, Protected<Vec<u8>>);
31
32impl<const N: usize> PlaintextWritten<N> {
33    fn new(nonce: Nonce<N>, plaintext: Protected<Vec<u8>>) -> Self {
34        Self(nonce, plaintext)
35    }
36
37    /// Provides a closure that takes the plaintext and to which the ciphertext and tag must be written.
38    pub fn accepts_ciphertext_and_tag_ok<E>(
39        self,
40        f: impl FnOnce(Vec<u8>) -> Result<Vec<u8>, E>,
41    ) -> EncryptedWithTag<N, E> {
42        EncryptedWithTag::new(self.0, self.1.map_ok(f))
43    }
44}
45
46pub struct EncryptedWithTag<const N: usize, E> {
47    nonce: Nonce<N>,
48    bytes: Result<Protected<Vec<u8>>, E>,
49}
50
51impl<const N: usize, E> EncryptedWithTag<N, E> {
52    fn new(nonce: Nonce<N>, bytes: Result<Protected<Vec<u8>>, E>) -> Self {
53        Self { bytes, nonce }
54    }
55
56    pub fn build(self) -> Result<LocalCipherText, E> {
57        // The value has been encrypted, so we can unwrap it
58        let inner = self.bytes?.risky_unwrap();
59        let mut bytes = BytesMut::with_capacity(N + inner.len());
60        bytes.extend(self.nonce.into_inner());
61        bytes.extend(inner);
62        Ok(LocalCipherText(bytes.freeze()))
63    }
64}