vest_lib/combinators/tuple/mod.rs
1//! Sequential and dependent composition.
2//!
3//! [`Pair`] parses two formats in order; N-ary formats nest it as
4//! `Pair(A, Pair(B, C))`. [`Bind`] chooses the second format based on the first's value.
5/// Executable trait implementations for this combinator.
6pub mod exec;
7/// Correctness proofs for this combinator.
8pub mod proof;
9/// Specification trait implementations for this combinator.
10pub mod spec;
11
12use vstd::prelude::*;
13
14verus! {
15
16/// Sequential composition of formats `A` and `B`.
17#[derive(Copy)]
18pub struct Pair<A, B>(pub A, pub B);
19
20impl<A: Clone, B: Clone> Clone for Pair<A, B> {
21 fn clone(&self) -> (cloned: Self)
22 ensures
23 call_ensures(A::clone, (&self.0,), cloned.0),
24 call_ensures(B::clone, (&self.1,), cloned.1),
25 {
26 Pair(self.0.clone(), self.1.clone())
27 }
28}
29
30/// Sequential composition of formats `A` and `B`, where `B` may depend on the value of `A`.
31///
32/// Parsing semantics: parses `A` to get a `key`, then parses `B(key)` to get the body `value`,
33/// and returns `(key, value)`.
34/// During serialization, the caller must provide both the `key` and `value`.
35///
36/// ## Note on usage
37///
38/// Prefer [`super::Implicit`] when the key should be recovered from the body value instead of
39/// being carried explicitly through the value type.
40#[derive(Copy)]
41pub struct Bind<A, B>(pub A, pub B);
42
43impl<A: Clone, B: Clone> Clone for Bind<A, B> {
44 fn clone(&self) -> (cloned: Self)
45 ensures
46 call_ensures(A::clone, (&self.0,), cloned.0),
47 call_ensures(B::clone, (&self.1,), cloned.1),
48 {
49 Bind(self.0.clone(), self.1.clone())
50 }
51}
52
53} // verus!