use crate::assert_length;
use crate::encode;
use crate::hash_type;
use crate::HashType;
use crate::HashableContent;
use crate::HashableContentBytes;
use crate::HoloHash;
use crate::HoloHashOf;
use crate::HoloHashed;
use crate::HOLO_HASH_CORE_LEN;
use futures::FutureExt;
use hash_type::HashTypeAsync;
use hash_type::HashTypeSync;
use must_future::MustBoxFuture;
pub const MAX_HASHABLE_CONTENT_LEN: usize = 16 * 1000 * 1000;
impl<T: HashTypeSync> HoloHash<T> {
pub fn with_data_sync<C: HashableContent<HashType = T>>(content: &C) -> HoloHash<T> {
hash_from_content(content)
}
}
impl<T, C> HoloHashed<C>
where
T: HashTypeSync,
C: HashableContent<HashType = T>,
{
pub fn from_content_sync(content: C) -> Self {
let hash: HoloHashOf<C> = HoloHash::<T>::with_data_sync(&content);
Self { content, hash }
}
pub fn verify_hash_sync(&self) -> Result<(), HoloHash<T>> {
let hash = HoloHash::<T>::with_data_sync(&self.content);
if self.hash == hash {
Ok(())
} else {
Err(hash)
}
}
}
impl<T: HashTypeAsync> HoloHash<T> {
pub async fn with_data<C: HashableContent<HashType = T>>(content: &C) -> HoloHash<T> {
hash_from_content(content)
}
}
impl<T, C> HoloHashed<C>
where
T: HashTypeAsync,
C: HashableContent<HashType = T>,
{
pub async fn from_content(content: C) -> Self {
let hash: HoloHashOf<C> = HoloHash::<T>::with_data(&content).await;
Self { content, hash }
}
pub async fn verify_hash(&self) -> Result<(), HoloHash<T>> {
let hash = HoloHash::<T>::with_data(&self.content).await;
if self.hash == hash {
Ok(())
} else {
Err(hash)
}
}
}
impl<T, C> HoloHashed<C>
where
T: HashTypeAsync,
C: HashableContent<HashType = T>,
{
}
fn hash_from_content<T: HashType, C: HashableContent<HashType = T>>(content: &C) -> HoloHash<T> {
match content.hashable_content() {
HashableContentBytes::Content(sb) => {
let bytes: Vec<u8> = holochain_serialized_bytes::UnsafeBytes::from(sb).into();
let hash = encode::blake2b_256(&bytes);
assert_length!(HOLO_HASH_CORE_LEN, &hash);
HoloHash::<T>::from_raw_32_and_type(hash, content.hash_type())
}
HashableContentBytes::Prehashed39(bytes) => HoloHash::from_raw_39_panicky(bytes),
}
}
pub trait HashableContentExtSync<T>: HashableContent
where
T: HashTypeSync,
{
fn to_hash(&self) -> HoloHash<T>;
fn into_hashed(self) -> HoloHashed<Self>;
}
pub trait HashableContentExtAsync<'a, T>: HashableContent
where
T: HashTypeAsync,
{
fn to_hash(&self) -> MustBoxFuture<HoloHash<T>>;
fn into_hashed(self) -> MustBoxFuture<'a, HoloHashed<Self>>;
}
impl<T, C> HashableContentExtSync<T> for C
where
T: HashTypeSync,
C: HashableContent<HashType = T>,
{
fn to_hash(&self) -> HoloHash<T> {
HoloHash::with_data_sync(self)
}
fn into_hashed(self) -> HoloHashed<Self> {
HoloHashed::from_content_sync(self)
}
}
impl<'a, T, C> HashableContentExtAsync<'a, T> for C
where
T: HashTypeAsync,
C: 'a + HashableContent<HashType = T> + Send + Sync,
{
fn to_hash(&self) -> MustBoxFuture<HoloHash<T>> {
async move { HoloHash::with_data(self).await }
.boxed()
.into()
}
fn into_hashed(self) -> MustBoxFuture<'a, HoloHashed<Self>> {
async move { HoloHashed::from_content(self).await }
.boxed()
.into()
}
}