chksum 0.1.0-rc5

Simple checksum calculator library.
Documentation
use std::ops::{BitOr, Shr};

pub(super) const BLOCK_LENGTH_BITS: usize = 512;
pub(super) const BLOCK_LENGTH_BYTES: usize = BLOCK_LENGTH_BITS / 8;
pub(super) const BLOCK_LENGTH_WORDS: usize = BLOCK_LENGTH_BYTES / 2;
pub(super) const BLOCK_LENGTH_DWORDS: usize = BLOCK_LENGTH_WORDS / 2;

#[derive(Debug, Eq, PartialEq)]
pub(super) struct Block([u8; BLOCK_LENGTH_BYTES]);

impl BitOr for Block {
    type Output = Self;

    #[cfg_attr(not(debug_assertions), inline)]
    fn bitor(self, rhs: Self) -> Self::Output {
        Self([
            self.0[0x00] | rhs.0[0x00],
            self.0[0x01] | rhs.0[0x01],
            self.0[0x02] | rhs.0[0x02],
            self.0[0x03] | rhs.0[0x03],
            self.0[0x04] | rhs.0[0x04],
            self.0[0x05] | rhs.0[0x05],
            self.0[0x06] | rhs.0[0x06],
            self.0[0x07] | rhs.0[0x07],
            self.0[0x08] | rhs.0[0x08],
            self.0[0x09] | rhs.0[0x09],
            self.0[0x0A] | rhs.0[0x0A],
            self.0[0x0B] | rhs.0[0x0B],
            self.0[0x0C] | rhs.0[0x0C],
            self.0[0x0D] | rhs.0[0x0D],
            self.0[0x0E] | rhs.0[0x0E],
            self.0[0x0F] | rhs.0[0x0F],
            self.0[0x10] | rhs.0[0x10],
            self.0[0x11] | rhs.0[0x11],
            self.0[0x12] | rhs.0[0x12],
            self.0[0x13] | rhs.0[0x13],
            self.0[0x14] | rhs.0[0x14],
            self.0[0x15] | rhs.0[0x15],
            self.0[0x16] | rhs.0[0x16],
            self.0[0x17] | rhs.0[0x17],
            self.0[0x18] | rhs.0[0x18],
            self.0[0x19] | rhs.0[0x19],
            self.0[0x1A] | rhs.0[0x1A],
            self.0[0x1B] | rhs.0[0x1B],
            self.0[0x1C] | rhs.0[0x1C],
            self.0[0x1D] | rhs.0[0x1D],
            self.0[0x1E] | rhs.0[0x1E],
            self.0[0x1F] | rhs.0[0x1F],
            self.0[0x20] | rhs.0[0x20],
            self.0[0x21] | rhs.0[0x21],
            self.0[0x22] | rhs.0[0x22],
            self.0[0x23] | rhs.0[0x23],
            self.0[0x24] | rhs.0[0x24],
            self.0[0x25] | rhs.0[0x25],
            self.0[0x26] | rhs.0[0x26],
            self.0[0x27] | rhs.0[0x27],
            self.0[0x28] | rhs.0[0x28],
            self.0[0x29] | rhs.0[0x29],
            self.0[0x2A] | rhs.0[0x2A],
            self.0[0x2B] | rhs.0[0x2B],
            self.0[0x2C] | rhs.0[0x2C],
            self.0[0x2D] | rhs.0[0x2D],
            self.0[0x2E] | rhs.0[0x2E],
            self.0[0x2F] | rhs.0[0x2F],
            self.0[0x30] | rhs.0[0x30],
            self.0[0x31] | rhs.0[0x31],
            self.0[0x32] | rhs.0[0x32],
            self.0[0x33] | rhs.0[0x33],
            self.0[0x34] | rhs.0[0x34],
            self.0[0x35] | rhs.0[0x35],
            self.0[0x36] | rhs.0[0x36],
            self.0[0x37] | rhs.0[0x37],
            self.0[0x38] | rhs.0[0x38],
            self.0[0x39] | rhs.0[0x39],
            self.0[0x3A] | rhs.0[0x3A],
            self.0[0x3B] | rhs.0[0x3B],
            self.0[0x3C] | rhs.0[0x3C],
            self.0[0x3D] | rhs.0[0x3D],
            self.0[0x3E] | rhs.0[0x3E],
            self.0[0x3F] | rhs.0[0x3F],
        ])
    }
}

impl BitOr<[u8; BLOCK_LENGTH_BYTES]> for Block {
    type Output = Self;

    #[cfg_attr(not(debug_assertions), inline)]
    fn bitor(self, rhs: [u8; BLOCK_LENGTH_BYTES]) -> Self::Output {
        let rhs: Self = rhs.into();
        self.bitor(rhs)
    }
}

impl Shr<usize> for Block {
    type Output = Self;

    #[allow(clippy::suspicious_arithmetic_impl)]
    #[cfg_attr(nightly, optimize(speed))]
    #[cfg_attr(not(debug_assertions), inline)]
    fn shr(self, rhs: usize) -> Self::Output {
        let block = {
            let mut vec = vec![0x00; rhs];
            vec.extend_from_slice(&self.0[..BLOCK_LENGTH_BYTES - rhs]);
            vec
        };
        let block: [u8; BLOCK_LENGTH_BYTES] = block.try_into().unwrap();
        block.into()
    }
}

impl From<[u8; BLOCK_LENGTH_BYTES]> for Block {
    #[cfg_attr(not(debug_assertions), inline)]
    fn from(block: [u8; BLOCK_LENGTH_BYTES]) -> Self {
        Self(block)
    }
}

impl From<Block> for [u8; BLOCK_LENGTH_BYTES] {
    #[cfg_attr(not(debug_assertions), inline)]
    fn from(block: Block) -> Self {
        block.0
    }
}

impl From<Block> for [u32; BLOCK_LENGTH_DWORDS] {
    #[cfg_attr(not(debug_assertions), inline)]
    fn from(block: Block) -> Self {
        [
            u32::from_be_bytes([block.0[0x00], block.0[0x01], block.0[0x02], block.0[0x03]]),
            u32::from_be_bytes([block.0[0x04], block.0[0x05], block.0[0x06], block.0[0x07]]),
            u32::from_be_bytes([block.0[0x08], block.0[0x09], block.0[0x0A], block.0[0x0B]]),
            u32::from_be_bytes([block.0[0x0C], block.0[0x0D], block.0[0x0E], block.0[0x0F]]),
            u32::from_be_bytes([block.0[0x10], block.0[0x11], block.0[0x12], block.0[0x13]]),
            u32::from_be_bytes([block.0[0x14], block.0[0x15], block.0[0x16], block.0[0x17]]),
            u32::from_be_bytes([block.0[0x18], block.0[0x19], block.0[0x1A], block.0[0x1B]]),
            u32::from_be_bytes([block.0[0x1C], block.0[0x1D], block.0[0x1E], block.0[0x1F]]),
            u32::from_be_bytes([block.0[0x20], block.0[0x21], block.0[0x22], block.0[0x23]]),
            u32::from_be_bytes([block.0[0x24], block.0[0x25], block.0[0x26], block.0[0x27]]),
            u32::from_be_bytes([block.0[0x28], block.0[0x29], block.0[0x2A], block.0[0x2B]]),
            u32::from_be_bytes([block.0[0x2C], block.0[0x2D], block.0[0x2E], block.0[0x2F]]),
            u32::from_be_bytes([block.0[0x30], block.0[0x31], block.0[0x32], block.0[0x33]]),
            u32::from_be_bytes([block.0[0x34], block.0[0x35], block.0[0x36], block.0[0x37]]),
            u32::from_be_bytes([block.0[0x38], block.0[0x39], block.0[0x3A], block.0[0x3B]]),
            u32::from_be_bytes([block.0[0x3C], block.0[0x3D], block.0[0x3E], block.0[0x3F]]),
        ]
    }
}