ahsah 2.1.0

Incremental hashing contexts for MD5 and SHA-2 with reader helpers and optional SIMD decode paths
Documentation
use crate::{buffer::BlockBuffer, digest::Digest, encoding::DigestBytes};

use super::sha2::{compress_sha512, digest_from_u64_state};

const INITIAL_STATE: [u64; 8] = [
    0x6a09e667f3bcc908,
    0xbb67ae8584caa73b,
    0x3c6ef372fe94f82b,
    0xa54ff53a5f1d36f1,
    0x510e527fade682d1,
    0x9b05688c2b3e6c1f,
    0x1f83d9abfb41bd6b,
    0x5be0cd19137e2179,
];

#[derive(Clone, Debug)]
pub struct Sha512 {
    state: [u64; 8],
    buffer: BlockBuffer<128, 16, true>,
}

impl Default for Sha512 {
    fn default() -> Self {
        Self::new()
    }
}

impl Sha512 {
    pub fn new() -> Self {
        Self {
            state: INITIAL_STATE,
            buffer: BlockBuffer::new(),
        }
    }

    pub fn digest(data: &[u8]) -> DigestBytes {
        <Self as Digest>::digest(data)
    }

    pub fn finalize_hex(self) -> String {
        <Self as Digest>::finalize_hex(self)
    }
}

impl Digest for Sha512 {
    const OUTPUT_SIZE: usize = 64;

    fn update(&mut self, data: &[u8]) {
        let state = &mut self.state;
        self.buffer
            .update(data, |block| compress_sha512(state, block));
    }

    fn input_size(&self) -> u128 {
        self.buffer.message_len()
    }

    fn reset(&mut self) {
        self.state = INITIAL_STATE;
        self.buffer.reset();
    }

    fn finalize(mut self) -> DigestBytes {
        let state = &mut self.state;
        self.buffer.finalize(|block| compress_sha512(state, block));
        digest_from_u64_state(&self.state, Self::OUTPUT_SIZE)
    }
}