#![no_std]
extern crate block_buffer;
extern crate byte_tools;
#[macro_use]
extern crate digest;
#[cfg(not(feature = "asm"))]
extern crate fake_simd as simd;
#[cfg(feature = "asm")]
extern crate sha1_asm as utils;
#[cfg(not(feature = "asm"))]
mod utils;
use utils::compress;
use byte_tools::write_u32v_be;
use block_buffer::BlockBuffer512;
pub use digest::Digest;
use digest::generic_array::GenericArray;
use digest::generic_array::typenum::{U20, U64};
mod consts;
use consts::{STATE_LEN, H};
#[derive(Clone)]
pub struct Sha1 {
h: [u32; STATE_LEN],
len: u64,
buffer: BlockBuffer512,
}
impl Default for Sha1 {
fn default() -> Self {
Sha1{ h: H, len: 0u64, buffer: Default::default() }
}
}
impl digest::BlockInput for Sha1 {
type BlockSize = U64;
}
impl digest::Input for Sha1 {
fn process(&mut self, input: &[u8]) {
self.len += input.len() as u64;
let state = &mut self.h;
self.buffer.input(input, |d| compress(state, d));
}
}
impl digest::FixedOutput for Sha1 {
type OutputSize = U20;
fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> {
{
let state = &mut self.h;
let l = self.len << 3;
let l = if cfg!(target_endian = "little") { l.to_be() } else { l.to_le() };
self.buffer.len_padding(l, |d| compress(state, d));
}
let mut out = GenericArray::default();
write_u32v_be(&mut out, &self.h);
out
}
}
impl_opaque_debug!(Sha1);