pub(crate) const MAX_ALIAS_BYTES: usize = 1024 * 1024 * 32;
#[inline]
#[must_use]
pub(crate) const fn depth_exceeded(depth: usize, max_depth: usize) -> bool {
depth > max_depth
}
#[inline]
#[must_use]
pub(crate) const fn alias_count_exceeded(alias_count: usize, max_alias_expansions: usize) -> bool {
alias_count > max_alias_expansions
}
#[inline]
#[must_use]
pub(crate) fn alias_ratio_exceeded(
alias_count: usize,
anchor_count: usize,
ratio: Option<f64>,
) -> bool {
match ratio {
None => false,
Some(ratio) => {
let anchors = anchor_count.max(1) as f64;
(alias_count as f64) > ratio * anchors
}
}
}
#[inline]
#[must_use]
pub(crate) const fn jump_charge_exceeded(
charge: usize,
expanded_nodes: usize,
event_count: usize,
factor: usize,
) -> (usize, bool) {
let charge = charge.saturating_add(expanded_nodes);
(charge, charge > event_count.saturating_mul(factor))
}
#[inline]
#[must_use]
pub(crate) const fn alias_bytes_exceeded(
alias_bytes: usize,
expanded_bytes: usize,
max_document_length: usize,
) -> (usize, bool) {
let total = alias_bytes.saturating_add(expanded_bytes);
(
total,
total > max_document_length || total > MAX_ALIAS_BYTES,
)
}
#[inline]
#[must_use]
pub(crate) const fn nodes_exceeded(node_count: usize, max_nodes: usize) -> bool {
node_count > max_nodes
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn depth_is_exact_at_the_boundary() {
assert!(!depth_exceeded(128, 128));
assert!(depth_exceeded(129, 128));
}
#[test]
fn ratio_treats_no_anchors_as_one() {
assert!(!alias_ratio_exceeded(10, 0, Some(10.0)));
assert!(alias_ratio_exceeded(11, 0, Some(10.0)));
assert!(!alias_ratio_exceeded(usize::MAX, 0, None));
assert!(!alias_ratio_exceeded(usize::MAX, 1, Some(f64::NAN)));
assert!(!alias_ratio_exceeded(usize::MAX, 1, Some(f64::INFINITY)));
assert!(alias_ratio_exceeded(1, 1, Some(-1.0)));
}
#[test]
fn jump_charge_saturates_instead_of_wrapping() {
let (charge, over) = jump_charge_exceeded(usize::MAX - 1, 5, 10, 100);
assert_eq!(charge, usize::MAX);
assert!(over);
let (_, over) = jump_charge_exceeded(0, 1, usize::MAX, 2);
assert!(!over);
}
#[test]
fn alias_bytes_respect_both_ceilings() {
assert!(!alias_bytes_exceeded(0, 10, 100).1);
assert!(alias_bytes_exceeded(95, 10, 100).1);
assert!(alias_bytes_exceeded(0, MAX_ALIAS_BYTES + 1, usize::MAX).1);
assert!(alias_bytes_exceeded(usize::MAX, 1, usize::MAX).1);
}
}
#[cfg(kani)]
mod proofs {
use super::*;
#[kani::proof]
fn depth_exact_and_monotone() {
let depth: usize = kani::any();
let max: usize = kani::any();
assert_eq!(depth_exceeded(depth, max), depth > max);
if depth_exceeded(depth, max) && depth < usize::MAX {
assert!(depth_exceeded(depth + 1, max));
}
}
#[kani::proof]
fn counts_exact_and_monotone() {
let n: usize = kani::any();
let max: usize = kani::any();
assert_eq!(alias_count_exceeded(n, max), n > max);
assert_eq!(nodes_exceeded(n, max), n > max);
if n < usize::MAX {
assert!(!alias_count_exceeded(n, max) || alias_count_exceeded(n + 1, max));
}
}
#[kani::proof]
fn ratio_is_safe_and_conservative() {
let aliases: u16 = kani::any();
let anchors: u16 = kani::any();
let which: u8 = kani::any();
kani::assume(which < 6);
let ratios = [f64::NAN, f64::INFINITY, 0.5, 1.0, 10.0, 1.0e6];
let ratio = ratios[usize::from(which)];
let (a, n) = (usize::from(aliases), usize::from(anchors));
assert!(!alias_ratio_exceeded(a, n, None));
let hit = alias_ratio_exceeded(a, n, Some(ratio));
if ratio.is_nan() || ratio == f64::INFINITY {
assert!(!hit);
}
if ratio.is_finite() && ratio >= 1.0 && a <= n {
assert!(!hit);
}
}
#[kani::proof]
fn jump_charge_never_wraps() {
let charge_bits: u32 = kani::any();
let add_bits: u32 = kani::any();
let events_bits: u8 = kani::any();
let factor_bits: u8 = kani::any();
let (charge, add, events, factor) = (
charge_bits as usize,
add_bits as usize,
events_bits as usize,
usize::from(factor_bits),
);
let (next, over) = jump_charge_exceeded(charge, add, events, factor);
assert!(next >= charge);
assert!(next >= add);
if over && add < usize::MAX {
assert!(jump_charge_exceeded(charge, add + 1, events, factor).1);
}
}
#[kani::proof]
fn alias_bytes_never_wrap() {
let bytes: usize = kani::any();
let add: usize = kani::any();
let max_doc: usize = kani::any();
let (total, over) = alias_bytes_exceeded(bytes, add, max_doc);
assert!(total >= bytes && total >= add);
if total > MAX_ALIAS_BYTES || total > max_doc {
assert!(over);
}
if !over {
assert!(total <= max_doc && total <= MAX_ALIAS_BYTES);
}
}
}