#![allow(warnings, clippy::infallible_try_from)]
use core::convert::Infallible;
use crate::intrinsics::{Felt, Word};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[repr(transparent)]
pub struct Digest {
pub inner: Word,
}
impl Digest {
#[inline]
pub fn new(felts: [Felt; 4]) -> Self {
Self {
inner: Word::from(felts),
}
}
#[inline]
pub const fn from_word(word: Word) -> Self {
Self { inner: word }
}
}
impl TryFrom<Word> for Digest {
type Error = Infallible;
#[inline]
fn try_from(word: Word) -> Result<Self, Self::Error> {
Ok(Self::from_word(word))
}
}
impl From<Digest> for Word {
#[inline]
fn from(digest: Digest) -> Self {
digest.inner
}
}
impl From<[Felt; 4]> for Digest {
#[inline]
fn from(felts: [Felt; 4]) -> Self {
Self::new(felts)
}
}
impl From<Digest> for [Felt; 4] {
#[inline]
fn from(digest: Digest) -> Self {
(&digest.inner).into()
}
}
#[cfg(all(target_family = "wasm", miden))]
unsafe extern "C" {
#[link_name = "miden::core::crypto::hashes::poseidon2::merge"]
fn extern_poseidon2_merge(
a0: Felt,
a1: Felt,
a2: Felt,
a3: Felt,
b0: Felt,
b1: Felt,
b2: Felt,
b3: Felt,
result_ptr: *mut Felt,
);
}
#[inline]
#[cfg(all(target_family = "wasm", miden))]
pub fn merge(digests: [Digest; 2]) -> Digest {
unsafe {
let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
let result_ptr = ret_area.as_mut_ptr() as *mut Felt;
extern_poseidon2_merge(
digests[0].inner.a,
digests[0].inner.b,
digests[0].inner.c,
digests[0].inner.d,
digests[1].inner.a,
digests[1].inner.b,
digests[1].inner.c,
digests[1].inner.d,
result_ptr,
);
Digest::from_word(ret_area.assume_init())
}
}
#[inline]
#[cfg(not(all(target_family = "wasm", miden)))]
pub fn merge(_digests: [Digest; 2]) -> Digest {
unimplemented!("crypto intrinsics are only available when targeting the Miden VM")
}