use core::fmt;
use crate::mac::hmac::algo::{self, Digest as _, HexDigest as _};
use crate::ct;
use crate::hex;
#[must_use]
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Digest<D: algo::Digest> {
raw: D
}
impl<D: algo::Digest> fmt::Debug for Digest<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Digest { ... }")
}
}
impl<D: algo::Digest + Copy> Digest<D> {
pub const fn new(digest: D) -> Self {
Self { raw: digest }
}
#[must_use]
pub const fn into_inner(self) -> D {
self.raw
}
pub fn hex_encode(&self) -> HexDigest<D::Hex> {
let mut out = D::Hex::zeroes();
hex::encode_into(self.as_ref(), out.as_mut()).unwrap();
HexDigest::new(out)
}
}
impl<D: algo::Digest> AsRef<[u8]> for Digest<D> {
#[inline]
fn as_ref(&self) -> &[u8] { self.raw.as_ref() }
}
impl<D: algo::Digest> AsRef<D> for Digest<D> {
#[inline]
fn as_ref(&self) -> &D { &self.raw }
}
impl<D: algo::Digest> PartialEq for Digest<D> {
fn eq(&self, other: &Self) -> bool {
ct::ct_eq(self.raw, other.raw)
}
}
impl<D: algo::Digest> Eq for Digest<D> {}
impl<D: algo::Digest> PartialEq<[u8]> for Digest<D> {
fn eq(&self, other: &[u8]) -> bool {
ct::ct_eq(self.raw, other)
}
}
impl<D: algo::Digest, T> PartialEq<&T> for Digest<D> where Self: PartialEq<T> {
#[inline]
fn eq(&self, other: &&T) -> bool {
self.eq(other)
}
}
impl<D: algo::Digest, T> PartialEq<&mut T> for Digest<D> where Self: PartialEq<T> {
#[inline]
fn eq(&self, other: &&mut T) -> bool {
self.eq(other)
}
}
#[repr(transparent)]
#[must_use]
#[derive(Copy, Clone)]
pub struct HexDigest<D: algo::HexDigest> {
raw: D
}
impl<D: algo::HexDigest> HexDigest<D> {
const fn new(digest: D) -> Self {
Self { raw: digest }
}
pub fn decode(&self) -> Digest<D::Digest> {
let mut output = D::Digest::zeroes();
hex::decode_into(self.raw.as_ref(), output.as_mut())
.unwrap();
Digest::new(output)
}
#[inline]
pub fn as_str(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.raw.as_ref()) }
}
#[must_use]
pub const fn into_inner(self) -> D {
self.raw
}
}
impl<D: algo::HexDigest> AsRef<[u8]> for HexDigest<D> {
#[inline]
fn as_ref(&self) -> &[u8] { self.raw.as_ref() }
}
impl<D: algo::HexDigest> AsRef<D> for HexDigest<D> {
#[inline]
fn as_ref(&self) -> &D { &self.raw }
}
impl<D: algo::HexDigest> PartialEq for HexDigest<D> {
fn eq(&self, other: &Self) -> bool {
ct::ct_eq(self.raw, other.raw)
}
}
impl<D: algo::HexDigest> Eq for HexDigest<D> {}
impl<D: algo::HexDigest> PartialEq<[u8]> for HexDigest<D> {
fn eq(&self, other: &[u8]) -> bool {
ct::ct_eq(self.raw, other)
}
}
impl<D: algo::HexDigest, T> PartialEq<&T> for HexDigest<D> where Self: PartialEq<T> {
#[inline]
fn eq(&self, other: &&T) -> bool {
self.eq(other)
}
}
impl<D: algo::HexDigest, T> PartialEq<&mut T> for HexDigest<D> where Self: PartialEq<T> {
#[inline]
fn eq(&self, other: &&mut T) -> bool {
self.eq(other)
}
}
impl<D: algo::HexDigest> From<HexDigest<D>> for Digest<D::Digest> {
fn from(value: HexDigest<D>) -> Self {
value.decode()
}
}
impl<D: algo::Digest> From<Digest<D>> for HexDigest<D::Hex> {
fn from(value: Digest<D>) -> Self {
value.hex_encode()
}
}