use std::{array::TryFromSliceError, convert::TryFrom};
use blake2::{
digest::{Update, VariableOutput},
VarBlake2b,
};
use serde::{Deserialize, Serialize};
use casper_types::bytesrepr::{self, FromBytes, ToBytes};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
pub struct Blake2bHash([u8; Blake2bHash::LENGTH]);
impl Blake2bHash {
pub const LENGTH: usize = 32;
pub fn new(data: &[u8]) -> Self {
let mut ret = [0u8; Blake2bHash::LENGTH];
let mut hasher = VarBlake2b::new(Blake2bHash::LENGTH).unwrap();
hasher.update(data);
hasher.finalize_variable(|hash| ret.clone_from_slice(hash));
Blake2bHash(ret)
}
pub fn value(&self) -> [u8; Blake2bHash::LENGTH] {
self.0
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
}
impl core::fmt::LowerHex for Blake2bHash {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let hex_string = base16::encode_lower(&self.value());
if f.alternate() {
write!(f, "0x{}", hex_string)
} else {
write!(f, "{}", hex_string)
}
}
}
impl core::fmt::UpperHex for Blake2bHash {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let hex_string = base16::encode_upper(&self.value());
if f.alternate() {
write!(f, "0x{}", hex_string)
} else {
write!(f, "{}", hex_string)
}
}
}
impl core::fmt::Display for Blake2bHash {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "Blake2bHash({:#x})", self)
}
}
impl core::fmt::Debug for Blake2bHash {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}", self)
}
}
impl From<[u8; Blake2bHash::LENGTH]> for Blake2bHash {
fn from(arr: [u8; Blake2bHash::LENGTH]) -> Self {
Blake2bHash(arr)
}
}
impl<'a> TryFrom<&'a [u8]> for Blake2bHash {
type Error = TryFromSliceError;
fn try_from(slice: &[u8]) -> Result<Blake2bHash, Self::Error> {
<[u8; Blake2bHash::LENGTH]>::try_from(slice).map(Blake2bHash)
}
}
impl AsRef<[u8]> for Blake2bHash {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<Blake2bHash> for [u8; Blake2bHash::LENGTH] {
fn from(hash: Blake2bHash) -> Self {
hash.0
}
}
impl ToBytes for Blake2bHash {
#[inline(always)]
fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
self.0.to_bytes()
}
#[inline(always)]
fn serialized_length(&self) -> usize {
self.0.serialized_length()
}
}
impl FromBytes for Blake2bHash {
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
FromBytes::from_bytes(bytes).map(|(arr, rem)| (Blake2bHash(arr), rem))
}
}
impl hex::FromHex for Blake2bHash {
type Error = hex::FromHexError;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
Ok(Blake2bHash(hex::FromHex::from_hex(hex)?))
}
}