use std::fmt;
use hexlify::Hex;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{Visitor, Error};
use blake2::{Blake2b, Digest};
use blake2::digest::VariableOutput;
#[derive(Hash, PartialEq, Eq, Clone)]
pub struct BlockHash([u8; 32]);
struct HashVisitor;
impl BlockHash {
pub fn from_bytes(bytes: &[u8]) -> Option<BlockHash> {
if bytes.len() == 32 {
let mut ar = [0u8; 32];
ar.copy_from_slice(bytes);
return Some(BlockHash(ar));
}
return None;
}
pub fn hash_bytes(bytes: &[u8]) -> BlockHash {
let mut hash: Blake2b = VariableOutput::new(32).expect("length is ok");
hash.input(bytes);
let mut result = [0u8; 32];
hash.variable_result(&mut result).expect("length is okay");
return BlockHash(result);
}
}
impl fmt::Debug for BlockHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "BlockHash({})", &Hex(&self.0))
}
}
impl fmt::Display for BlockHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", &Hex(&self.0))
}
}
impl<'a> Visitor<'a> for HashVisitor {
type Value = BlockHash;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("bytes")
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where E: Error
{
if value.len() == 32 {
let mut array = [0u8; 32];
array.copy_from_slice(value);
Ok(BlockHash(array))
} else {
return Err(E::invalid_length(value.len(), &self));
}
}
}
impl<'a> Deserialize<'a> for BlockHash {
fn deserialize<D>(deserializer: D) -> Result<BlockHash, D::Error>
where D: Deserializer<'a>
{
deserializer.deserialize_bytes(HashVisitor)
}
}
impl Serialize for BlockHash {
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
ser.serialize_bytes(&self.0)
}
}