blake2 0.11.0

BLAKE2 hash functions
Documentation
use core::ops::{Add, BitXor, Shl, Shr};

#[cfg(feature = "zeroize")]
use digest::zeroize::Zeroize;

macro_rules! impl_vector4 {
    ($vec:ident, $word:ident) => {
        #[derive(Clone, Copy, Debug)]
        #[repr(C)]
        pub(crate) struct $vec(
            pub(crate) $word,
            pub(crate) $word,
            pub(crate) $word,
            pub(crate) $word,
        );

        impl $vec {
            #[inline(always)]
            pub(crate) fn new(e0: $word, e1: $word, e2: $word, e3: $word) -> Self {
                Self(e0, e1, e2, e3)
            }

            #[inline(always)]
            pub(crate) fn gather(
                src: &[$word],
                i0: usize,
                i1: usize,
                i2: usize,
                i3: usize,
            ) -> Self {
                $vec::new(src[i0], src[i1], src[i2], src[i3])
            }

            #[cfg(target_endian = "little")]
            #[inline(always)]
            #[allow(clippy::wrong_self_convention)]
            pub(crate) fn from_le(self) -> Self {
                self
            }

            #[cfg(not(target_endian = "little"))]
            #[inline(always)]
            pub(crate) fn from_le(self) -> Self {
                $vec::new(
                    $word::from_le(self.0),
                    $word::from_le(self.1),
                    $word::from_le(self.2),
                    $word::from_le(self.3),
                )
            }

            #[cfg(target_endian = "little")]
            #[inline(always)]
            pub(crate) fn to_le(self) -> Self {
                self
            }

            #[cfg(not(target_endian = "little"))]
            #[inline(always)]
            pub(crate) fn to_le(self) -> Self {
                $vec::new(
                    self.0.to_le(),
                    self.1.to_le(),
                    self.2.to_le(),
                    self.3.to_le(),
                )
            }

            #[inline(always)]
            pub(crate) fn wrapping_add(self, rhs: Self) -> Self {
                self + rhs
            }

            #[inline(always)]
            pub(crate) fn rotate_right_const(self, n: u32) -> Self {
                $vec::new(
                    self.0.rotate_right(n),
                    self.1.rotate_right(n),
                    self.2.rotate_right(n),
                    self.3.rotate_right(n),
                )
            }

            #[inline(always)]
            pub(crate) fn shuffle_left_1(self) -> Self {
                $vec::new(self.1, self.2, self.3, self.0)
            }

            #[inline(always)]
            pub(crate) fn shuffle_left_2(self) -> Self {
                $vec::new(self.2, self.3, self.0, self.1)
            }

            #[inline(always)]
            pub(crate) fn shuffle_left_3(self) -> Self {
                $vec::new(self.3, self.0, self.1, self.2)
            }

            #[inline(always)]
            pub(crate) fn shuffle_right_1(self) -> Self {
                self.shuffle_left_3()
            }
            #[inline(always)]
            pub(crate) fn shuffle_right_2(self) -> Self {
                self.shuffle_left_2()
            }
            #[inline(always)]
            pub(crate) fn shuffle_right_3(self) -> Self {
                self.shuffle_left_1()
            }

            #[inline(always)]
            pub(crate) fn as_bytes(&self) -> &[u8] {
                let p = self as *const Self as *const u8;
                unsafe { core::slice::from_raw_parts(p, core::mem::size_of::<Self>()) }
            }
        }

        impl Add for $vec {
            type Output = Self;

            #[inline(always)]
            fn add(self, rhs: Self) -> Self::Output {
                $vec::new(
                    self.0.wrapping_add(rhs.0),
                    self.1.wrapping_add(rhs.1),
                    self.2.wrapping_add(rhs.2),
                    self.3.wrapping_add(rhs.3),
                )
            }
        }

        impl BitXor for $vec {
            type Output = Self;

            #[inline(always)]
            fn bitxor(self, rhs: Self) -> Self::Output {
                $vec::new(
                    self.0 ^ rhs.0,
                    self.1 ^ rhs.1,
                    self.2 ^ rhs.2,
                    self.3 ^ rhs.3,
                )
            }
        }

        impl Shl<$vec> for $vec {
            type Output = Self;

            #[inline(always)]
            fn shl(self, rhs: Self) -> Self::Output {
                $vec::new(
                    self.0 << rhs.0,
                    self.1 << rhs.1,
                    self.2 << rhs.2,
                    self.3 << rhs.3,
                )
            }
        }

        impl Shr<$vec> for $vec {
            type Output = Self;

            #[inline(always)]
            fn shr(self, rhs: Self) -> Self::Output {
                $vec::new(
                    self.0 >> rhs.0,
                    self.1 >> rhs.1,
                    self.2 >> rhs.2,
                    self.3 >> rhs.3,
                )
            }
        }

        #[cfg(feature = "zeroize")]
        impl Zeroize for $vec {
            fn zeroize(&mut self) {
                self.0.zeroize();
                self.1.zeroize();
                self.2.zeroize();
                self.3.zeroize();
            }
        }
    };
}

impl_vector4!(u32x4, u32);
impl_vector4!(u64x4, u64);