pub mod config_contracts {
pub fn validate_size(size: usize, max: usize) -> bool {
contract_pre_configuration!();
let result = size <= max;
contract_post_configuration!(&"ok");
result
}
pub fn validate_index(index: usize, len: usize) -> bool {
contract_pre_configuration!();
index < len
}
pub fn validated_len(data: &[u8]) -> usize {
debug_assert!(!data.is_empty(), "data must not be empty");
data.len()
}
}
pub mod numeric_contracts {
pub fn checked_add(a: u64, b: u64) -> Option<u64> {
a.checked_add(b)
}
pub fn is_valid_float(val: f64) -> bool {
val.is_finite()
}
pub fn normalize(val: f64, min: f64, max: f64) -> f64 {
debug_assert!(max > min, "max must be greater than min");
((val - min) / (max - min)).clamp(0.0, 1.0)
}
}
#[cfg(verus)]
mod verus_specs {
use builtin::*;
use builtin_macros::*;
verus! {
#[requires(covered_lines <= total_lines)]
#[ensures(result <= 100)]
fn verify_coverage_percentage(covered_lines: u64, total_lines: u64) -> u64 {
if total_lines == 0 { 100 } else { (covered_lines * 100) / total_lines }
}
#[requires(coverage_pct <= 100)]
#[ensures(result == (coverage_pct >= threshold))]
fn verify_coverage_gate(coverage_pct: u64, threshold: u64) -> bool {
coverage_pct >= threshold
}
#[requires(threshold >= 0 && threshold <= 100)]
#[ensures(result >= 0 && result <= 100)]
#[recommends(threshold >= 95)]
fn verify_minimum_coverage_threshold(threshold: u64) -> u64 { threshold }
#[requires(killed_mutants <= total_mutants)]
#[ensures(result <= 100)]
fn verify_mutation_score(killed_mutants: u64, total_mutants: u64) -> u64 {
if total_mutants == 0 { 100 } else { (killed_mutants * 100) / total_mutants }
}
#[requires(mutation_score <= 100)]
#[ensures(result == (mutation_score >= 80))]
#[recommends(mutation_score >= 85)]
fn verify_mutation_gate(mutation_score: u64) -> bool {
mutation_score >= 80
}
#[requires(survived >= 0)]
#[ensures(result == killed + survived)]
fn verify_mutant_total(killed: u64, survived: u64) -> u64 {
killed + survived
}
#[requires(score <= 134)]
#[ensures(result <= 4)]
fn verify_quality_grade(score: u64) -> u64 {
if score >= 120 { 0 } else if score >= 100 { 1 } else if score >= 80 { 2 } else if score >= 60 { 3 } else { 4 } }
#[requires(grade <= 4)]
#[ensures(result == (grade <= max_allowed))]
fn verify_grade_gate(grade: u64, max_allowed: u64) -> bool {
grade <= max_allowed
}
#[requires(tdg_score >= 0 && tdg_score <= 100)]
#[ensures(result == (tdg_score >= 95))]
#[recommends(tdg_score >= 95)]
fn verify_tdg_gate(tdg_score: u64) -> bool {
tdg_score >= 95
}
#[requires(components > 0)]
#[ensures(result <= 100)]
#[invariant(sum <= components * 100)]
fn verify_tdg_aggregate(sum: u64, components: u64) -> u64 {
sum / components
}
#[requires(complexity > 0)]
#[ensures(result == (complexity <= 10))]
#[recommends(complexity <= 10)]
fn verify_complexity_gate(complexity: u64) -> bool {
complexity <= 10
}
#[requires(num_functions > 0)]
#[ensures(result <= max_complexity)]
#[decreases(num_functions)]
fn verify_avg_complexity(total_complexity: u64, num_functions: u64, max_complexity: u64) -> u64 {
let avg = total_complexity / num_functions;
if avg > max_complexity { max_complexity } else { avg }
}
#[ensures(result == (count == 0))]
#[recommends(count == 0)]
fn verify_zero_satd(count: u64) -> bool {
count == 0
}
#[requires(unit + property + integration == total)]
#[ensures(result == total)]
#[invariant(unit <= total && property <= total && integration <= total)]
fn verify_test_count(unit: u64, property: u64, integration: u64, total: u64) -> u64 {
total
}
#[requires(total > 0)]
#[ensures(result <= 100)]
fn verify_test_ratio(category_count: u64, total: u64) -> u64 {
(category_count * 100) / total
}
#[ensures(result == (vulnerabilities == 0))]
#[recommends(vulnerabilities == 0)]
fn verify_security_gate(vulnerabilities: u64) -> bool {
vulnerabilities == 0
}
#[requires(severity <= 4)]
#[ensures(result == (severity == 0))]
fn verify_no_critical_vulns(severity: u64) -> bool {
severity == 0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_size() {
assert!(config_contracts::validate_size(5, 10));
assert!(!config_contracts::validate_size(11, 10));
assert!(config_contracts::validate_size(10, 10));
}
#[test]
fn test_validate_index() {
assert!(config_contracts::validate_index(0, 5));
assert!(config_contracts::validate_index(4, 5));
assert!(!config_contracts::validate_index(5, 5));
}
#[test]
fn test_validated_len() {
assert_eq!(config_contracts::validated_len(&[1, 2, 3]), 3);
}
#[test]
fn test_checked_add() {
assert_eq!(numeric_contracts::checked_add(1, 2), Some(3));
assert_eq!(numeric_contracts::checked_add(u64::MAX, 1), None);
}
#[test]
fn test_is_valid_float() {
assert!(numeric_contracts::is_valid_float(1.0));
assert!(!numeric_contracts::is_valid_float(f64::NAN));
assert!(!numeric_contracts::is_valid_float(f64::INFINITY));
}
#[test]
fn test_normalize() {
let result = numeric_contracts::normalize(5.0, 0.0, 10.0);
assert!((result - 0.5).abs() < f64::EPSILON);
assert!((numeric_contracts::normalize(0.0, 0.0, 10.0)).abs() < f64::EPSILON);
assert!((numeric_contracts::normalize(10.0, 0.0, 10.0) - 1.0).abs() < f64::EPSILON);
}
}
#[cfg(kani)]
mod kani_proofs {
#[kani::proof]
fn verify_config_bounds() {
let val: u32 = kani::any();
kani::assume(val <= 1000);
assert!(val <= 1000);
}
#[kani::proof]
fn verify_index_safety() {
let len: usize = kani::any();
kani::assume(len > 0 && len <= 1024);
let idx: usize = kani::any();
kani::assume(idx < len);
assert!(idx < len);
}
#[kani::proof]
fn verify_no_overflow_add() {
let a: u32 = kani::any();
let b: u32 = kani::any();
kani::assume(a <= 10000);
kani::assume(b <= 10000);
let result = a.checked_add(b);
assert!(result.is_some());
}
#[kani::proof]
fn verify_no_overflow_mul() {
let a: u32 = kani::any();
let b: u32 = kani::any();
kani::assume(a <= 1000);
kani::assume(b <= 1000);
let result = a.checked_mul(b);
assert!(result.is_some());
}
#[kani::proof]
fn verify_division_nonzero() {
let numerator: u64 = kani::any();
let denominator: u64 = kani::any();
kani::assume(denominator > 0);
let result = numerator / denominator;
assert!(result <= numerator);
}
}