use crate::{
crypto::{
KeyMatchStrength,
cipher::{AeadDecryptor, CipherMatch, DecryptError},
},
platform::MaybeSendBoxFuture,
};
#[derive(Debug)]
pub struct MetricsAeadDecryptor<D> {
inner: D,
name: String,
}
#[bon::bon]
impl<D> MetricsAeadDecryptor<D> {
#[builder]
pub fn new(inner: D, #[builder(into)] name: String) -> Self {
Self { inner, name }
}
}
impl<D> MetricsAeadDecryptor<D> {
pub fn inner(&self) -> &D {
&self.inner
}
pub fn into_inner(self) -> D {
self.inner
}
}
impl<D: AeadDecryptor> AeadDecryptor for MetricsAeadDecryptor<D> {
fn cipher_match(&self, m: &CipherMatch<'_>) -> Option<KeyMatchStrength> {
self.inner.cipher_match(m)
}
fn decrypt<'a>(
&'a self,
cipher_match: Option<&'a CipherMatch<'a>>,
nonce: &'a [u8],
ciphertext: &'a [u8],
tag: &'a [u8],
aad: &'a [u8],
) -> MaybeSendBoxFuture<'a, Result<Vec<u8>, DecryptError>> {
Box::pin(async move {
let result = self
.inner
.decrypt(cipher_match, nonce, ciphertext, tag, aad)
.await;
let outcome = match &result {
Ok(_) => "success",
Err(DecryptError::NoMatchingKey) => "no_matching_key",
Err(DecryptError::Other { .. }) => "error",
};
::metrics::counter!(
"huskarl.aead.decrypt",
"name" => self.name.clone(),
"outcome" => outcome,
)
.increment(1);
result
})
}
fn try_refresh(&self) -> MaybeSendBoxFuture<'_, bool> {
Box::pin(async move {
let refreshed = self.inner.try_refresh().await;
let outcome = if refreshed {
"refreshed"
} else {
"not_refreshed"
};
::metrics::counter!(
"huskarl.aead.refresh",
"name" => self.name.clone(),
"outcome" => outcome,
)
.increment(1);
refreshed
})
}
}