vest_lib/combinators/implicit/
proof.rs1use crate::core::{proof::*, spec::*};
3use vstd::prelude::*;
4
5verus! {
6
7impl<Head, Tail> SPRoundTripDps for super::Implicit<Head, Tail> where
8 Head: SPRoundTripDps + NonTailFmt,
9 Tail: super::DepCombinator<Key = Head::T>,
10 Tail::Body: SPRoundTripDps<T = Tail::Val>,
11 {
12 open spec fn unambiguous(&self) -> bool {
13 &&& self.0.serialize_dps_inv()
14 &&& self.0.unambiguous()
15 &&& forall|key: Head::T| #[trigger] self.1.apply(key).unambiguous()
16 }
17
18 proof fn theorem_serialize_dps_parse_roundtrip(&self, value: Self::T, obuf: Seq<u8>) {
19 let key = self.1.recover(value);
20 let next = self.1.apply(key);
21 let next_buf = next.spec_serialize_dps(value, obuf);
22 let serialized = self.0.spec_serialize_dps(key, next_buf);
23 assert(self.0.consistent(key) && next.consistent(value));
24 next.theorem_serialize_dps_parse_roundtrip(value, obuf);
25 self.0.theorem_serialize_dps_parse_roundtrip(key, next_buf);
26 self.0.lemma_serialize_dps_prepend(key, next_buf);
27 self.0.lemma_serialize_dps_len(key, next_buf);
28 if let Some((n0, _)) = self.0.spec_parse(serialized) {
29 assert(n0 == serialized.len() - next_buf.len());
30 assert(serialized.skip(n0) == next_buf);
31 }
32 }
33}
34
35impl<Head, Tail> NonMalleable for super::Implicit<Head, Tail> where
36 Head: SoundParser + NonMalleable,
37 Tail: super::DepCombinator<Key = Head::T>,
38 Tail::Body: SoundParser<T = Tail::Val> + NonMalleable,
39 {
40 open spec fn nonmal_inv(&self) -> bool {
41 &&& self.0.nonmal_inv()
42 &&& self.0.sound_inv()
43 &&& forall|key: Head::PVal| #[trigger] self.1.apply(key).nonmal_inv()
44 &&& forall|key: Head::PVal| #[trigger] self.1.apply(key).sound_inv()
45 &&& self.1.recover_inv()
46 }
47
48 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
49 if let Some((n1, v1)) = self.spec_parse(buf1) {
50 if let Some((n2, v2)) = self.spec_parse(buf2) {
51 if v1 == v2 {
52 assert(self.nonmal_inv());
53 let (n1a, k1) = self.0.spec_parse(buf1)->0;
54 let (n2a, k2) = self.0.spec_parse(buf2)->0;
55 let body1 = self.1.apply(k1);
56 let body2 = self.1.apply(k2);
57 let (n1b, v) = body1.spec_parse(buf1.skip(n1a))->0;
58 let (n2b, v) = body2.spec_parse(buf2.skip(n2a))->0;
59 self.0.lemma_parse_sound_value(buf1);
60 self.0.lemma_parse_sound_value(buf2);
61 body1.lemma_parse_sound_value(buf1.skip(n1a));
62 body2.lemma_parse_sound_value(buf2.skip(n2a));
63 self.1.lemma_recover_consistent(k1, v);
64 self.1.lemma_recover_consistent(k2, v);
65 assert(k1 == k2 && body1 == body2);
66 let body = body1;
67 self.0.lemma_parse_safe(buf1);
68 self.0.lemma_parse_safe(buf2);
69 body.lemma_parse_safe(buf1.skip(n1a));
70 body.lemma_parse_safe(buf2.skip(n2a));
71 self.0.lemma_parse_non_malleable(buf1, buf2);
72 body.lemma_parse_non_malleable(buf1.skip(n1a), buf2.skip(n2a));
73 assert(n1 == n1a + n1b && n2 == n2a + n2b);
74 assert(buf1.take(n1) == buf2.take(n2)) by {
75 assert(buf1.take(n1) == buf1.take(n1a) + buf1.skip(n1a).take(n1b));
76 assert(buf2.take(n2) == buf2.take(n2a) + buf2.skip(n2a).take(n2b));
77 }
78 }
79 }
80 }
81 }
82}
83
84impl<Head, Tail> NoLookAhead for super::Implicit<Head, Tail> where
85 Head: NoLookAhead,
86 Tail: super::DepCombinator<Key = Head::PVal>,
87 Tail::Body: NoLookAhead<PVal = Tail::Val>,
88 {
89 open spec fn no_lookahead_inv(&self) -> bool {
90 &&& self.0.no_lookahead_inv()
91 &&& forall|key: Head::PVal| #[trigger] self.1.apply(key).no_lookahead_inv()
92 }
93
94 proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
95 broadcast use vstd::seq_lib::group_seq_properties;
96
97 use crate::combinators::tuple::proof::lemma_take_skip;
98
99 if let Some((n, v)) = self.spec_parse(i1) {
100 if 0 <= n <= i2.len() {
101 if i2.take(n) == i1.take(n) {
102 if let Some((n1, key)) = self.0.spec_parse(i1) {
103 let body = self.1.apply(key);
104 if let Some((n2, _v2)) = body.spec_parse(i1.skip(n1)) {
105 self.lemma_parse_safe(i1);
106 self.0.lemma_parse_safe(i1);
107 body.lemma_parse_safe(i1.skip(n1));
108 assert(i2.take(n1) == i1.take(n1));
109 self.0.lemma_no_lookahead(i1, i2);
110 assert(i2.skip(n1).take(n2) == i1.skip(n1).take(n2)) by {
111 lemma_take_skip(i1, n1, n2);
112 lemma_take_skip(i2, n1, n2);
113 };
114 body.lemma_no_lookahead(i1.skip(n1), i2.skip(n1));
115 assert(self.spec_parse(i2) == Some((n, v)));
116 }
117 }
118 }
119 }
120 }
121 }
122}
123
124impl<Head, Tail> Productive for super::Implicit<Head, Tail> where
125 Head: Productive,
126 Tail: super::DepCombinator<Key = Head::PVal>,
127 Tail::Body: Productive<PVal = Tail::Val>,
128 {
129 open spec fn productive_inv(&self) -> bool {
130 ||| self.0.productive_inv()
131 ||| forall|key: Head::PVal| #[trigger] self.1.apply(key).productive_inv()
132 }
133
134 proof fn lemma_productive(&self, s: Seq<u8>) {
135 if let Some((n, v)) = self.spec_parse(s) {
136 let (n1, key) = self.0.spec_parse(s)->0;
137 let next = self.1.apply(key);
138 let (n2, _val) = next.spec_parse(s.skip(n1))->0;
139 self.0.lemma_parse_safe(s);
140 next.lemma_parse_safe(s.skip(n1));
141 if self.0.productive_inv() {
142 self.0.lemma_productive(s);
143 } else {
144 next.lemma_productive(s.skip(n1));
145 }
146 }
147 }
148}
149
150impl<Head, Tail> EquivSerializersGeneral for super::Implicit<Head, Tail> where
151 Head: EquivSerializersGeneral,
152 Tail: super::DepCombinator<Key = Head::SVal>,
153 Tail::Body: EquivSerializersGeneral<SVal = Tail::Val>,
154 {
155 open spec fn equiv_general_inv(&self) -> bool {
156 &&& self.0.equiv_general_inv()
157 &&& forall|key: Head::SVal| #[trigger] self.1.apply(key).equiv_general_inv()
158 }
159
160 proof fn lemma_serialize_equiv(&self, value: Self::SVal, obuf: Seq<u8>) {
161 let key = self.1.recover(value);
162 let next = self.1.apply(key);
163 let obuf1 = next.spec_serialize_dps(value, obuf);
164 next.lemma_serialize_equiv(value, obuf);
165 self.0.lemma_serialize_equiv(key, obuf1);
166 }
167}
168
169impl<Head, Tail> EquivSerializers for super::Implicit<Head, Tail> where
170 Head: EquivSerializersGeneral,
171 Tail: super::DepCombinator<Key = Head::SVal>,
172 Tail::Body: EquivSerializers<SVal = Tail::Val>,
173 {
174 open spec fn equiv_inv(&self) -> bool {
175 &&& self.0.equiv_general_inv()
176 &&& forall|key: Head::SVal| #[trigger] self.1.apply(key).equiv_inv()
177 }
178
179 proof fn lemma_serialize_equiv_on_empty(&self, value: Self::SVal) {
180 let key = self.1.recover(value);
181 let next = self.1.apply(key);
182 let empty = Seq::empty();
183 let obuf = next.spec_serialize_dps(value, empty);
184 next.lemma_serialize_equiv_on_empty(value);
185 self.0.lemma_serialize_equiv(key, obuf);
186 }
187}
188
189}