use crate::zerokms::IndexKey;
use zeroize::{Zeroize, ZeroizeOnDrop};
use super::{path_values::PathSegment, ste_vec::TokenizedSelector};
pub(crate) trait PrefixMac {
fn finalize_reset<const N: usize>(&mut self) -> [u8; N];
}
pub(crate) trait UpdatePrefixMac<T> {
fn update(&mut self, value: T);
}
impl<'p, M> UpdatePrefixMac<PathSegment<'p>> for M
where
for<'s> M: PrefixMac + UpdatePrefixMac<&'s str>,
{
fn update(&mut self, value: PathSegment<'p>) {
match value {
PathSegment::Root => self.update("$"),
PathSegment::ArrayWildcardItem => self.update("[*]"),
PathSegment::ArrayItem => self.update("[@]"),
PathSegment::ArrayPositionItem(i) => self.update(&format!("{i}")),
PathSegment::ObjectItem(key) => self.update(&format!(".{key}")),
}
}
}
impl<const N: usize, M> UpdatePrefixMac<TokenizedSelector<N>> for M
where
M: PrefixMac + UpdatePrefixMac<[u8; N]>,
{
fn update(&mut self, value: TokenizedSelector<N>) {
self.update(value.as_bytes());
}
}
#[derive(Zeroize, ZeroizeOnDrop)]
pub(super) struct Blake3PrefixMac {
prefix: Vec<u8>,
hasher: blake3::Hasher,
}
impl Blake3PrefixMac {
pub fn new(key: &IndexKey, prefix: Vec<u8>) -> Self {
let mut hasher = blake3::Hasher::new_keyed(key.key());
hasher.update(&prefix);
Self { prefix, hasher }
}
fn reset(&mut self) {
self.hasher.reset();
self.hasher.update(&self.prefix);
}
}
impl PrefixMac for Blake3PrefixMac {
fn finalize_reset<const N: usize>(&mut self) -> [u8; N] {
let mut output = [0; N];
self.hasher.finalize_xof().fill(&mut output);
self.reset();
output
}
}
impl UpdatePrefixMac<String> for Blake3PrefixMac {
fn update(&mut self, mut value: String) {
self.hasher.update(value.as_bytes());
value.zeroize();
}
}
impl UpdatePrefixMac<&str> for Blake3PrefixMac {
fn update(&mut self, value: &str) {
self.hasher.update(value.as_bytes());
}
}
impl UpdatePrefixMac<[u8; 16]> for Blake3PrefixMac {
fn update(&mut self, mut value: [u8; 16]) {
self.hasher.update(&value);
value.zeroize();
}
}
#[cfg(test)]
mod test {
}