Skip to content

Commit

Permalink
Remove ArrayEncoding usage from Digest and delete ArrayEncoding.
Browse files Browse the repository at this point in the history
  • Loading branch information
briansmith committed Oct 11, 2023
1 parent 59efee9 commit b2fd38e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 47 deletions.
43 changes: 24 additions & 19 deletions src/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@
// The goal for this implementation is to drive the overhead as close to zero
// as possible.

use crate::{
c, cpu, debug,
endian::{ArrayEncoding, BigEndian},
polyfill,
};
use crate::{c, cpu, debug, polyfill};
use core::num::Wrapping;

mod sha1;
Expand Down Expand Up @@ -248,8 +244,7 @@ impl Digest {
impl AsRef<[u8]> for Digest {
#[inline(always)]
fn as_ref(&self) -> &[u8] {
let as64 = unsafe { &self.value.as64 };
&as64.as_byte_array()[..self.algorithm.output_len]
&self.value.0[..self.algorithm.output_len]
}
}

Expand Down Expand Up @@ -456,10 +451,7 @@ union State {
}

#[derive(Clone, Copy)]
union Output {
as64: [BigEndian<u64>; 512 / 8 / core::mem::size_of::<BigEndian<u64>>()],
as32: [BigEndian<u32>; 256 / 8 / core::mem::size_of::<BigEndian<u32>>()],
}
struct Output([u8; MAX_OUTPUT_LEN]);

/// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms
/// in this module.
Expand All @@ -474,17 +466,30 @@ pub const MAX_OUTPUT_LEN: usize = 512 / 8;
pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN;

fn sha256_format_output(input: State) -> Output {
let input = unsafe { &input.as32 };
Output {
as32: input.map(BigEndian::from),
}
let input = unsafe { input.as32 };
format_output::<_, _, { core::mem::size_of::<u32>() }>(input, u32::to_be_bytes)
}

fn sha512_format_output(input: State) -> Output {
let input = unsafe { &input.as64 };
Output {
as64: input.map(BigEndian::from),
}
let input = unsafe { input.as64 };
format_output::<_, _, { core::mem::size_of::<u64>() }>(input, u64::to_be_bytes)
}

#[inline]
fn format_output<T, F, const N: usize>(input: [Wrapping<T>; sha2::CHAINING_WORDS], f: F) -> Output
where
F: Fn(T) -> [u8; N],
T: Copy,
{
let mut output = Output([0; MAX_OUTPUT_LEN]);
output
.0
.iter_mut()
.zip(input.iter().copied().map(|Wrapping(w)| f(w)).flatten())
.for_each(|(o, i)| {
*o = i;
});
output
}

/// The length of the output of SHA-1, in bytes.
Expand Down
28 changes: 0 additions & 28 deletions src/endian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ where
const ZERO: Self;
}

/// Work around the inability to implement `AsRef` for arrays of `Encoding`s
/// due to the coherence rules.
pub trait ArrayEncoding<T> {
fn as_byte_array(&self) -> &T;
}

macro_rules! define_endian {
($endian:ident) => {
#[derive(Clone, Copy)]
Expand All @@ -25,21 +19,6 @@ macro_rules! define_endian {
};
}

macro_rules! impl_array_encoding {
($endian:ident, $base:ident, $elems:expr) => {
impl ArrayEncoding<[u8; $elems * core::mem::size_of::<$base>()]>
for [$endian<$base>; $elems]
{
#[inline]
fn as_byte_array(&self) -> &[u8; $elems * core::mem::size_of::<$base>()] {
let as_bytes_ptr =
self.as_ptr() as *const [u8; $elems * core::mem::size_of::<$base>()];
unsafe { &*as_bytes_ptr }
}
}
};
}

macro_rules! impl_endian {
($endian:ident, $base:ident, $to_endian:ident, $from_endian:ident, $size:expr) => {
impl Encoding<$base> for $endian<$base> {
Expand Down Expand Up @@ -80,18 +59,11 @@ macro_rules! impl_endian {
$base::$from_endian(value)
}
}

impl_array_encoding!($endian, $base, 1);
impl_array_encoding!($endian, $base, 2);
impl_array_encoding!($endian, $base, 3);
impl_array_encoding!($endian, $base, 4);
impl_array_encoding!($endian, $base, 8);
};
}

define_endian!(BigEndian);
impl_endian!(BigEndian, u32, to_be, from_be, 4);
impl_endian!(BigEndian, u64, to_be, from_be, 8);

#[cfg(test)]
mod tests {
Expand Down

0 comments on commit b2fd38e

Please sign in to comment.