tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

slice.rs (4311B)


      1 // Copyright 2023 Cryspen Sarl
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 //! This module contains the trait and related errors for hashers that take slices as
     10 //! arguments and write the results to mutable slices.
     11 
     12 use super::arrayref;
     13 
     14 /// A trait for oneshot hashing, where the output is written to a provided slice.
     15 pub trait Hash {
     16    /// Writes the digest for the given input byte slice, into `digest` in immediate mode.
     17    fn hash(digest: &mut [u8], payload: &[u8]) -> Result<usize, HashError>;
     18 }
     19 
     20 /// A trait for incremental hashing, where the output is written to a provided slice.
     21 pub trait DigestIncremental: super::DigestIncrementalBase {
     22    /// Writes the digest into `digest`.
     23    ///
     24    /// Note that the digest state can be continued to be used, to extend the digest.
     25    fn finish(state: &mut Self::IncrementalState, digest: &mut [u8]) -> Result<usize, FinishError>;
     26 }
     27 
     28 /// Error indicating that finalizing failed.
     29 #[derive(Debug, PartialEq)]
     30 pub enum FinishError {
     31    /// The length of the provided digest buffer is invalid.
     32    InvalidDigestLength,
     33    /// Unknown error.
     34    Unknown,
     35 }
     36 
     37 impl core::fmt::Display for FinishError {
     38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
     39        let text = match self {
     40            FinishError::InvalidDigestLength => {
     41                "the length of the provided digest buffer is invalid"
     42            }
     43            FinishError::Unknown => "indicates an unknown error",
     44        };
     45 
     46        f.write_str(text)
     47    }
     48 }
     49 
     50 /// Error indicating that hashing failed.
     51 #[derive(Debug, PartialEq)]
     52 pub enum HashError {
     53    /// The length of the provided digest buffer is invalid.
     54    InvalidDigestLength,
     55    /// The length of the provided payload is invalid.
     56    InvalidPayloadLength,
     57 }
     58 
     59 impl core::fmt::Display for HashError {
     60    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
     61        let text = match self {
     62            HashError::InvalidDigestLength => "the length of the provided digest buffer is invalid",
     63            HashError::InvalidPayloadLength => "the length of the provided payload is invalid",
     64        };
     65 
     66        f.write_str(text)
     67    }
     68 }
     69 
     70 #[cfg(feature = "error-in-core")]
     71 mod error_in_core {
     72 
     73    impl core::error::Error for super::HashError {}
     74    impl core::error::Error for super::FinishError {}
     75 }
     76 
     77 impl From<arrayref::HashError> for HashError {
     78    fn from(e: arrayref::HashError) -> Self {
     79        match e {
     80            arrayref::HashError::InvalidPayloadLength => Self::InvalidPayloadLength,
     81        }
     82    }
     83 }
     84 
     85 #[macro_export]
     86 /// Implements [`Hash`] for any [`arrayref::Hash`].
     87 macro_rules! impl_hash_trait {
     88    ($type:ty => $len:expr) => {
     89        impl $crate::digest::slice::Hash for $type {
     90            fn hash(
     91                digest: &mut [u8],
     92                payload: &[u8],
     93            ) -> Result<usize, $crate::digest::slice::HashError> {
     94                let digest: &mut [u8; $len] = digest
     95                    .try_into()
     96                    .map_err(|_| $crate::digest::slice::HashError::InvalidDigestLength)?;
     97                <Self as $crate::digest::arrayref::Hash<$len>>::hash(digest, payload)
     98                    .map(|_| $len)
     99                    .map_err($crate::digest::slice::HashError::from)
    100            }
    101        }
    102    };
    103 }
    104 
    105 #[macro_export]
    106 /// Implements [`DigestIncremental`] for any [`arrayref::DigestIncremental`].
    107 macro_rules! impl_digest_incremental_trait {
    108    ($type:ty => $incremental_state:ty, $len:expr) => {
    109        impl $crate::digest::slice::DigestIncremental for $type {
    110            fn finish(
    111                state: &mut Self::IncrementalState,
    112                digest: &mut [u8],
    113            ) -> Result<usize, $crate::digest::slice::FinishError> {
    114                let digest: &mut [u8; $len] = digest
    115                    .try_into()
    116                    .map_err(|_| $crate::digest::slice::FinishError::InvalidDigestLength)?;
    117                <Self as $crate::digest::arrayref::DigestIncremental<$len>>::finish(state, digest);
    118 
    119                Ok($len)
    120            }
    121        }
    122    };
    123 }
    124 
    125 pub use impl_digest_incremental_trait;
    126 pub use impl_hash_trait;