evidence 0.1.0

Type-level tags for cryptographic primitives
Documentation
//! Property-based tests for Digest.

#![cfg(feature = "sha2")]

use bolero::check;
use evidence::codec::Encode;
use evidence::digest::{Digest, DigestPrimitive, DigestUnchecked, sha2::Sha256};
use hybrid_array::Array;

/// A simple identity codec for testing — just returns the bytes directly.
enum Identity {}

impl Encode<Vec<u8>> for Identity {
    type Error = core::convert::Infallible;

    fn encode(value: &Vec<u8>) -> Result<Vec<u8>, Self::Error> {
        Ok(value.clone())
    }
}

impl Encode<[u8; 32]> for Identity {
    type Error = core::convert::Infallible;

    fn encode(value: &[u8; 32]) -> Result<Vec<u8>, Self::Error> {
        Ok(value.to_vec())
    }
}

#[test]
fn digest_deterministic() {
    check!().with_type::<Vec<u8>>().for_each(|data| {
        let d1: Digest<Vec<u8>, Sha256, Identity> = Digest::hash(data);
        let d2: Digest<Vec<u8>, Sha256, Identity> = Digest::hash(data);
        assert_eq!(d1, d2, "same input must produce same digest");
    });
}

#[test]
fn digest_roundtrip_array() {
    check!().with_type::<[u8; 32]>().for_each(|bytes| {
        // Input is exactly 32 bytes, matching Sha256::Size
        let array: Array<u8, <Sha256 as DigestPrimitive>::Size> = Array::from(*bytes);

        let digest: Digest<(), Sha256, Identity> = Digest::from_unchecked_array(array);
        let recovered = digest.into_array();

        assert_eq!(array, recovered, "roundtrip must preserve bytes");
    });
}

#[test]
fn different_inputs_different_digests() {
    check!()
        .with_type::<(Vec<u8>, Vec<u8>)>()
        .filter(|(a, b)| a != b)
        .for_each(|(a, b)| {
            let da: Digest<Vec<u8>, Sha256, Identity> = Digest::hash(a);
            let db: Digest<Vec<u8>, Sha256, Identity> = Digest::hash(b);
            assert_ne!(da, db, "different inputs should produce different digests");
        });
}