automation_structures/connectives/
buffer.rs1use vstd::prelude::*;
8
9use crate::value_eq::ValueEq;
10
11verus! {
12
13pub open spec fn buffer_bounded<T>(values: Seq<T>, capacity: nat) -> bool {
15 values.len() <= capacity
16}
17
18pub proof fn exact_capacity_admitted<T>(values: Seq<T>, capacity: nat)
20 requires values.len() == capacity,
21 ensures buffer_bounded(values, capacity),
22{
23}
24
25pub open spec fn contains_up_to<T>(values: Seq<T>, end: int, value: T) -> bool {
27 exists|index: int| 0 <= index < end && index < values.len() && values[index] == value
28}
29
30pub open spec fn contains_value<T>(values: Seq<T>, value: T) -> bool {
32 contains_up_to(values, values.len() as int, value)
33}
34
35pub open spec fn all_distinct<T>(values: Seq<T>) -> bool {
37 forall|left: int, right: int|
38 0 <= left < values.len() && 0 <= right < values.len() && left != right
39 ==> #[trigger] values[left] != #[trigger] values[right]
40}
41
42pub proof fn lemma_contains_extend<T>(values: Seq<T>, end: int, value: T)
44 requires 0 <= end < values.len(),
45 ensures contains_up_to(values, end + 1, value)
46 == (contains_up_to(values, end, value) || values[end] == value),
47{
48 if contains_up_to(values, end + 1, value) {
49 let index = choose|index: int|
50 0 <= index < end + 1 && index < values.len() && values[index] == value;
51 assert(index < end || index == end);
52 }
53 if contains_up_to(values, end, value) {
54 let index = choose|index: int|
55 0 <= index < end && index < values.len() && values[index] == value;
56 assert(0 <= index < end + 1 && index < values.len());
57 }
58 if values[end] == value {
59 assert(0 <= end < end + 1 && end < values.len());
60 }
61}
62
63pub proof fn lemma_push_contains<T>(values: Seq<T>, added: T, value: T)
65 ensures contains_value(values.push(added), value)
66 == (contains_value(values, value) || value == added),
67{
68 let pushed = values.push(added);
69 if contains_value(pushed, value) {
70 let index = choose|index: int| 0 <= index < pushed.len() && pushed[index] == value;
71 if index < values.len() {
72 assert(pushed[index] == values[index]);
73 } else {
74 assert(index == values.len());
75 }
76 }
77 if contains_value(values, value) {
78 let index = choose|index: int| 0 <= index < values.len() && values[index] == value;
79 assert(pushed[index] == values[index]);
80 }
81 if value == added {
82 assert(pushed[values.len() as int] == value);
83 }
84}
85
86pub proof fn indexed_value_contained<T>(values: Seq<T>, index: int)
88 requires 0 <= index < values.len(),
89 ensures contains_value(values, values[index]),
90{
91 assert(0 <= index < values.len() && values[index] == values[index]);
92}
93
94pub proof fn contains_remove_distinct<T>(values: Seq<T>, removed: int, value: T)
96 requires
97 all_distinct(values),
98 0 <= removed < values.len(),
99 ensures
100 contains_value(values.remove(removed), value)
101 == (contains_value(values, value) && value != values[removed]),
102{
103 values.remove_ensures(removed);
104 let reduced = values.remove(removed);
105 if contains_value(reduced, value) {
106 let index = choose|index: int|
107 0 <= index < reduced.len() && reduced[index] == value;
108 let old_index = if index < removed { index } else { index + 1 };
109 assert(0 <= old_index < values.len());
110 assert(old_index != removed);
111 assert(reduced[index] == values[old_index]);
112 assert(contains_value(values, value));
113 if value == values[removed] {
114 assert(values[old_index] == values[removed]);
115 assert(false);
116 }
117 }
118 if contains_value(values, value) && value != values[removed] {
119 let old_index = choose|index: int|
120 0 <= index < values.len() && values[index] == value;
121 assert(old_index != removed);
122 let index = if old_index < removed { old_index } else { old_index - 1 };
123 assert(0 <= index < reduced.len());
124 assert(reduced[index] == values[old_index]);
125 }
126}
127
128pub struct Buffer<T> {
130 pub capacity: usize,
132 pub values: Vec<T>,
134}
135
136impl<T> Buffer<T> {
137 pub closed spec fn well_formed(&self) -> bool {
139 buffer_bounded(self.values@, self.capacity as nat)
140 }
141
142 pub fn new(capacity: usize) -> (buffer: Self)
144 ensures
145 buffer.well_formed(),
146 buffer.capacity == capacity,
147 buffer.values@.len() == 0,
148 {
149 Self { capacity, values: Vec::new() }
150 }
151
152 pub fn capacity(&self) -> (capacity: usize)
154 ensures capacity == self.capacity,
155 {
156 self.capacity
157 }
158
159 pub fn len(&self) -> (length: usize)
161 ensures length == self.values@.len(),
162 {
163 self.values.len()
164 }
165
166 pub fn is_empty(&self) -> (empty: bool)
168 ensures empty == (self.values@.len() == 0),
169 {
170 self.values.is_empty()
171 }
172
173 pub fn is_full(&self) -> (full: bool)
175 ensures full == (self.values@.len() == self.capacity),
176 {
177 self.values.len() == self.capacity
178 }
179
180 pub fn push(&mut self, value: T) -> (result: Result<(), T>)
186 requires old(self).well_formed(),
187 ensures
188 final(self).well_formed(),
189 final(self).capacity == old(self).capacity,
190 old(self).values@.len() < old(self).capacity ==> result is Ok,
191 old(self).values@.len() >= old(self).capacity ==> result == Err(value),
192 old(self).values@.len() < old(self).capacity ==>
193 final(self).values@ == old(self).values@.push(value),
194 old(self).values@.len() >= old(self).capacity ==>
195 final(self).values@ == old(self).values@,
196 {
197 if self.values.len() >= self.capacity { return Err(value); }
198 self.values.push(value);
199 Ok(())
200 }
201
202 pub fn pop(&mut self) -> (value: Option<T>)
204 requires old(self).well_formed(),
205 ensures
206 final(self).well_formed(),
207 final(self).capacity == old(self).capacity,
208 old(self).values@.len() == 0 ==> value is None,
209 old(self).values@.len() > 0 ==> value == Some(old(self).values@[0]),
210 old(self).values@.len() == 0 ==> final(self).values@ == old(self).values@,
211 old(self).values@.len() > 0 ==>
212 final(self).values@ == old(self).values@.skip(1),
213 all_distinct(old(self).values@) ==> all_distinct(final(self).values@),
214 {
215 if self.values.is_empty() { None } else { Some(self.values.remove(0)) }
216 }
217}
218
219pub fn retained_contains<T: ValueEq + Copy>(values: &Vec<T>, value: T) -> (present: bool)
221 ensures present == contains_value(values@, value),
222{
223 let mut index: usize = 0;
224 while index < values.len()
225 invariant
226 index <= values.len(),
227 !contains_up_to(values@, index as int, value),
228 decreases values.len() - index,
229 {
230 if values[index].value_eq(&value) {
231 assert(contains_value(values@, value));
232 return true;
233 }
234 proof { lemma_contains_extend(values@, index as int, value); }
235 index = index + 1;
236 }
237 false
238 }
239
240impl<T: ValueEq + Copy> Buffer<T> {
241 pub fn contains(&self, value: T) -> (present: bool)
243 ensures present == contains_value(self.values@, value),
244 {
245 retained_contains(&self.values, value)
246 }
247
248 pub fn push_unique(&mut self, value: T) -> (accepted: bool)
250 requires
251 old(self).well_formed(),
252 all_distinct(old(self).values@),
253 ensures
254 final(self).well_formed(),
255 all_distinct(final(self).values@),
256 final(self).capacity == old(self).capacity,
257 accepted == (old(self).values@.len() < old(self).capacity
258 && !contains_value(old(self).values@, value)),
259 accepted ==> final(self).values@ == old(self).values@.push(value),
260 !accepted ==> final(self).values@ == old(self).values@,
261 {
262 if self.values.len() >= self.capacity || self.contains(value) {
263 return false;
264 }
265 let ghost before = self.values@;
266 self.values.push(value);
267 proof {
268 assert(all_distinct(self.values@)) by {
269 assert forall|left: int, right: int|
270 0 <= left < self.values@.len()
271 && 0 <= right < self.values@.len()
272 && left != right
273 implies #[trigger] self.values@[left] != #[trigger] self.values@[right] by {
274 if left < before.len() && right < before.len() {
275 } else if left == before.len() && right < before.len() {
276 assert(self.values@[right] == before[right]);
277 assert(contains_value(before, before[right]));
278 } else if right == before.len() && left < before.len() {
279 assert(self.values@[left] == before[left]);
280 assert(contains_value(before, before[left]));
281 }
282 }
283 }
284 }
285 true
286 }
287
288 pub fn remove_value(&mut self, value: T) -> (removed: bool)
290 requires
291 old(self).well_formed(),
292 all_distinct(old(self).values@),
293 ensures
294 final(self).well_formed(),
295 all_distinct(final(self).values@),
296 final(self).capacity == old(self).capacity,
297 removed == contains_value(old(self).values@, value),
298 removed ==> exists|index: int|
299 0 <= index < old(self).values@.len()
300 && old(self).values@[index] == value
301 && final(self).values@ == old(self).values@.remove(index),
302 !removed ==> final(self).values@ == old(self).values@,
303 forall|candidate: T| #[trigger] contains_value(final(self).values@, candidate)
304 == (contains_value(old(self).values@, candidate) && candidate != value),
305 {
306 let ghost before = self.values@;
307 assert(before == old(self).values@);
308 assert(buffer_bounded(before, self.capacity as nat)) by {
309 reveal(Buffer::well_formed);
310 }
311 let mut index: usize = 0;
312 while index < self.values.len()
313 invariant
314 index <= self.values.len(),
315 self.values@ == before,
316 before == old(self).values@,
317 self.capacity == old(self).capacity,
318 buffer_bounded(before, self.capacity as nat),
319 all_distinct(before),
320 forall|prior: int| 0 <= prior < index ==>
321 before[prior] != value,
322 decreases self.values.len() - index,
323 {
324 if self.values[index].value_eq(&value) {
325 proof {
326 assert(before[index as int] == value);
327 indexed_value_contained(before, index as int);
328 assert(contains_value(before, value));
329 }
330 let _removed_value = self.values.remove(index);
331 assert(_removed_value == value);
332 proof { before.remove_ensures(index as int); }
333 assert(self.values@ == before.remove(index as int));
334 assert(self.values@.len() < before.len());
335 assert(self.well_formed()) by {
336 reveal(Buffer::well_formed);
337 reveal(buffer_bounded);
338 }
339 assert(all_distinct(self.values@)) by {
340 before.remove_ensures(index as int);
341 assert forall|left: int, right: int|
342 0 <= left < self.values@.len()
343 && 0 <= right < self.values@.len()
344 && left != right
345 implies #[trigger] self.values@[left] != #[trigger] self.values@[right] by {
346 let old_left = if left < index { left } else { left + 1 };
347 let old_right = if right < index { right } else { right + 1 };
348 assert(0 <= old_left < before.len());
349 assert(0 <= old_right < before.len());
350 assert(old_left != old_right);
351 assert(self.values@[left] == before[old_left]);
352 assert(self.values@[right] == before[old_right]);
353 }
354 }
355 assert forall|candidate: T|
356 #[trigger] contains_value(self.values@, candidate)
357 == (contains_value(before, candidate) && candidate != value) by {
358 contains_remove_distinct(before, index as int, candidate);
359 assert(before[index as int] == value);
360 }
361 assert(exists|old_index: int|
362 0 <= old_index < before.len()
363 && before[old_index] == value
364 && self.values@ == before.remove(old_index)) by {
365 assert(0 <= index as int);
366 assert((index as int) < before.len());
367 }
368 return true;
369 }
370 index = index + 1;
371 }
372 assert(!contains_value(before, value)) by {
373 if contains_value(before, value) {
374 let present = choose|present: int|
375 0 <= present < before.len() && before[present] == value;
376 assert(false);
377 }
378 }
379 false
380 }
381}
382
383}
384
385impl<T: core::fmt::Debug> core::fmt::Debug for Buffer<T> {
386 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387 formatter
388 .debug_struct("Buffer")
389 .field("capacity", &self.capacity)
390 .field("values", &self.values)
391 .finish()
392 }
393}