ps-hash-core 0.1.0-25

Core hashing primitives for ps-hash.
Documentation
mod implementations;
mod methods;

use ps_ecc::ReedSolomon;

use crate::{HashError, HASH_SIZE_BIN, PARITY};

pub const RS: ReedSolomon = match ReedSolomon::new(PARITY) {
    Ok(rs) => rs,
    Err(_) => panic!("Failed to construct Reed-Solomon codec."),
};

#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Hash {
    pub(crate) inner: [u8; HASH_SIZE_BIN],
}

#[inline]
pub fn hash(data: impl AsRef<[u8]>) -> Result<Hash, HashError> {
    Hash::hash(data)
}

#[cfg(test)]
#[allow(clippy::expect_used)]
mod tests {
    use super::{hash, Hash, HASH_SIZE_BIN, PARITY, RS};

    #[test]
    fn rs_codec_is_valid() {
        assert_eq!(RS.parity(), PARITY);
    }

    /// Pins the correction budget: changing it changes every encoded length.
    #[test]
    fn rs_codec_parity_matches_constant() {
        assert_eq!(RS.parity(), 7);
    }

    #[test]
    fn hash_struct_has_correct_size() {
        assert_eq!(std::mem::size_of::<Hash>(), HASH_SIZE_BIN);
    }

    #[test]
    fn hash_struct_is_copy() {
        fn assert_copy<T: Copy>() {}
        assert_copy::<Hash>();
    }

    #[test]
    fn hash_struct_is_clone() {
        fn assert_clone<T: Clone>() {}
        assert_clone::<Hash>();
    }

    #[test]
    fn hash_function_delegates_to_method() {
        let data = b"test data";
        let via_fn = hash(data).expect("hashing should succeed");
        let via_method = Hash::hash(data).expect("hashing should succeed");
        assert_eq!(via_fn, via_method);
    }

    #[test]
    fn hash_function_returns_ok_for_empty() {
        assert!(hash(b"").is_ok());
    }

    #[test]
    fn hash_function_returns_ok_for_non_empty() {
        assert!(hash(b"non-empty").is_ok());
    }

    #[test]
    fn hash_inner_field_has_correct_size() {
        let h = hash(b"test").expect("hashing should succeed");
        assert_eq!(h.inner.len(), HASH_SIZE_BIN);
    }
}