cipherstash-client 0.42.0

The official CipherStash SDK
Documentation
use super::priv_state::{PlaintextEntry, TermBuilder};
use super::SteVecPendingEncryption;
use crate::encryption::{
    json_indexer::{
        path_values::{PathSegment, PathValue},
        prefix_mac::{PrefixMac, UpdatePrefixMac},
    },
    EncryptionError,
};

#[cfg_attr(test, derive(Debug))]
pub struct StePlaintextVec<'p>(Vec<PlaintextEntry<'p>>);

impl<'p> StePlaintextVec<'p> {
    pub fn new() -> Self {
        Self(Vec::new())
    }

    /// Build a SteVec from a StePlaintextVec with selector length `N`.
    ///
    /// Threads two MACs through the build pipeline:
    /// - `selector_macca` (Blake3) tokenizes the JSON path into the entry's
    ///   path selector AND the (path, value) pair into its value selector.
    ///   Always Blake3 regardless of mode.
    /// - `term_macca` (HMAC-SHA256) feeds the orderable-key derivation.
    ///   Always HMAC regardless of mode.
    ///
    /// The mode-dependent piece is the orderable primitive (ORE vs OPE) —
    /// selected by the `TB: TermBuilder` type parameter, not by the MAC
    /// flavour.
    ///
    /// ## Output layout
    ///
    /// Every JSON node contributes two entries: a **path entry** (ciphertext +
    /// optional orderable term) and a presence-only **value entry** (see
    /// [`super::priv_state::EntryWithTokenizedSelector`]). All path entries
    /// come first, in traversal order — the root `$` entry MUST stay at index
    /// 0, since decryption reads only the root ciphertext — with every value
    /// entry appended after them.
    pub fn index<const N: usize, TB, MSel, MTerm>(
        self,
        selector_macca: &mut MSel,
        term_macca: &mut MTerm,
    ) -> Result<SteVecPendingEncryption<N>, EncryptionError>
    where
        TB: TermBuilder,
        for<'u> MSel: PrefixMac
            + UpdatePrefixMac<PathSegment<'p>>
            + UpdatePrefixMac<[u8; N]>
            + UpdatePrefixMac<&'u str>
            + UpdatePrefixMac<String>,
        for<'u> MTerm: PrefixMac + UpdatePrefixMac<&'u str> + UpdatePrefixMac<[u8; N]>,
    {
        let node_count = self.0.len();
        let mut path_entries = Vec::with_capacity(node_count * 2);
        let mut value_entries = Vec::with_capacity(node_count);
        for entry in self.0 {
            let (path_entry, value_entry) = entry
                .build_selector::<N, MSel>(selector_macca)
                .build_terms::<TB, _>(term_macca)?;
            path_entries.push(path_entry);
            value_entries.push(value_entry);
        }
        path_entries.append(&mut value_entries);

        Ok(SteVecPendingEncryption(path_entries))
    }

    fn push(&mut self, PathValue(path, value): PathValue<'p>) {
        self.0.push(PlaintextEntry::new(path, value));
    }
}

impl<'p> FromIterator<PathValue<'p>> for StePlaintextVec<'p> {
    fn from_iter<I: IntoIterator<Item = PathValue<'p>>>(iter: I) -> Self {
        let mut ste_vec = StePlaintextVec::new();
        for entry in iter {
            ste_vec.push(entry);
        }
        ste_vec
    }
}