#![doc = crate::before_snippet!()]
#![doc = crate::before_snippet!()]
#[allow(unused)]
use core::ffi::{c_int, c_uchar, c_void};
use core::{
fmt,
mem::MaybeUninit,
ops::{Deref, DerefMut},
};
#[cfg(rom_md5_bsd)]
#[derive(Clone)]
#[repr(C)]
struct InternalContext {
buf: [u32; 4],
bits: [u32; 2],
_in: [u8; 64],
}
#[cfg(rom_md5_bsd)]
unsafe extern "C" {
fn esp_rom_md5_init(context: *mut InternalContext);
fn esp_rom_md5_update(context: *mut InternalContext, buf: *const c_void, len: u32);
fn esp_rom_md5_final(digest: *mut u8, context: *mut InternalContext);
}
#[cfg(rom_md5_mbedtls)]
#[derive(Clone)]
#[repr(C)]
struct InternalContext {
total: [u32; 2],
state: [u32; 4],
buffer: [c_uchar; 64],
}
#[cfg(rom_md5_mbedtls)]
unsafe extern "C" {
fn esp_rom_mbedtls_md5_starts_ret(context: *mut InternalContext) -> c_int;
fn esp_rom_mbedtls_md5_update_ret(
context: *mut InternalContext,
buf: *const c_void,
len: u32,
) -> c_int;
fn esp_rom_mbedtls_md5_finish_ret(context: *mut InternalContext, digest: *mut u8) -> c_int;
}
#[derive(Clone)]
pub struct Context(InternalContext);
impl Context {
#[inline]
pub fn new() -> Self {
let mut ctx = MaybeUninit::<InternalContext>::uninit();
unsafe {
#[cfg(rom_md5_bsd)]
esp_rom_md5_init(ctx.as_mut_ptr());
#[cfg(rom_md5_mbedtls)]
let _ = esp_rom_mbedtls_md5_starts_ret(ctx.as_mut_ptr());
Self(ctx.assume_init())
}
}
#[inline]
pub fn consume<T: AsRef<[u8]>>(&mut self, data: T) {
let data = data.as_ref();
unsafe {
#[cfg(rom_md5_bsd)]
esp_rom_md5_update(
&mut self.0 as *mut _,
data.as_ptr() as *const c_void,
data.len() as u32,
);
#[cfg(rom_md5_mbedtls)]
let _ = esp_rom_mbedtls_md5_update_ret(
&mut self.0 as *mut _,
data.as_ptr() as *const c_void,
data.len() as u32,
);
}
}
#[inline]
pub fn compute(mut self) -> Digest {
let mut digest = MaybeUninit::<[u8; 16]>::uninit();
unsafe {
#[cfg(rom_md5_bsd)]
esp_rom_md5_final(digest.as_mut_ptr() as *mut _, &mut self.0 as *mut _);
#[cfg(rom_md5_mbedtls)]
let _ = esp_rom_mbedtls_md5_finish_ret(
&mut self.0 as *mut _,
digest.as_mut_ptr() as *mut _,
);
Digest(digest.assume_init())
}
}
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
#[inline]
pub fn compute<T: AsRef<[u8]>>(data: T) -> Digest {
let mut ctx = Context::new();
ctx.consume(data);
ctx.compute()
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Digest(pub [u8; 16]);
impl fmt::LowerHex for Digest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &byte in &self.0 {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}
impl fmt::UpperHex for Digest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &byte in &self.0 {
write!(f, "{byte:02X}")?;
}
Ok(())
}
}
impl fmt::Display for Digest {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Digest as fmt::LowerHex>::fmt(self, f)
}
}
impl fmt::Debug for Digest {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Digest as fmt::LowerHex>::fmt(self, f)
}
}
impl From<Digest> for [u8; 16] {
#[inline]
fn from(digest: Digest) -> Self {
digest.0
}
}
impl From<Context> for Digest {
#[inline]
fn from(context: Context) -> Digest {
context.compute()
}
}
impl Deref for Digest {
type Target = [u8; 16];
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Digest {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}