krabka_verified/
delivery.rs1#[cfg(creusot)]
4use creusot_std::prelude::{Int, logic};
5use creusot_std::prelude::{ensures, requires};
6
7#[ensures(result == (!scheduled || (uncertainty_ms@ >= 0
13 && activation_ms@ + uncertainty_ms@ <= i64::MAX@
14 && activation_ms@ + uncertainty_ms@ <= now_ms@)))]
15#[must_use]
16pub fn scheduled_delivery_visible(
17 scheduled: bool,
18 uncertainty_ms: i64,
19 activation_ms: i64,
20 now_ms: i64,
21) -> bool {
22 if !scheduled {
23 return true;
24 }
25 if uncertainty_ms < 0 {
26 return false;
27 }
28 let Some(deadline_ms) = activation_ms.checked_add(uncertainty_ms) else {
29 return false;
30 };
31 deadline_ms <= now_ms
32}
33
34#[cfg(creusot)]
36#[cfg_attr(test, mutants::skip)]
37#[logic]
38fn clamp_to(value: Int, low: Int, high: Int) -> Int {
39 pearlite! { if value < low { low } else if value > high { high } else { value } }
40}
41
42#[requires(log_start@ <= log_end@)]
50#[ensures(result@ == [email protected](clamp_to(current@, log_start@, log_end@)).min(log_end@))]
51#[ensures(log_start@ <= result@ && result@ <= log_end@)]
52#[ensures(current@ <= candidate@ && log_start@ <= candidate@ && candidate@ <= log_end@
53 ==> result@ == candidate@)]
54#[must_use]
55pub fn delivery_watermark_advance(
56 log_start: i64,
57 current: i64,
58 candidate: i64,
59 log_end: i64,
60) -> i64 {
61 let bounded_current = if current < log_start {
62 log_start
63 } else if current > log_end {
64 log_end
65 } else {
66 current
67 };
68 if candidate <= bounded_current {
69 bounded_current
70 } else if candidate >= log_end {
71 log_end
72 } else {
73 candidate
74 }
75}
76
77#[ensures(result.0 == (low@ <= last_high@ + 1))]
83#[ensures(result.1@ >= last_high@ && result.1@ >= high@)]
84#[ensures(result.1@ == last_high@ || result.1@ == high@)]
85#[must_use]
86pub fn coalesce_delivery_range(last_high: i64, low: i64, high: i64) -> (bool, i64) {
87 let merge = if low <= last_high {
88 true
89 } else {
90 low == last_high + 1
92 };
93 let merged_high = if high > last_high { high } else { last_high };
94 (merge, merged_high)
95}
96
97#[cfg(test)]
98mod tests {
99 use {
100 super::{coalesce_delivery_range, delivery_watermark_advance, scheduled_delivery_visible},
101 assert2::assert,
102 };
103
104 #[test]
105 fn visibility_never_ignores_deadline_or_overflow() {
106 assert!(scheduled_delivery_visible(false, 250, i64::MAX, i64::MIN));
107 assert!(!scheduled_delivery_visible(true, -1, 10_000, 10_000));
108 assert!(scheduled_delivery_visible(true, 0, 10_000, 10_000));
109 assert!(!scheduled_delivery_visible(true, 250, 10_000, 10_249));
110 assert!(scheduled_delivery_visible(true, 250, 10_000, 10_250));
111 assert!(!scheduled_delivery_visible(true, 1, i64::MAX, i64::MAX));
112 }
113
114 #[test]
115 fn watermark_step_is_monotonic_inside_live_bounds() {
116 assert!(delivery_watermark_advance(5, 7, 9, 10) == 9);
117 assert!(delivery_watermark_advance(5, 7, 6, 10) == 7);
118 assert!(delivery_watermark_advance(5, 7, 12, 10) == 10);
119 assert!(delivery_watermark_advance(5, 2, 8, 10) == 8);
120 assert!(delivery_watermark_advance(5, 2, 4, 10) == 5);
121 assert!(delivery_watermark_advance(5, 12, 12, 10) == 10);
122 }
123
124 #[test]
125 fn range_step_merges_only_overlap_or_adjacency() {
126 assert!(coalesce_delivery_range(4, 5, 9) == (true, 9));
127 assert!(coalesce_delivery_range(9, 6, 7) == (true, 9));
128 assert!(coalesce_delivery_range(9, 11, 12) == (false, 12));
129 assert!(coalesce_delivery_range(i64::MAX, i64::MAX, i64::MAX) == (true, i64::MAX));
130 }
131}