use gridiron::fp_256;
use gridiron::fp_256::Fp256;
use internal::ByteVector;
use nonemptyvec::NonEmptyVec;
pub trait Hashable {
fn to_bytes(&self) -> ByteVector;
}
impl Hashable for u8 {
fn to_bytes(&self) -> ByteVector {
vec![*self]
}
}
impl<T> Hashable for Vec<T>
where
T: Hashable,
{
fn to_bytes(&self) -> ByteVector {
let mut result: Vec<u8> = Vec::new();
for t in self.iter() {
let mut bytes = t.to_bytes();
result.append(&mut bytes);
}
result
}
}
impl<T: Hashable + Clone> Hashable for NonEmptyVec<T> {
fn to_bytes(&self) -> Vec<u8> {
self.to_vec().to_bytes()
}
}
impl<T: Hashable, U: Hashable> Hashable for (T, U) {
fn to_bytes(&self) -> ByteVector {
vec![self.0.to_bytes(), self.1.to_bytes()].to_bytes()
}
}
impl<T: Hashable, U: Hashable, V: Hashable> Hashable for (T, U, V) {
fn to_bytes(&self) -> ByteVector {
vec![self.0.to_bytes(), self.1.to_bytes(), self.2.to_bytes()].to_bytes()
}
}
impl<T: Hashable + Copy> Hashable for Option<T> {
fn to_bytes(&self) -> ByteVector {
self.map_or(vec![0], |x| x.to_bytes())
}
}
pub trait Hashable32 {
fn to_bytes_32(&self) -> [u8; 32];
}
impl<T: Hashable32> Hashable for T {
fn to_bytes(&self) -> Vec<u8> {
self.to_bytes_32().to_vec()
}
}
impl Hashable32 for Fp256 {
fn to_bytes_32(&self) -> [u8; fp_256::NUMBYTES] {
self.to_bytes_array()
}
}
#[cfg(test)]
mod test {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn byte_hashable(ref v in any::<u8>()) {
let hashable: ByteVector = Hashable::to_bytes(v);
assert_eq!(vec![v.clone()], hashable);
}
#[test]
fn bytevector_hashable(bv in prop::collection::vec(any::<u8>(), 0..32)) {
let hashable = bv.to_bytes();
assert_eq!(bv, hashable);
}
#[test]
fn bytevector_of_bytevector_hashable(bv1 in prop::collection::vec(any::<u8>(), 0..32), bv2 in prop::collection::vec(any::<u8>(), 0..32)) {
let concat = [&bv1[..], &bv2[..]].concat();
assert_eq!(concat, vec![bv1, bv2].to_bytes());
}
}
}