1use vstd::prelude::*;
14
15verus! {
16
17pub open spec fn map_spec(position: int, start: int, old_end: int, new_end: int) -> int {
19 if position < start {
20 position
21 } else if position >= old_end {
22 new_end + (position - old_end)
23 } else {
24 start
25 }
26}
27
28pub fn map_position(position: usize, start: usize, old_end: usize, new_end: usize) -> (mapped: usize)
32 requires
33 start <= old_end,
34 position >= old_end ==> new_end + (position - old_end) <= usize::MAX,
35 ensures
36 mapped as int == map_spec(position as int, start as int, old_end as int, new_end as int),
37{
38 if position < start {
39 position
40 } else if position >= old_end {
41 new_end.saturating_add(position - old_end)
42 } else {
43 start
44 }
45}
46
47proof fn map_spec_monotone(a: int, b: int, start: int, old_end: int, new_end: int)
51 requires
52 start <= old_end,
53 start <= new_end,
54 a <= b,
55 ensures
56 map_spec(a, start, old_end, new_end) <= map_spec(b, start, old_end, new_end),
57{
58}
59
60proof fn map_spec_in_bounds(
62 position: int,
63 start: int,
64 old_end: int,
65 new_end: int,
66 old_len: int,
67 new_len: int,
68)
69 requires
70 0 <= start <= old_end <= old_len,
71 0 <= start <= new_end <= new_len,
72 0 <= position <= old_len,
73 new_len == old_len - (old_end - start) + (new_end - start),
74 ensures
75 0 <= map_spec(position, start, old_end, new_end) <= new_len,
76{
77}
78
79}
80
81verus! {
82
83pub open spec fn to_ints(edits: Seq<(usize, usize)>) -> Seq<(int, int)> {
85 edits.map_values(|pair: (usize, usize)| (pair.0 as int, pair.1 as int))
86}
87
88pub open spec fn batch_ok(edits: Seq<(int, int)>, len: int) -> bool {
90 forall|i: int| #![trigger edits[i]] 0 <= i < edits.len() ==> {
91 let (s, e) = edits[i];
92 &&& 0 <= s <= e <= len
93 &&& i + 1 < edits.len() ==> {
94 let (s2, _) = edits[i + 1];
95 &&& s < s2
96 &&& e <= s2
97 }
98 }
99}
100
101proof fn insert_preserves(
104 edits: Seq<(usize, usize)>,
105 pre: Seq<(usize, (usize, usize))>,
106 j: usize,
107 i: usize,
108 pair: (usize, usize),
109)
110 requires
111 j as int <= pre.len(),
112 pre.len() == i as int,
113 (i as int) < edits.len(),
114 pair == edits[i as int],
115 forall|k: int| #![trigger pre[k]] 0 <= k < pre.len() ==> {
116 &&& (pre[k].0 as int) < i as int
117 &&& pre[k].1 == edits[pre[k].0 as int]
118 },
119 forall|a: int, b: int| #![trigger pre[a], pre[b]]
120 0 <= a < b < pre.len() ==> pre[a].0 != pre[b].0,
121 forall|k: int| #![trigger pre[k]] 0 <= k < pre.len() - 1 ==>
122 pre[k].1.0 <= pre[k + 1].1.0,
123 j > 0 ==> pre[j as int - 1].1.0 as int <= pair.0 as int,
124 forall|p: int| #![trigger pre[p]] j as int <= p < pre.len() ==>
125 pre[p].1.0 as int > pair.0 as int,
126 ensures
127 ({
128 let post = pre.insert(j as int, (i, pair));
129 &&& post.len() == i as int + 1
130 &&& forall|k: int| #![trigger post[k]] 0 <= k < post.len() ==> {
131 &&& (post[k].0 as int) < i as int + 1
132 &&& post[k].1 == edits[post[k].0 as int]
133 }
134 &&& forall|a: int, b: int| #![trigger post[a], post[b]]
135 0 <= a < b < post.len() ==> post[a].0 != post[b].0
136 &&& forall|k: int| #![trigger post[k]] 0 <= k < post.len() - 1 ==>
137 post[k].1.0 <= post[k + 1].1.0
138 }),
139{
140 let post = pre.insert(j as int, (i, pair));
141 assert forall|k: int| #![trigger post[k]] 0 <= k < post.len() implies {
142 &&& (post[k].0 as int) < i as int + 1
143 &&& post[k].1 == edits[post[k].0 as int]
144 } by {
145 if k == j as int {
146 assert(post[k] == (i, pair));
147 } else if k < j as int {
148 assert(post[k] == pre[k]);
149 } else {
150 assert(post[k] == pre[k - 1]);
151 }
152 }
153 assert forall|a: int, b: int| #![trigger post[a], post[b]]
154 0 <= a < b < post.len() implies post[a].0 != post[b].0 by {
155 if a == j as int {
156 assert(post[b] == pre[b - 1]);
157 } else if b == j as int {
158 assert(post[a] == pre[a]);
159 } else {
160 assert(post[a] == if a < j as int { pre[a] } else { pre[a - 1] });
161 assert(post[b] == if b < j as int { pre[b] } else { pre[b - 1] });
162 }
163 }
164 assert forall|k: int| #![trigger post[k]] 0 <= k < post.len() - 1 implies
165 post[k].1.0 <= post[k + 1].1.0 by {
166 if k + 1 < j as int {
167 assert(post[k] == pre[k]);
168 assert(post[k + 1] == pre[k + 1]);
169 } else if k + 1 == j as int {
170 assert(post[k] == pre[k]);
171 assert(post[k + 1] == (i, pair));
172 } else if k == j as int {
174 assert(post[k] == (i, pair));
175 assert(post[k + 1] == pre[k]);
176 } else {
178 assert(post[k] == pre[k - 1]);
179 assert(post[k + 1] == pre[k]);
180 }
181 }
182}
183
184#[allow(clippy::ptr_arg, clippy::needless_range_loop)]
189fn sort_by_start(edits: &Vec<(usize, usize)>) -> (out: Vec<(usize, (usize, usize))>)
190 ensures
191 out@.len() == edits@.len(),
192 forall|k: int| #![trigger out@[k]] 0 <= k < out@.len() ==> {
194 &&& (out@[k].0 as int) < edits@.len()
195 &&& out@[k].1 == edits@[out@[k].0 as int]
196 },
197 forall|a: int, b: int| #![trigger out@[a], out@[b]]
199 0 <= a < b < out@.len() ==> out@[a].0 != out@[b].0,
200 forall|k: int| #![trigger out@[k]] 0 <= k < out@.len() - 1 ==>
202 out@[k].1.0 <= out@[k + 1].1.0,
203{
204 let mut out: Vec<(usize, (usize, usize))> = Vec::new();
205 for i in 0..edits.len()
206 invariant
207 i <= edits.len(),
208 out@.len() == i as int,
209 forall|k: int| #![trigger out@[k]] 0 <= k < out@.len() ==> {
210 &&& (out@[k].0 as int) < i as int
211 &&& out@[k].1 == edits@[out@[k].0 as int]
212 },
213 forall|a: int, b: int| #![trigger out@[a], out@[b]]
214 0 <= a < b < out@.len() ==> out@[a].0 != out@[b].0,
215 forall|k: int| #![trigger out@[k]] 0 <= k < out@.len() - 1 ==>
216 out@[k].1.0 <= out@[k + 1].1.0,
217 {
218 let pair = edits[i];
219 let s = pair.0;
220 let ghost pre = out@;
221 let mut j = out.len();
223 while j > 0 && out[j - 1].1.0 > s
224 invariant
225 j <= out.len(),
226 out@ == pre,
227 forall|p: int| #![trigger out@[p]] j <= p < out@.len() ==>
228 out@[p].1.0 > s as int,
229 decreases j,
230 {
231 j -= 1;
232 }
233 out.insert(j, (i, pair));
234 proof {
235 insert_preserves(edits@, pre, j, i, pair);
236 }
237 }
238 out
239}
240
241#[allow(clippy::result_unit_err, clippy::needless_range_loop)]
247pub fn check_batch(len: usize, edits: Vec<(usize, usize)>) -> (out: Result<Vec<(usize, usize)>, ()>)
248 ensures
249 out.is_ok() ==> batch_ok(to_ints(out.unwrap()@), len as int),
250 out.is_err() ==> {
251 ||| exists|i: int| #![trigger edits@[i]] 0 <= i < edits@.len() && {
252 let (s, e) = edits@[i]; !(0 <= s <= e <= len as int)
253 }
254 ||| exists|i: int, j: int| #![trigger edits@[i], edits@[j]]
255 0 <= i < edits@.len() && 0 <= j < edits@.len() && i != j && {
256 let (si, ei) = edits@[i]; let (sj, _ej) = edits@[j];
257 &&& si == sj || (si <= sj && ei > sj)
258 }
259 },
260{
261 let sorted = sort_by_start(&edits);
262 let n = sorted.len();
263 let mut i = 0usize;
264 while i < n
266 invariant
267 0 <= i <= n,
268 n == sorted@.len(),
269 forall|k: int| #![trigger sorted@[k]] 0 <= k < sorted@.len() ==> {
271 &&& (sorted@[k].0 as int) < edits@.len()
272 &&& sorted@[k].1 == edits@[sorted@[k].0 as int]
273 },
274 forall|a: int, b: int| #![trigger sorted@[a], sorted@[b]]
275 0 <= a < b < sorted@.len() ==> sorted@[a].0 != sorted@[b].0,
276 forall|k: int| #![trigger sorted@[k]] 0 <= k < sorted@.len() - 1 ==>
277 sorted@[k].1.0 <= sorted@[k + 1].1.0,
278 forall|k: int| #![trigger sorted@[k]] 0 <= k < i as int ==> {
279 let (sk, ek) = sorted@[k].1;
280 &&& 0 <= sk as int
281 &&& sk <= ek
282 &&& ek <= len
283 },
284 forall|k: int| #![trigger sorted@[k]] 0 <= k < i as int - 1 ==> {
285 let (sk, ek) = sorted@[k].1;
286 let (sk1, _ek1) = sorted@[k + 1].1;
287 &&& sk < sk1
288 &&& ek <= sk1
289 },
290 decreases n - i,
291 {
292 let (s, e) = sorted[i].1;
293 if !(s <= e && e <= len) {
294 proof {
295 let w = sorted@[i as int].0 as int;
296 assert(0 <= w < edits@.len());
297 assert(edits@[w] == (s, e));
298 assert(!(0 <= s as int && s <= e && e <= len));
299 assert(exists|i2: int| #![trigger edits@[i2]] 0 <= i2 < edits@.len() && {
300 let (s2, e2) = edits@[i2]; !(0 <= s2 <= e2 <= len as int)
301 });
302 }
303 return Err(());
304 }
305 if i > 0 {
306 let (sp, ep) = sorted[i - 1].1;
307 if sp == s || ep > s {
308 proof {
309 let a = sorted@[i as int - 1].0 as int;
310 let b = sorted@[i as int].0 as int;
311 assert(0 <= a < edits@.len());
312 assert(0 <= b < edits@.len());
313 assert(a != b);
314 assert(edits@[a] == (sp, ep));
315 assert(edits@[b] == (s, e));
316 assert(sp as int <= s as int);
318 assert(exists|i2: int, j2: int| #![trigger edits@[i2], edits@[j2]]
319 0 <= i2 < edits@.len() && 0 <= j2 < edits@.len() && i2 != j2 && {
320 let (si, ei) = edits@[i2]; let (sj, _ej) = edits@[j2];
321 &&& si == sj || (si <= sj && ei > sj)
322 });
323 }
324 return Err(());
325 }
326 }
327 i += 1;
328 }
329 let mut result: Vec<(usize, usize)> = Vec::new();
331 let mut k = 0usize;
332 while k < n
333 invariant
334 0 <= k <= n,
335 n == sorted@.len(),
336 result@.len() == k as int,
337 forall|p: int| #![trigger result@[p]] 0 <= p < k as int ==>
338 result@[p] == sorted@[p].1,
339 decreases n - k,
340 {
341 result.push(sorted[k].1);
342 k += 1;
343 }
344 proof {
345 let ri = to_ints(result@);
346 assert forall|p: int| #![trigger ri[p]] 0 <= p < ri.len() implies {
347 let (s, e) = ri[p];
348 &&& 0 <= s <= e <= len as int
349 &&& p + 1 < ri.len() ==> {
350 let (s2, _) = ri[p + 1];
351 &&& s < s2 &&& e <= s2
352 }
353 } by {
354 assert(result@[p] == sorted@[p].1);
355 if p + 1 < ri.len() {
356 assert(result@[p + 1] == sorted@[p + 1].1);
357 }
358 }
359 assert(batch_ok(ri, len as int));
360 }
361 Ok(result)
362}
363
364}