Skip to main content

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!