use crate::algorithms::hash::HashAlgorithm;
use crate::error::{Error, Result};
use crate::traits::HashAlgorithmTrait;
use seal_crypto::prelude::Hasher;
use seal_crypto::schemes::hash::{Sha256, Sha384, Sha512};
use std::ops::Deref;
macro_rules! impl_hash_algorithm {
($wrapper:ident, $algo:ty, $algo_enum:expr) => {
#[derive(Clone, Debug, Default)]
pub struct $wrapper;
impl $wrapper {
pub fn new() -> Self {
Self
}
}
impl From<$wrapper> for Box<dyn HashAlgorithmTrait> {
fn from(wrapper: $wrapper) -> Self {
Box::new(wrapper)
}
}
impl HashAlgorithmTrait for $wrapper {
fn hash(&self, data: &[u8]) -> Vec<u8> {
<$algo>::hash(data)
}
fn hmac(&self, key: &[u8], msg: &[u8]) -> Result<Vec<u8>> {
<$algo>::hmac(key, msg).map_err(Error::from)
}
fn clone_box(&self) -> Box<dyn HashAlgorithmTrait> {
Box::new(self.clone())
}
fn algorithm(&self) -> HashAlgorithm {
$algo_enum
}
fn into_boxed(self) -> Box<dyn HashAlgorithmTrait> {
Box::new(self)
}
}
};
}
#[derive(Clone, Debug)]
pub struct HashAlgorithmWrapper {
pub(crate) algorithm: Box<dyn HashAlgorithmTrait>,
}
impl Deref for HashAlgorithmWrapper {
type Target = Box<dyn HashAlgorithmTrait>;
fn deref(&self) -> &Self::Target {
&self.algorithm
}
}
impl Into<Box<dyn HashAlgorithmTrait>> for HashAlgorithmWrapper {
fn into(self) -> Box<dyn HashAlgorithmTrait> {
self.algorithm
}
}
impl HashAlgorithmWrapper {
pub fn new(algorithm: Box<dyn HashAlgorithmTrait>) -> Self {
Self { algorithm }
}
pub fn from_enum(algorithm: HashAlgorithm) -> Self {
let algorithm: Box<dyn HashAlgorithmTrait> = match algorithm {
HashAlgorithm::Sha256 => Box::new(Hash256Wrapper::new()),
HashAlgorithm::Sha384 => Box::new(Hash384Wrapper::new()),
HashAlgorithm::Sha512 => Box::new(Hash512Wrapper::new()),
};
Self::new(algorithm)
}
}
impl HashAlgorithmTrait for HashAlgorithmWrapper {
fn hash(&self, data: &[u8]) -> Vec<u8> {
self.algorithm.hash(data)
}
fn hmac(&self, key: &[u8], msg: &[u8]) -> Result<Vec<u8>> {
self.algorithm.hmac(key, msg)
}
fn algorithm(&self) -> HashAlgorithm {
self.algorithm.algorithm()
}
fn clone_box(&self) -> Box<dyn HashAlgorithmTrait> {
Box::new(self.clone())
}
fn into_boxed(self) -> Box<dyn HashAlgorithmTrait> {
self.algorithm
}
}
impl From<HashAlgorithm> for HashAlgorithmWrapper {
fn from(algorithm: HashAlgorithm) -> Self {
Self::from_enum(algorithm)
}
}
impl From<Box<dyn HashAlgorithmTrait>> for HashAlgorithmWrapper {
fn from(algorithm: Box<dyn HashAlgorithmTrait>) -> Self {
Self::new(algorithm)
}
}
impl_hash_algorithm!(Hash256Wrapper, Sha256, HashAlgorithm::Sha256);
impl_hash_algorithm!(Hash384Wrapper, Sha384, HashAlgorithm::Sha384);
impl_hash_algorithm!(Hash512Wrapper, Sha512, HashAlgorithm::Sha512);