//! Contains contexts used for the digest algorithms. //! //! These contexts contain the digest name and the salt to be used with the digest. //! //! # Defaults //! Both the digest name (`Algorithm`) and the `Context` itself implement `Default`. //! The default algorithm is `SHA256Truncated`, and the default `Context` uses this algorithm along with the default salt (which is the library's hard-coded static salt.) use crate::*; use std::{ io::{ Read, }, }; /// An algorithm to use for the context. /// /// # CRC /// `CRC32` and `CRC64` are only available if compiled with the default "crc" feature enabled. /// If the library is compiled without this feature, but with the "ffi" feature (i.e. generates native libraries), then FFI requests for the CRC family of digests will instead use the default (`Sha256Truncated`). #[derive(Clone,Debug,PartialEq,Eq,Hash)] pub enum Algorithm { #[cfg(feature="crc")] /// The 32 bit CRC checksum (requires default feature `crc`) Crc32, #[cfg(feature="crc")] /// The 64 bit CRC checksum (requires default feature `crc`) Crc64, /// The SHA256 hash Sha256, /// The SHA256 hash truncated to the first 64 bits Sha256Truncated, } impl Default for Algorithm { #[inline] fn default() -> Self { Self::Sha256Truncated } } /// A kana-hash context containing it's salt and algorithm. /// /// # Default /// The default context contains the `SHA256Truncated` digest algorithm and the library's hard-coded static salt. #[derive(Clone,Debug,PartialEq,Eq,Hash)] pub struct Context { algo: Algorithm, salt: salt::Salt, } impl Context { /// Create a new kana-hash context with an algorithm and a salt pub fn new(algo: Algorithm, salt: impl Into) -> Self { Self { algo, salt: salt.into(), } } /// The algorithm used pub fn get_algorithm(&self) -> &Algorithm { &self.algo } /// The salt used pub fn get_salt(&self) -> &salt::Salt { &self.salt } pub(crate) fn compute(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error> { fn provide(input: &mut R, salt: &salt::Salt, output: &mut usize) -> Result, error::Error> where P: provider::ByteProvider, R: Read + ?Sized { let this = P::compute(input, &salt, output)?; Ok(Vec::from(this.bytes())) } let mut output = 0usize; let bytes = match self.algo { #[cfg(feature="crc")] Algorithm::Crc32 => provide::(&mut from, &self.salt, &mut output)?, #[cfg(feature="crc")] Algorithm::Crc64 => provide::(&mut from, &self.salt, &mut output)?, Algorithm::Sha256 => provide::(&mut from, &self.salt, &mut output)?, Algorithm::Sha256Truncated => provide::(&mut from, &self.salt, &mut output)?, }.into_boxed_slice(); Ok((output, bytes)) } #[cfg(feature="ffi")] pub(crate) unsafe fn into_raw(self) -> CContext { CContext{ algo: u8::from(self.algo), salt: salt::into_raw(self.salt), flags: Default::default(), } } #[cfg(feature="ffi")] pub(crate) unsafe fn clone_from_raw(from: *const CContext) -> Self { let from = &*from; Self { algo: from.algo.into(), salt: salt::clone_from_raw(&from.salt as *const salt::FFI), } } #[cfg(feature="ffi")] pub(crate) unsafe fn from_raw(from: *mut CContext) -> Self { let from = &mut *from; let output = Self{ algo: from.algo.into(), salt: salt::from_raw(&mut from.salt as *mut salt::FFI), }; from.algo = 0; output } } impl Default for Context { fn default() -> Self { Self { algo: Default::default(), salt: Default::default(), } } } pub(crate) const ALGO_DEFAULT: u8 = 0; pub(crate) const ALGO_CRC32: u8 = 1; pub(crate) const ALGO_CRC64: u8 = 2; pub(crate) const ALGO_SHA256: u8 = 3; pub(crate) const ALGO_SHA256_TRUNCATED: u8 = 4; /// FFI context #[derive(Debug)] #[repr(C)] pub(crate) struct CContext { algo: u8, flags: u64, //nothing yet, might be flags later idk salt: salt::FFI, } impl From for u8 { fn from(al: Algorithm) -> Self { match al { #[cfg(feature="crc")] Algorithm::Crc32 => ALGO_CRC32, #[cfg(feature="crc")] Algorithm::Crc64 => ALGO_CRC64, Algorithm::Sha256 => ALGO_SHA256, Algorithm::Sha256Truncated => ALGO_SHA256_TRUNCATED, } } } impl From for Algorithm { fn from(al: u8) -> Self { match al { #[cfg(feature="crc")] ALGO_CRC32 => Algorithm::Crc32, #[cfg(feature="crc")] ALGO_CRC64 => Algorithm::Crc64, ALGO_SHA256 => Algorithm::Sha256, ALGO_SHA256_TRUNCATED => Algorithm::Sha256Truncated, _ => Self::default(), } } }