automation_structures/
connective_api.rs1use vstd::prelude::*;
8
9verus! {
10
11pub struct Accumulator<T: Copy> {
13 #[allow(dead_code)]
14 original: Ghost<Seq<T>>,
15 accumulated: Vec<T>,
16 pending: Vec<T>,
17}
18
19impl<T: Copy> Accumulator<T> {
20 pub closed spec fn well_formed(&self) -> bool {
21 crate::connectives::accumulator::carries(
22 self.original@,
23 self.accumulated@,
24 self.pending@,
25 )
26 }
27
28 pub fn new(values: Vec<T>) -> (accumulator: Self)
30 ensures accumulator.well_formed(),
31 {
32 let ghost original = values@;
33 Self { original: Ghost(original), accumulated: Vec::new(), pending: values }
34 }
35
36 pub fn accumulated_len(&self) -> usize { self.accumulated.len() }
38
39 pub fn pending_len(&self) -> usize { self.pending.len() }
41
42 pub fn is_complete(&self) -> bool { self.pending.is_empty() }
44
45 #[expect(clippy::indexing_slicing, reason = "the branch proves the accumulated index is in bounds")]
47 pub fn accumulated(&self, index: usize) -> Option<T> {
48 if index < self.accumulated.len() { Some(self.accumulated[index]) } else { None }
49 }
50
51 #[expect(clippy::indexing_slicing, reason = "the branch proves the pending index is in bounds")]
53 pub fn pending(&self, index: usize) -> Option<T> {
54 if index < self.pending.len() { Some(self.pending[index]) } else { None }
55 }
56
57 #[expect(clippy::indexing_slicing, reason = "the nonempty guard proves the pending head exists")]
59 pub fn advance(&mut self) -> (value: Option<T>)
60 requires old(self).well_formed(),
61 ensures final(self).well_formed(),
62 {
63 if self.pending.is_empty() { return None; }
64 let ghost old_accumulated = self.accumulated@;
65 let ghost old_pending = self.pending@;
66 let value = self.pending[0];
67 self.pending.remove(0);
68 self.accumulated.push(value);
69 proof {
70 crate::connectives::accumulator::consume_pending_head(
71 old_accumulated,
72 old_pending,
73 );
74 assert(self.accumulated@ =~= old_accumulated.push(old_pending[0]));
75 assert(self.pending@ =~= old_pending.skip(1));
76 }
77 Some(value)
78 }
79}
80
81pub struct Buffer<T> {
83 capacity: usize,
84 values: Vec<T>,
85}
86
87impl<T> Buffer<T> {
88 pub closed spec fn well_formed(&self) -> bool {
89 crate::connectives::buffer::buffer_bounded(self.values@, self.capacity as nat)
90 }
91
92 pub fn new(capacity: usize) -> (buffer: Self)
94 ensures buffer.well_formed(),
95 {
96 Self { capacity, values: Vec::new() }
97 }
98
99 pub fn capacity(&self) -> usize { self.capacity }
101
102 pub fn len(&self) -> usize { self.values.len() }
104
105 pub fn is_empty(&self) -> bool { self.values.is_empty() }
107
108 pub fn is_full(&self) -> bool { self.values.len() == self.capacity }
110
111 pub fn push(&mut self, value: T) -> (result: Result<(), T>)
113 requires old(self).well_formed(),
114 ensures final(self).well_formed(),
115 {
116 if self.values.len() >= self.capacity { return Err(value); }
117 self.values.push(value);
118 Ok(())
119 }
120
121 pub fn pop(&mut self) -> (value: Option<T>)
123 requires old(self).well_formed(),
124 ensures final(self).well_formed(),
125 {
126 if self.values.is_empty() { None } else { Some(self.values.remove(0)) }
127 }
128}
129
130#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
132pub struct Counter {
133 value: u64,
134}
135
136impl Counter {
137 pub fn new(value: u64) -> (counter: Self) { Self { value } }
139
140 pub fn value(&self) -> u64 { self.value }
142
143 #[must_use]
145 pub fn try_increment(&mut self) -> (accepted: bool) {
146 if self.value == u64::MAX { return false; }
147 self.value = self.value + 1;
148 true
149 }
150
151 #[must_use]
153 pub fn try_decrement(&mut self) -> (accepted: bool) {
154 if self.value == 0 { return false; }
155 self.value = self.value - 1;
156 true
157 }
158}
159
160#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
162pub struct Marker {
163 marked: bool,
164}
165
166impl Marker {
167 pub fn new(marked: bool) -> (marker: Self) { Self { marked } }
169
170 pub fn is_marked(&self) -> bool { self.marked }
172
173 pub fn set(&mut self) -> (changed: bool) {
175 let changed = !self.marked;
176 self.marked = true;
177 changed
178 }
179
180 pub fn clear(&mut self) -> (changed: bool) {
182 let changed = self.marked;
183 self.marked = false;
184 changed
185 }
186}
187
188pub fn projection_consistent(projected: bool, source: bool) -> (consistent: bool)
190 ensures consistent == crate::connectives::projection::membership_consistent(projected, source),
191{
192 projected == source
193}
194
195pub fn strictly_before(left: usize, right: usize) -> (ordered: bool) {
197 crate::connectives::ordering_pass::is_strictly_before(left, right)
198}
199
200}
201
202impl<T: Copy + core::fmt::Debug> core::fmt::Debug for Accumulator<T> {
203 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
204 formatter
205 .debug_struct("Accumulator")
206 .field("accumulated", &self.accumulated)
207 .field("pending", &self.pending)
208 .finish()
209 }
210}
211
212impl<T: core::fmt::Debug> core::fmt::Debug for Buffer<T> {
213 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
214 formatter
215 .debug_struct("Buffer")
216 .field("capacity", &self.capacity)
217 .field("values", &self.values)
218 .finish()
219 }
220}