Skip to main content

automation_structures/
connective_api.rs

1//! Checked public entry points for reusable connective roles.
2//!
3//! Connectives retain or relate the state passed between structures. Their
4//! checked facades keep the state carrier private, so ordinary Rust code
5//! cannot bypass a connective's invariant.
6
7use vstd::prelude::*;
8
9use crate::connectives::accumulator::Accumulator as AccumulatorCarrier;
10use crate::connectives::buffer::Buffer as BufferCarrier;
11use crate::connectives::counter::Counter as CounterCarrier;
12use crate::connectives::marker::Marker as MarkerCarrier;
13use crate::value_eq::ValueEq;
14
15verus! {
16
17/// An ordered partial result paired with its pending suffix.
18///
19/// `Accumulator` preserves the original order while values move from the
20/// pending suffix into the accumulated prefix.
21///
22/// # Examples
23///
24/// ```rust
25/// use automation_structures::Accumulator;
26///
27/// let mut values = Accumulator::new(vec![10, 20]);
28/// assert_eq!(values.advance(), Some(10));
29/// assert_eq!(values.accumulated_iter().collect::<Vec<_>>(), vec![&10]);
30/// assert_eq!(values.pending_iter().collect::<Vec<_>>(), vec![&20]);
31/// ```
32pub struct Accumulator<T: Copy> {
33    inner: AccumulatorCarrier<T>,
34}
35
36impl<T: Copy> Accumulator<T> {
37    /// Whether the owner reconstructs one complete ordered sequence.
38    pub closed spec fn well_formed(&self) -> bool {
39        self.inner.well_formed()
40    }
41
42    /// Whether no values remain in the pending suffix.
43    pub closed spec fn complete(&self) -> bool {
44        self.inner.pending@.len() == 0
45    }
46
47    /// Total logical length of the accumulated prefix and pending suffix.
48    pub closed spec fn total_len(&self) -> nat {
49        self.inner.accumulated@.len() + self.inner.pending@.len()
50    }
51
52    /// Construct an accumulator with an empty consumed prefix.
53    pub fn new(values: Vec<T>) -> (accumulator: Self)
54        ensures accumulator.well_formed(),
55    {
56        Self { inner: AccumulatorCarrier::new(values) }
57    }
58
59    /// Construct an accumulator whose supplied prefix is already incorporated.
60    pub fn from_accumulated(values: Vec<T>) -> (accumulator: Self)
61        ensures
62            accumulator.well_formed(),
63            accumulator.complete(),
64    {
65        Self { inner: AccumulatorCarrier::from_accumulated(values) }
66    }
67
68    /// Total number of values across both segments when representable by `usize`.
69    pub fn checked_len(&self) -> Option<usize> {
70        self.inner
71            .accumulated_len()
72            .checked_add(self.inner.pending_len())
73    }
74
75    /// Whether both segments are empty.
76    pub fn is_empty(&self) -> bool {
77        self.inner.accumulated_len() == 0 && self.inner.pending_len() == 0
78    }
79
80    /// Number of values already accumulated.
81    pub fn accumulated_len(&self) -> usize { self.inner.accumulated_len() }
82
83    /// Number of values still pending.
84    pub fn pending_len(&self) -> usize { self.inner.pending_len() }
85
86    /// Whether no values remain pending.
87    pub fn is_complete(&self) -> (complete: bool)
88        ensures complete == self.complete(),
89    {
90        self.inner.is_complete()
91    }
92
93    /// Read one accumulated value by original order.
94    pub fn accumulated(&self, index: usize) -> Option<T> { self.inner.accumulated(index) }
95
96    /// Read one pending value by original order.
97    pub fn pending(&self, index: usize) -> Option<T> { self.inner.pending(index) }
98
99    /// Move the next pending value into the accumulated prefix.
100    pub fn advance(&mut self) -> (value: Option<T>)
101        requires old(self).well_formed(),
102        ensures final(self).well_formed(),
103    {
104        self.inner.advance()
105    }
106
107    /// Append one value when the pending suffix is empty.
108    ///
109    /// # Errors
110    ///
111    /// Returns the supplied value unchanged while pending values remain.
112    pub fn try_append(&mut self, value: T) -> (result: Result<(), T>)
113        requires old(self).well_formed(),
114        ensures final(self).well_formed(),
115    {
116        if !self.inner.is_complete() { return Err(value); }
117        self.inner.append(value);
118        Ok(())
119    }
120}
121
122/// A bounded first-in, first-out connective.
123///
124/// Capacity and contents remain private; mutation is possible only through
125/// the checked FIFO operations.
126///
127/// # Examples
128///
129/// ```rust
130/// use automation_structures::Buffer;
131///
132/// let mut buffer = Buffer::new(2);
133/// assert_eq!(buffer.push("first"), Ok(()));
134/// assert_eq!(buffer.push("second"), Ok(()));
135/// assert_eq!(buffer.push("full"), Err("full"));
136/// assert_eq!(buffer.pop(), Some("first"));
137/// ```
138pub struct Buffer<T> {
139    inner: BufferCarrier<T>,
140}
141
142impl<T> Buffer<T> {
143    /// Logical FIFO contents used by proof consumers.
144    pub closed spec fn retained(&self) -> Seq<T> {
145        self.inner.values@
146    }
147
148    /// Logical capacity used by proof consumers.
149    pub closed spec fn admitted_capacity(&self) -> nat {
150        self.inner.capacity as nat
151    }
152
153    /// Whether a logical value occurs in the retained FIFO contents.
154    pub closed spec fn contains_retained(&self, value: T) -> bool {
155        crate::connectives::buffer::contains_value(self.inner.values@, value)
156    }
157
158    /// Whether the retained values fit within the configured capacity.
159    pub closed spec fn well_formed(&self) -> bool {
160        self.inner.well_formed()
161    }
162
163    /// Whether every retained value occurs at most once.
164    pub closed spec fn distinct(&self) -> bool {
165        crate::connectives::buffer::all_distinct(self.inner.values@)
166    }
167
168    /// Construct an empty FIFO with a fixed capacity.
169    pub fn new(capacity: usize) -> (buffer: Self)
170        ensures
171            buffer.well_formed(),
172            buffer.distinct(),
173            buffer.admitted_capacity() == capacity as nat,
174            buffer.retained() == Seq::<T>::empty(),
175            forall|value: T| !buffer.contains_retained(value),
176    {
177        Self { inner: BufferCarrier::new(capacity) }
178    }
179
180    /// Fixed FIFO capacity.
181    pub fn capacity(&self) -> (capacity: usize)
182        ensures capacity as nat == self.admitted_capacity(),
183    {
184        self.inner.capacity()
185    }
186
187    /// Number of retained values.
188    pub fn len(&self) -> (length: usize)
189        ensures length as nat == self.retained().len(),
190    {
191        self.inner.len()
192    }
193
194    /// Whether no values are retained.
195    pub fn is_empty(&self) -> (empty: bool)
196        ensures empty == (self.retained().len() == 0),
197    {
198        self.inner.is_empty()
199    }
200
201    /// Whether the FIFO is at capacity.
202    pub fn is_full(&self) -> (full: bool)
203        ensures full == (self.retained().len() == self.admitted_capacity()),
204    {
205        self.inner.is_full()
206    }
207
208    /// Push one value, returning it unchanged when the FIFO is full.
209    ///
210    /// # Errors
211    ///
212    /// Returns the supplied value when the buffer is full.
213    pub fn push(&mut self, value: T) -> (result: Result<(), T>)
214        requires old(self).well_formed(),
215        ensures
216            final(self).well_formed(),
217            final(self).admitted_capacity() == old(self).admitted_capacity(),
218            old(self).retained().len() < old(self).admitted_capacity() ==>
219                final(self).retained() == old(self).retained().push(value),
220            old(self).retained().len() >= old(self).admitted_capacity() ==>
221                final(self).retained() == old(self).retained(),
222    {
223        self.inner.push(value)
224    }
225
226    /// Remove and return the oldest retained value.
227    pub fn pop(&mut self) -> (value: Option<T>)
228        requires old(self).well_formed(),
229        ensures
230            final(self).well_formed(),
231            final(self).admitted_capacity() == old(self).admitted_capacity(),
232            old(self).retained().len() == 0 ==>
233                final(self).retained() == old(self).retained(),
234            old(self).retained().len() > 0 ==>
235                final(self).retained() == old(self).retained().skip(1),
236            old(self).distinct() ==> final(self).distinct(),
237    {
238        self.inner.pop()
239    }
240}
241
242impl<T: ValueEq + Copy> Buffer<T> {
243    /// Query retained membership using the shared equality adapter.
244    pub fn contains(&self, value: T) -> (present: bool)
245        ensures present == self.contains_retained(value),
246    {
247        self.inner.contains(value)
248    }
249
250    /// Append a value only when it is absent and capacity remains.
251    #[must_use]
252    pub fn push_unique(&mut self, value: T) -> (accepted: bool)
253        requires old(self).well_formed(), old(self).distinct(),
254        ensures
255            final(self).well_formed(),
256            final(self).distinct(),
257            final(self).admitted_capacity() == old(self).admitted_capacity(),
258            accepted == (old(self).retained().len() < old(self).admitted_capacity()
259                && !old(self).contains_retained(value)),
260            accepted ==> final(self).retained() == old(self).retained().push(value),
261            !accepted ==> final(self).retained() == old(self).retained(),
262    {
263        self.inner.push_unique(value)
264    }
265
266    /// Remove one distinct retained value wherever it occurs.
267    #[must_use]
268    pub fn remove(&mut self, value: T) -> (removed: bool)
269        requires old(self).well_formed(), old(self).distinct(),
270        ensures
271            final(self).well_formed(),
272            final(self).distinct(),
273            final(self).admitted_capacity() == old(self).admitted_capacity(),
274            removed == old(self).contains_retained(value),
275            forall|candidate: T| #[trigger] final(self).contains_retained(candidate)
276                == (old(self).contains_retained(candidate) && candidate != value),
277    {
278        self.inner.remove_value(value)
279    }
280}
281
282/// A retained nonnegative occurrence or generation count.
283///
284/// # Examples
285///
286/// ```rust
287/// use automation_structures::Counter;
288///
289/// let mut count = Counter::default();
290/// assert!(count.try_increment());
291/// assert_eq!(count.value(), 1);
292/// ```
293#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
294pub struct Counter {
295    inner: CounterCarrier,
296}
297
298impl Counter {
299    /// Construct a counter at `value`.
300    pub fn new(value: u64) -> Self { Self { inner: CounterCarrier::new(value) } }
301
302    /// Current retained count.
303    pub fn value(&self) -> u64 { self.inner.value() }
304
305    /// Increment unless the `u64` representation is exhausted.
306    #[must_use]
307    pub fn try_increment(&mut self) -> bool { self.inner.try_increment() }
308
309    /// Decrement when positive.
310    #[must_use]
311    pub fn try_decrement(&mut self) -> bool { self.inner.try_decrement() }
312}
313
314/// A reusable retained boolean marker.
315///
316/// # Examples
317///
318/// ```rust
319/// use automation_structures::Marker;
320///
321/// let mut marker = Marker::default();
322/// assert!(marker.set());
323/// assert!(marker.is_marked());
324/// assert!(marker.clear());
325/// ```
326#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
327pub struct Marker {
328    inner: MarkerCarrier,
329}
330
331impl Marker {
332    /// Construct a marker with an explicit initial state.
333    pub fn new(marked: bool) -> Self { Self { inner: MarkerCarrier::new(marked) } }
334
335    /// Whether the marker is set.
336    pub fn is_marked(&self) -> bool { self.inner.is_marked() }
337
338    /// Set the marker and return whether its state changed.
339    #[must_use]
340    pub fn set(&mut self) -> bool { self.inner.set() }
341
342    /// Clear the marker and return whether its state changed.
343    #[must_use]
344    pub fn clear(&mut self) -> bool { self.inner.clear() }
345}
346
347/// Test agreement between a projected membership answer and its source.
348///
349/// # Examples
350///
351/// ```rust
352/// use automation_structures::projection_consistent;
353///
354/// assert!(projection_consistent(true, true));
355/// assert!(!projection_consistent(true, false));
356/// ```
357pub fn projection_consistent(projected: bool, source: bool) -> (consistent: bool)
358    ensures consistent == crate::connectives::projection::membership_consistent(projected, source),
359{
360    projected == source
361}
362
363/// Test the strict ordering relation between two positions.
364///
365/// # Examples
366///
367/// ```rust
368/// use automation_structures::strictly_before;
369///
370/// assert!(strictly_before(1, 2));
371/// assert!(!strictly_before(2, 2));
372/// ```
373pub fn strictly_before(left: usize, right: usize) -> (ordered: bool) {
374    crate::connectives::ordering_pass::is_strictly_before(left, right)
375}
376
377}
378
379impl<T: Copy> Accumulator<T> {
380    /// Borrow the accumulated prefix in original order.
381    pub fn accumulated_iter(&self) -> impl ExactSizeIterator<Item = &T> {
382        self.inner.accumulated.iter()
383    }
384
385    /// Borrow the pending suffix in original order.
386    pub fn pending_iter(&self) -> impl ExactSizeIterator<Item = &T> {
387        self.inner.pending.iter()
388    }
389
390    /// Borrow the complete sequence in original order.
391    pub fn iter(&self) -> impl Iterator<Item = &T> {
392        self.inner
393            .accumulated
394            .iter()
395            .chain(self.inner.pending.iter())
396    }
397}
398
399impl<T: Copy> Default for Accumulator<T> {
400    fn default() -> Self {
401        Self::new(Vec::new())
402    }
403}
404
405impl<T: Copy + core::fmt::Debug> core::fmt::Debug for Accumulator<T> {
406    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407        formatter
408            .debug_struct("Accumulator")
409            .field("accumulated", &self.inner.accumulated)
410            .field("pending", &self.inner.pending)
411            .finish()
412    }
413}
414
415impl<T> Buffer<T> {
416    /// Borrow a retained value by FIFO position.
417    pub fn get(&self, index: usize) -> Option<&T> {
418        self.inner.values.get(index)
419    }
420
421    /// Borrow the retained FIFO contents.
422    pub fn as_slice(&self) -> &[T] {
423        self.inner.values.as_slice()
424    }
425
426    /// Borrow the retained values in FIFO order.
427    pub fn iter(&self) -> core::slice::Iter<'_, T> {
428        self.inner.values.iter()
429    }
430}
431
432impl<T> Default for Buffer<T> {
433    fn default() -> Self {
434        Self::new(0)
435    }
436}
437
438impl<T: Clone> Clone for Buffer<T> {
439    fn clone(&self) -> Self {
440        Self {
441            inner: BufferCarrier {
442                capacity: self.inner.capacity,
443                values: self.inner.values.clone(),
444            },
445        }
446    }
447}
448
449impl<T: PartialEq> PartialEq for Buffer<T> {
450    fn eq(&self, other: &Self) -> bool {
451        self.inner.capacity == other.inner.capacity && self.inner.values == other.inner.values
452    }
453}
454
455impl<T: Eq> Eq for Buffer<T> {}
456
457impl<T: core::fmt::Debug> core::fmt::Debug for Buffer<T> {
458    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
459        formatter
460            .debug_struct("Buffer")
461            .field("capacity", &self.inner.capacity)
462            .field("values", &self.inner.values)
463            .finish()
464    }
465}
466
467impl<T> AsRef<[T]> for Buffer<T> {
468    fn as_ref(&self) -> &[T] {
469        self.as_slice()
470    }
471}
472
473impl<'a, T> IntoIterator for &'a Buffer<T> {
474    type Item = &'a T;
475    type IntoIter = core::slice::Iter<'a, T>;
476
477    fn into_iter(self) -> Self::IntoIter {
478        self.iter()
479    }
480}
481
482impl<T> IntoIterator for Buffer<T> {
483    type Item = T;
484    type IntoIter = std::vec::IntoIter<T>;
485
486    fn into_iter(self) -> Self::IntoIter {
487        self.inner.values.into_iter()
488    }
489}
490
491impl From<u64> for Counter {
492    fn from(value: u64) -> Self {
493        Self::new(value)
494    }
495}
496
497impl From<Counter> for u64 {
498    fn from(counter: Counter) -> Self {
499        counter.value()
500    }
501}
502
503impl From<bool> for Marker {
504    fn from(marked: bool) -> Self {
505        Self::new(marked)
506    }
507}
508
509impl From<Marker> for bool {
510    fn from(marker: Marker) -> Self {
511        marker.is_marked()
512    }
513}