use std::marker::PhantomData;
pub struct HasLabel<T>(PhantomData<T>);
pub struct ValidRole<T>(PhantomData<T>);
pub struct MinTargetSize<T>(PhantomData<T>);
pub struct NoOverflow<T>(PhantomData<T>);
pub struct KeyboardAccessible<T>(PhantomData<T>);
pub struct AccessibleAA<T>(PhantomData<T>);
mod emit_impls {
use super::*;
use elicitation::contracts::Prop;
use elicitation::proc_macro2::TokenStream;
use elicitation::quote::quote;
impl<T: 'static> Prop for HasLabel<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_has_label() {
let label: &str = kani::any();
kani::assume(!label.is_empty());
assert!(!label.is_empty(), "Label must be non-empty");
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_has_label(label: &str)
requires !label.is_empty()
ensures !label.is_empty()
{
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
#[creusot::ensures(!label.is_empty())]
fn verify_has_label(label: &str) -> bool {
!label.is_empty()
}
}
}
}
impl<T: 'static> Prop for ValidRole<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_valid_role() {
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_valid_role(role: accesskit::Role) {
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
fn verify_valid_role(role: accesskit::Role) -> bool {
true
}
}
}
}
impl<T: 'static> Prop for MinTargetSize<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_min_target_size() {
let width: u32 = kani::any();
let height: u32 = kani::any();
kani::assume(width >= 44);
kani::assume(height >= 44);
assert!(width >= 44, "Width must be at least 44px");
assert!(height >= 44, "Height must be at least 44px");
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_min_target_size(width: u32, height: u32)
requires width >= 44 && height >= 44
ensures width >= 44 && height >= 44
{
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
#[creusot::requires(width >= 44)]
#[creusot::requires(height >= 44)]
#[creusot::ensures(width >= 44 && height >= 44)]
fn verify_min_target_size(width: u32, height: u32) -> bool {
width >= 44 && height >= 44
}
}
}
}
impl<T: 'static> Prop for NoOverflow<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_no_overflow() {
let x: i32 = kani::any();
let y: i32 = kani::any();
let width: u32 = kani::any();
let height: u32 = kani::any();
let vp_width: u32 = kani::any();
let vp_height: u32 = kani::any();
kani::assume(x >= 0);
kani::assume(y >= 0);
kani::assume(x as u32 + width <= vp_width);
kani::assume(y as u32 + height <= vp_height);
assert!(x as u32 + width <= vp_width, "Must fit horizontally");
assert!(y as u32 + height <= vp_height, "Must fit vertically");
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_no_overflow(
x: i32, y: i32,
width: u32, height: u32,
vp_width: u32, vp_height: u32
)
requires
x >= 0,
y >= 0,
x as u32 + width <= vp_width,
y as u32 + height <= vp_height
ensures
x as u32 + width <= vp_width,
y as u32 + height <= vp_height
{
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
#[creusot::requires(x >= 0 && y >= 0)]
#[creusot::requires((x as u32) + width <= vp_width)]
#[creusot::requires((y as u32) + height <= vp_height)]
#[creusot::ensures((x as u32) + width <= vp_width && (y as u32) + height <= vp_height)]
fn verify_no_overflow(
x: i32, y: i32,
width: u32, height: u32,
vp_width: u32, vp_height: u32
) -> bool {
(x as u32) + width <= vp_width && (y as u32) + height <= vp_height
}
}
}
}
impl<T: 'static> Prop for KeyboardAccessible<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_keyboard_accessible() {
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_keyboard_accessible(role: accesskit::Role) {
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
fn verify_keyboard_accessible(role: accesskit::Role) -> bool {
true
}
}
}
}
impl<T: 'static> Prop for AccessibleAA<T> {
fn kani_proof() -> TokenStream {
quote! {
#[kani::proof]
fn verify_accessible_aa() {
<HasLabel<T>>::kani_proof();
<ValidRole<T>>::kani_proof();
<KeyboardAccessible<T>>::kani_proof();
<NoOverflow<T>>::kani_proof();
}
}
}
fn verus_proof() -> TokenStream {
quote! {
#[verus::proof]
fn verify_accessible_aa() {
<HasLabel<T>>::verus_proof();
<ValidRole<T>>::verus_proof();
<KeyboardAccessible<T>>::verus_proof();
<NoOverflow<T>>::verus_proof();
}
}
}
fn creusot_proof() -> TokenStream {
quote! {
fn verify_accessible_aa() -> bool {
<HasLabel<T>>::creusot_proof() &&
<ValidRole<T>>::creusot_proof() &&
<KeyboardAccessible<T>>::creusot_proof() &&
<NoOverflow<T>>::creusot_proof()
}
}
}
}
}