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 struct Buffer<T> {
96 pub capacity: usize,
98 pub values: Vec<T>,
100}
101
102impl<T> Buffer<T> {
103 pub closed spec fn well_formed(&self) -> bool {
105 buffer_bounded(self.values@, self.capacity as nat)
106 }
107
108 pub fn new(capacity: usize) -> (buffer: Self)
110 ensures
111 buffer.well_formed(),
112 buffer.capacity == capacity,
113 buffer.values@.len() == 0,
114 {
115 Self { capacity, values: Vec::new() }
116 }
117
118 pub fn capacity(&self) -> (capacity: usize)
120 ensures capacity == self.capacity,
121 {
122 self.capacity
123 }
124
125 pub fn len(&self) -> (length: usize)
127 ensures length == self.values@.len(),
128 {
129 self.values.len()
130 }
131
132 pub fn is_empty(&self) -> (empty: bool)
134 ensures empty == (self.values@.len() == 0),
135 {
136 self.values.is_empty()
137 }
138
139 pub fn is_full(&self) -> (full: bool)
141 ensures full == (self.values@.len() == self.capacity),
142 {
143 self.values.len() == self.capacity
144 }
145
146 pub fn push(&mut self, value: T) -> (result: Result<(), T>)
152 requires old(self).well_formed(),
153 ensures
154 final(self).well_formed(),
155 final(self).capacity == old(self).capacity,
156 old(self).values@.len() < old(self).capacity ==>
157 final(self).values@ == old(self).values@.push(value),
158 old(self).values@.len() >= old(self).capacity ==>
159 final(self).values@ == old(self).values@,
160 {
161 if self.values.len() >= self.capacity { return Err(value); }
162 self.values.push(value);
163 Ok(())
164 }
165
166 pub fn pop(&mut self) -> (value: Option<T>)
168 requires old(self).well_formed(),
169 ensures
170 final(self).well_formed(),
171 final(self).capacity == old(self).capacity,
172 old(self).values@.len() == 0 ==> final(self).values@ == old(self).values@,
173 old(self).values@.len() > 0 ==>
174 final(self).values@ == old(self).values@.skip(1),
175 all_distinct(old(self).values@) ==> all_distinct(final(self).values@),
176 {
177 if self.values.is_empty() { None } else { Some(self.values.remove(0)) }
178 }
179}
180
181pub fn retained_contains<T: ValueEq + Copy>(values: &Vec<T>, value: T) -> (present: bool)
183 ensures present == contains_value(values@, value),
184{
185 let mut index: usize = 0;
186 while index < values.len()
187 invariant
188 index <= values.len(),
189 !contains_up_to(values@, index as int, value),
190 decreases values.len() - index,
191 {
192 if values[index].value_eq(&value) {
193 assert(contains_value(values@, value));
194 return true;
195 }
196 proof { lemma_contains_extend(values@, index as int, value); }
197 index = index + 1;
198 }
199 false
200 }
201
202impl<T: ValueEq + Copy> Buffer<T> {
203 pub fn contains(&self, value: T) -> (present: bool)
205 ensures present == contains_value(self.values@, value),
206 {
207 retained_contains(&self.values, value)
208 }
209
210 fn without_value(values: &Vec<T>, value: T) -> (out: Vec<T>)
211 requires all_distinct(values@),
212 ensures
213 all_distinct(out@),
214 out@.len() <= values@.len(),
215 forall|candidate: T| #[trigger] contains_value(out@, candidate)
216 == (contains_value(values@, candidate) && candidate != value),
217 {
218 let mut out = Vec::new();
219 let mut index: usize = 0;
220 while index < values.len()
221 invariant
222 index <= values.len(),
223 all_distinct(values@),
224 all_distinct(out@),
225 out@.len() <= index,
226 forall|candidate: T| #[trigger] contains_value(out@, candidate)
227 == (contains_up_to(values@, index as int, candidate)
228 && candidate != value),
229 decreases values.len() - index,
230 {
231 let current = values[index];
232 let ghost before = out@;
233 if !current.value_eq(&value) {
234 assert(!contains_value(before, current)) by {
235 if contains_value(before, current) {
236 assert(contains_up_to(values@, index as int, current));
237 let prior = choose|prior: int|
238 0 <= prior < index as int
239 && prior < values@.len()
240 && values@[prior] == current;
241 assert(values@[prior] != values@[index as int]);
242 }
243 }
244 out.push(current);
245 assert(all_distinct(out@)) by {
246 assert forall|left: int, right: int|
247 0 <= left < out@.len()
248 && 0 <= right < out@.len()
249 && left != right
250 implies #[trigger] out@[left] != #[trigger] out@[right] by {
251 if left < before.len() && right < before.len() {
252 } else if left == before.len() && right < before.len() {
253 assert(out@[right] == before[right]);
254 assert(contains_value(before, before[right]));
255 } else if right == before.len() && left < before.len() {
256 assert(out@[left] == before[left]);
257 assert(contains_value(before, before[left]));
258 }
259 }
260 }
261 }
262 assert forall|candidate: T| #[trigger] contains_value(out@, candidate)
263 == (contains_up_to(values@, index as int + 1, candidate)
264 && candidate != value) by {
265 lemma_contains_extend(values@, index as int, candidate);
266 if current != value {
267 if out@ != before {
268 lemma_push_contains(before, current, candidate);
269 }
270 }
271 }
272 index = index + 1;
273 }
274 out
275 }
276
277 pub fn push_unique(&mut self, value: T) -> (accepted: bool)
279 requires
280 old(self).well_formed(),
281 all_distinct(old(self).values@),
282 ensures
283 final(self).well_formed(),
284 all_distinct(final(self).values@),
285 final(self).capacity == old(self).capacity,
286 accepted == (old(self).values@.len() < old(self).capacity
287 && !contains_value(old(self).values@, value)),
288 accepted ==> final(self).values@ == old(self).values@.push(value),
289 !accepted ==> final(self).values@ == old(self).values@,
290 {
291 if self.values.len() >= self.capacity || self.contains(value) {
292 return false;
293 }
294 let ghost before = self.values@;
295 self.values.push(value);
296 proof {
297 assert(all_distinct(self.values@)) by {
298 assert forall|left: int, right: int|
299 0 <= left < self.values@.len()
300 && 0 <= right < self.values@.len()
301 && left != right
302 implies #[trigger] self.values@[left] != #[trigger] self.values@[right] by {
303 if left < before.len() && right < before.len() {
304 } else if left == before.len() && right < before.len() {
305 assert(self.values@[right] == before[right]);
306 assert(contains_value(before, before[right]));
307 } else if right == before.len() && left < before.len() {
308 assert(self.values@[left] == before[left]);
309 assert(contains_value(before, before[left]));
310 }
311 }
312 }
313 }
314 true
315 }
316
317 pub fn remove_value(&mut self, value: T) -> (removed: bool)
319 requires
320 old(self).well_formed(),
321 all_distinct(old(self).values@),
322 ensures
323 final(self).well_formed(),
324 all_distinct(final(self).values@),
325 final(self).capacity == old(self).capacity,
326 removed == contains_value(old(self).values@, value),
327 forall|candidate: T| #[trigger] contains_value(final(self).values@, candidate)
328 == (contains_value(old(self).values@, candidate) && candidate != value),
329 {
330 let removed = self.contains(value);
331 if removed {
332 self.values = Self::without_value(&self.values, value);
333 }
334 removed
335 }
336}
337
338}
339
340impl<T: core::fmt::Debug> core::fmt::Debug for Buffer<T> {
341 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
342 formatter
343 .debug_struct("Buffer")
344 .field("capacity", &self.capacity)
345 .field("values", &self.values)
346 .finish()
347 }
348}