krabka_verified/restore_sidecar/
restore_producer_ids_strict.rs1#[cfg(creusot)]
2use super::{Int, invariant};
3use {
4 super::{RestoreAbortedTxn, RestoreSegmentExtent},
5 crate::log_index::{IndexEntry, OffsetEntry, TimeEntry},
6 creusot_std::prelude::*,
7};
8
9#[ensures(match result {
17 Some(frontier) => segment_base@ >= 0
18 && segment_end@ >= segment_base@
19 && frontier@ == segment_end@ - segment_base@
20 && frontier@ <= u32::MAX@,
21 None => segment_base@ < 0
22 || segment_end@ < segment_base@
23 || segment_end@ - segment_base@ > u32::MAX@,
24})]
25#[must_use]
26pub fn restore_index_frontier(segment_base: i64, segment_end: i64) -> Option<i64> {
27 if segment_base < 0 || segment_end < segment_base {
28 return None;
29 }
30 let relative = segment_end - segment_base;
31 if relative > i64::from(u32::MAX) {
32 None
33 } else {
34 Some(relative)
35 }
36}
37
38#[ensures(result == (relative_offset@ <= max_relative@
41 && position@ < log_bytes@
42 && match previous {
43 Some(IndexEntry { key: previous_relative, coordinate: previous_position }) =>
44 previous_relative@ < relative_offset@ && previous_position@ < position@,
45 None => true,
46 }))]
47#[must_use]
48pub fn restore_offset_index_entry_valid(
49 previous: Option<OffsetEntry>,
50 relative_offset: u32,
51 position: u32,
52 max_relative: i64,
53 log_bytes: u64,
54) -> bool {
55 i64::from(relative_offset) <= max_relative
56 && u64::from(position) < log_bytes
57 && match previous {
58 Some(IndexEntry {
59 key: previous_relative,
60 coordinate: previous_position,
61 }) => previous_relative < relative_offset && previous_position < position,
62 None => true,
63 }
64}
65
66#[ensures(result == (relative_offset@ <= max_relative@
76 && match previous {
77 Some(IndexEntry { key: previous_timestamp, coordinate: previous_relative }) =>
78 previous_timestamp@ <= timestamp@ && previous_relative@ < relative_offset@,
79 None => true,
80 }))]
81#[must_use]
82pub fn restore_time_index_entry_valid(
83 previous: Option<TimeEntry>,
84 timestamp: i64,
85 relative_offset: u32,
86 max_relative: i64,
87) -> bool {
88 i64::from(relative_offset) <= max_relative
89 && match previous {
90 Some(IndexEntry {
91 key: previous_timestamp,
92 coordinate: previous_relative,
93 }) => previous_timestamp <= timestamp && previous_relative < relative_offset,
94 None => true,
95 }
96}
97
98#[ensures(result == (entry.producer_id@ >= 0
110 && segment.base_offset@ >= 0
111 && entry.start_offset@ >= 0
112 && entry.start_offset@ <= entry.last_offset@
113 && segment.base_offset@ <= entry.last_offset@
114 && entry.last_offset@ <= segment.last_offset@
115 && match previous_last {
116 Some(previous) => previous@ < entry.last_offset@,
117 None => true,
118 }))]
119#[must_use]
120pub fn restore_txn_index_entry_valid(
121 previous_last: Option<i64>,
122 entry: RestoreAbortedTxn,
123 segment: RestoreSegmentExtent,
124) -> bool {
125 entry.producer_id >= 0
126 && segment.base_offset >= 0
127 && entry.start_offset >= 0
128 && entry.start_offset <= entry.last_offset
129 && segment.base_offset <= entry.last_offset
130 && entry.last_offset <= segment.last_offset
131 && !matches!(previous_last, Some(previous) if previous >= entry.last_offset)
132}
133
134#[ensures(result == (epoch@ >= 0
136 && segment_base@ >= 0
137 && segment_base@ <= start_offset@
138 && start_offset@ <= segment_end@
139 && match previous {
140 Some((previous_epoch, previous_start)) =>
141 previous_epoch@ < epoch@ && previous_start@ < start_offset@,
142 None => true,
143 }))]
144#[must_use]
145pub fn restore_leader_epoch_entry_valid(
146 previous: Option<(i32, i64)>,
147 epoch: i32,
148 start_offset: i64,
149 segment_base: i64,
150 segment_end: i64,
151) -> bool {
152 epoch >= 0
153 && segment_base >= 0
154 && segment_base <= start_offset
155 && start_offset <= segment_end
156 && match previous {
157 Some((previous_epoch, previous_start)) => {
158 previous_epoch < epoch && previous_start < start_offset
159 }
160 None => true,
161 }
162}
163
164#[ensures(result == (forall<i: Int> 1 <= i && i < [email protected]()
167 ==> producer_ids@[i - 1]@ < producer_ids@[i]@))]
168#[must_use]
169pub fn restore_producer_ids_strict(producer_ids: &[i64]) -> bool {
170 let mut index = 0usize;
171 #[invariant(index@ <= [email protected]())]
172 #[invariant(forall<i: Int> 1 <= i && i < index@
173 ==> producer_ids@[i - 1]@ < producer_ids@[i]@)]
174 #[variant([email protected]() - index@)]
175 while index < producer_ids.len() {
176 if index > 0
177 && let (Some(&previous), Some(¤t)) =
178 (producer_ids.get(index - 1), producer_ids.get(index))
179 && previous >= current
180 {
181 return false;
182 }
183 index += 1;
184 }
185 true
186}