use serde::{Deserialize, Serialize};
use sha3::digest::FixedOutput;
use sha3::Digest;
pub const DIGEST_BYTES: usize = 32;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Keccak256 {
bytes: [u8; DIGEST_BYTES],
string: String,
}
impl Keccak256 {
pub fn from_slice(preimage: &[u8]) -> Self {
let bytes = sha3::Keccak256::digest(preimage).into();
let string = format!("0x{}", hex::encode(bytes));
Self { bytes, string }
}
pub fn from_slices<R: AsRef<[u8]>>(preimages: &[R]) -> Self {
let mut hasher = sha3::Keccak256::new();
for preimage in preimages.iter() {
hasher.update(preimage);
}
let bytes: [u8; DIGEST_BYTES] = hasher.finalize_fixed().into();
let string = format!("0x{}", hex::encode(bytes));
Self { bytes, string }
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_slice()
}
pub fn as_str(&self) -> &str {
self.string.as_str()
}
pub fn to_vec(&self) -> Vec<u8> {
self.bytes.to_vec()
}
}
impl std::fmt::Display for Keccak256 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
#[test]
fn hash_and_stringify_works() {
assert_eq!(
super::Keccak256::from_slices(&["foo".as_bytes(), "bar".as_bytes(),]).as_str(),
"0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e"
);
}
}