use proptest::prelude::*;
use crate::metis::{DotSet, HaveSetDecodeBudget, HaveSetDecodeError};
const HEADER_PREFIX_LEN: usize = 41;
const HEADER_LEN: usize = HEADER_PREFIX_LEN + size_of::<u32>();
const SIGNATURE_LEN: usize = 64;
fn decode_possession_have_set(
bytes: &[u8],
budget: HaveSetDecodeBudget,
) -> Option<Result<DotSet, HaveSetDecodeError>> {
let encoded_len = bytes.get(HEADER_PREFIX_LEN..HEADER_LEN)?;
let have_len = usize::try_from(u32::from_be_bytes(encoded_len.try_into().ok()?)).ok()?;
let expected = HEADER_LEN
.checked_add(have_len)?
.checked_add(SIGNATURE_LEN)?;
if expected != bytes.len() {
return None;
}
Some(DotSet::from_bytes_with_budget(
&bytes[HEADER_LEN..HEADER_LEN + have_len],
budget,
))
}
proptest! {
#[test]
fn prop_polis_possession_have_set_never_panics(
header in prop::collection::vec(any::<u8>(), HEADER_PREFIX_LEN..=HEADER_PREFIX_LEN),
have_bytes in prop::collection::vec(any::<u8>(), 0..192),
signature in prop::collection::vec(any::<u8>(), SIGNATURE_LEN..=SIGNATURE_LEN),
max_exceptions in 0usize..=256,
) {
let mut envelope = header;
envelope.extend_from_slice(
&u32::try_from(have_bytes.len()).expect("generated frame length fits").to_be_bytes(),
);
envelope.extend_from_slice(&have_bytes);
envelope.extend_from_slice(&signature);
if let Ok(set) = decode_possession_have_set(
&envelope,
HaveSetDecodeBudget::new(max_exceptions),
).expect("generated outer length is exact") {
let reencoded = set.to_bytes();
prop_assert_eq!(reencoded.as_slice(), have_bytes.as_slice());
}
}
}