#![cfg(kani)]
use cas_kit::Hash;
fn hex_val(b: u8) -> u32 {
match b {
b'0'..=b'9' => u32::from(b - b'0'),
b'a'..=b'f' => u32::from(b - b'a') + 10,
_ => 99,
}
}
#[kani::proof]
#[kani::unwind(40)]
#[kani::solver(kissat)]
fn kani_bucket_matches_hex_prefix() {
let bytes: [u8; 32] = kani::any();
let h = Hash(bytes);
kani::assert(
u32::from(h.bucket()) < 256,
"bucket is a 2-hex-prefix index in 0..256",
);
let hex = h.to_hex();
kani::assert(hex.len() == 64, "to_hex emits exactly 64 chars");
let v0 = hex_val(hex.as_bytes()[0]);
let v1 = hex_val(hex.as_bytes()[1]);
kani::assert(v0 < 16 && v1 < 16, "hex chars are lowercase hex digits");
kani::assert(
v0 * 16 + v1 == u32::from(h.bucket()),
"first 2 hex chars of to_hex encode bucket()",
);
}
#[kani::proof]
#[kani::unwind(40)]
#[kani::solver(kissat)]
fn kani_hex_roundtrip_stability() {
let bytes: [u8; 32] = kani::any();
let h = Hash(bytes);
match Hash::from_hex(&h.to_hex()) {
Ok(parsed) => {
kani::assert(parsed == h, "from_hex(to_hex(h)) == h");
kani::assert(
parsed.bucket() == h.bucket(),
"bucket stable under hex roundtrip",
);
}
Err(_) => kani::assert(false, "from_hex always accepts to_hex output"),
}
}