use pith_digest::{SplitMix64, adler32, crc32, ffi, fnv1a64, sha256};
#[test]
fn ffi_surface_matches_the_library() {
let mut out = [0u8; 32];
let status = unsafe { ffi::pith_digest_sha256(b"abc".as_ptr(), 3, out.as_mut_ptr()) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(out, *sha256(b"abc").expect("within size limit").as_bytes());
let mut c = 0u32;
let status = unsafe { ffi::pith_digest_crc32(b"123456789".as_ptr(), 9, &mut c) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(c, crc32(b"123456789"));
assert_eq!(c, 0xcbf4_3926);
let mut a = 0u32;
let status = unsafe { ffi::pith_digest_adler32(b"Wikipedia".as_ptr(), 9, &mut a) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(a, adler32(b"Wikipedia"));
assert_eq!(a, 0x11e6_0398);
let mut f = 0u64;
let status = unsafe { ffi::pith_digest_fnv1a64(b"foobar".as_ptr(), 6, &mut f) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(f, fnv1a64(b"foobar"));
assert_eq!(f, 0x8594_4171_f739_67e8);
let mut seq = [0u64; 2];
let status = unsafe { ffi::pith_digest_splitmix64_fill(0, seq.as_mut_ptr(), 2) };
assert_eq!(status, ffi::PITH_OK);
let mut rng = SplitMix64::new(0);
assert_eq!(seq, [rng.next_u64(), rng.next_u64()]);
unsafe {
assert_eq!(
ffi::pith_digest_sha256(core::ptr::null(), 1, out.as_mut_ptr()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_crc32(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_adler32(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_fnv1a64(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_splitmix64_fill(0, core::ptr::null_mut(), 1),
ffi::PITH_E_INVALID
);
let status = ffi::pith_digest_sha256(core::ptr::null(), 0, out.as_mut_ptr());
assert_eq!(status, ffi::PITH_OK);
assert_eq!(out, *sha256(b"").expect("within size limit").as_bytes());
}
}
#[test]
fn ffi_surface_covers_the_tier_one_exports() {
let mut d20 = [0u8; 20];
let status = unsafe { ffi::pith_digest_sha1(b"abc".as_ptr(), 3, d20.as_mut_ptr()) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(
d20,
*pith_digest::sha1(b"abc")
.expect("within size limit")
.as_bytes()
);
let mut d64 = [0u8; 64];
let status = unsafe { ffi::pith_digest_sha512(b"abc".as_ptr(), 3, d64.as_mut_ptr()) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(d64, *pith_digest::sha512(b"abc").as_bytes());
let key = [0x0b_u8; 20];
let mut mac = [0u8; 32];
let status = unsafe {
ffi::pith_digest_hmac_sha256(key.as_ptr(), 20, b"Hi There".as_ptr(), 8, mac.as_mut_ptr())
};
assert_eq!(status, ffi::PITH_OK);
assert_eq!(
hex(&mac),
"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
);
let mut h = 0u64;
let status = unsafe { ffi::pith_digest_xxh64(core::ptr::null(), 0, 0, &mut h) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(h, 0xEF46_DB37_51D8_E999);
let mut d16 = [0u8; 16];
let status =
unsafe { ffi::pith_digest_murmur3_x64_128(core::ptr::null(), 0, 0, d16.as_mut_ptr()) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(d16, [0u8; 16]);
let mut c = 0u32;
let status = unsafe { ffi::pith_digest_crc32c(b"123456789".as_ptr(), 9, &mut c) };
assert_eq!(status, ffi::PITH_OK);
assert_eq!(c, 0xe306_9283);
let mut enc = [0u8; 12];
let mut enc_len = 0usize;
let status = unsafe {
ffi::pith_digest_base64_encode(b"foobar".as_ptr(), 6, enc.as_mut_ptr(), 12, &mut enc_len)
};
assert_eq!(status, ffi::PITH_OK);
assert_eq!(&enc[..enc_len], b"Zm9vYmFy");
let mut dec = [0u8; 6];
let mut dec_len = 0usize;
let status = unsafe {
ffi::pith_digest_base64_decode(enc.as_ptr(), enc_len, dec.as_mut_ptr(), 6, &mut dec_len)
};
assert_eq!(status, ffi::PITH_OK);
assert_eq!(&dec[..dec_len], b"foobar");
let mut slots = [0u64; 2];
let status = unsafe { ffi::pith_digest_xoshiro256_fill(0, slots.as_mut_ptr(), 2) };
assert_eq!(status, ffi::PITH_OK);
let mut rng = pith_digest::Xoshiro256StarStar::from_seed(0);
assert_eq!(slots, [rng.next_u64(), rng.next_u64()]);
unsafe {
assert_eq!(
ffi::pith_digest_sha1(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_sha512(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_hmac_sha256(b"x".as_ptr(), 1, b"y".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_xxh64(b"x".as_ptr(), 1, 0, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_murmur3_x64_128(b"x".as_ptr(), 1, 0, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_crc32c(b"x".as_ptr(), 1, core::ptr::null_mut()),
ffi::PITH_E_INVALID
);
assert_eq!(
ffi::pith_digest_xoshiro256_fill(0, core::ptr::null_mut(), 1),
ffi::PITH_E_INVALID
);
let mut enc_len = 0usize;
assert_eq!(
ffi::pith_digest_base64_encode(
b"foobar".as_ptr(),
6,
enc.as_mut_ptr(),
3,
&mut enc_len
),
ffi::PITH_E_REJECTED
);
let mut dec_len = 0usize;
assert_eq!(
ffi::pith_digest_base64_decode(b"Zy==".as_ptr(), 4, dec.as_mut_ptr(), 6, &mut dec_len),
ffi::PITH_E_REJECTED
);
}
}
fn hex(bytes: &[u8]) -> String {
let mut out = String::new();
for b in bytes {
out.push_str(&format!("{b:02x}"));
}
out
}