vest_lib/combinators/opt/
proof.rs1use crate::{
3 combinators::Pair,
4 core::{proof::*, spec::*},
5};
6use vstd::prelude::*;
7
8verus! {
9
10impl<A: SPRoundTripDps> super::Opt<A> {
11 proof fn lemma_serialize_parse_roundtrip(&self, v: Option<A::T>, obuf: Seq<u8>)
12 requires
13 self.0.unambiguous(),
14 parser_fails_on(self.0, obuf),
15 ensures
16 self.consistent(v) ==> {
17 let ibuf = self.spec_serialize_dps(v, obuf);
18 let n = self.byte_len(v) as int;
19 self.spec_parse(ibuf) == Some((n, v))
20 },
21 {
22 match v {
23 None => {},
24 Some(vv) => {
25 if self.consistent(Some(vv)) {
26 self.0.theorem_serialize_dps_parse_roundtrip(vv, obuf);
27 }
28 },
29 }
30 }
31}
32
33impl<A: NoLookAhead> super::Opt<A> {
34 proof fn lemma_opt_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>)
35 requires
36 self.0.safe_inv(),
37 self.0.no_lookahead_inv(),
38 parser_fails_on(self.0, i1) ==> parser_fails_on(self.0, i2),
39 ensures
40 self.spec_parse(i1) matches Some((n, v)) ==> 0 <= n <= i2.len() ==> i2.take(n)
41 == i1.take(n) ==> self.spec_parse(i2) == Some((n, v)),
42 {
43 if let Some((n, v)) = self.spec_parse(i1) {
44 if 0 <= n <= i2.len() {
45 if i2.take(n) == i1.take(n) {
46 if let Some((n0, v0)) = self.0.spec_parse(i1) {
47 self.0.lemma_no_lookahead(i1, i2);
48 } else {
49 assert(self.0.spec_parse(i2) is None);
50 }
51 }
52 }
53 }
54 }
55}
56
57impl<A: NonMalleable> NonMalleable for super::Opt<A> {
58 open spec fn nonmal_inv(&self) -> bool {
59 self.0.nonmal_inv()
60 }
61
62 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
63 self.0.lemma_parse_non_malleable(buf1, buf2);
64 }
65}
66
67impl<A: SafeParser> Productive for super::Opt<A> {
68 open spec fn productive_inv(&self) -> bool {
69 false
70 }
71
72 proof fn lemma_productive(&self, s: Seq<u8>) {
73 }
74}
75
76impl<A> EquivSerializersGeneral for super::Opt<A> where A: EquivSerializersGeneral {
77 open spec fn equiv_general_inv(&self) -> bool {
78 self.0.equiv_general_inv()
79 }
80
81 proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
82 match v {
83 None => {},
84 Some(vv) => {
85 self.0.lemma_serialize_equiv(vv, obuf);
86 },
87 }
88 }
89}
90
91impl<A> EquivSerializers for super::Opt<A> where A: EquivSerializers {
92 open spec fn equiv_inv(&self) -> bool {
93 self.0.equiv_inv()
94 }
95
96 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
97 match v {
98 None => {},
99 Some(vv) => {
100 self.0.lemma_serialize_equiv_on_empty(vv);
101 },
102 }
103 }
104}
105
106impl<A: SPRoundTripDps + NonTailFmt, B: SPRoundTripDps> SPRoundTripDps for super::Optional<A, B> {
107 open spec fn unambiguous(&self) -> bool {
108 &&& self.0.serialize_dps_inv()
109 &&& self.0.unambiguous()
110 &&& self.1.unambiguous()
111 &&& disjoint_domains(self.0, self.1)
112 }
113
114 proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
115 let opt = super::Opt(self.0);
116 let serialized1 = self.1.spec_serialize_dps(v.1, obuf);
117 self.1.theorem_serialize_dps_parse_roundtrip(v.1, obuf);
118 assert(parser_fails_on(self.0, serialized1)) by {
119 reveal(disjoint_domains);
120 assert(self.1.spec_parse(serialized1) is Some);
121 }
122 let serialized0 = opt.spec_serialize_dps(v.0, serialized1);
123 opt.lemma_serialize_parse_roundtrip(v.0, serialized1);
124 let n0 = serialized0.len() - serialized1.len();
125 opt.lemma_serialize_dps_prepend(v.0, serialized1);
126 opt.lemma_serialize_dps_len(v.0, serialized1);
127 assert(serialized0.skip(n0) == serialized1);
128 }
129}
130
131impl<A: NonMalleable, B: NonMalleable> NonMalleable for super::Optional<A, B> {
137 open spec fn nonmal_inv(&self) -> bool {
138 Pair(super::Opt(self.0), self.1).nonmal_inv()
139 }
140
141 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
142 Pair(super::Opt(self.0), self.1).lemma_parse_non_malleable(buf1, buf2);
143 }
144}
145
146impl<A: NoLookAhead, B: NoLookAhead> NoLookAhead for super::Optional<A, B> {
147 open spec fn no_lookahead_inv(&self) -> bool {
148 &&& self.0.no_lookahead_inv()
149 &&& self.1.no_lookahead_inv()
150 &&& disjoint_domains(self.0, self.1)
151 }
152
153 proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
154 reveal(disjoint_domains);
155 broadcast use vstd::seq_lib::group_seq_properties;
156
157 use crate::combinators::tuple::proof::lemma_take_skip;
158
159 let opt = super::Opt(self.0);
160 if let Some((n, v)) = self.spec_parse(i1) {
161 if 0 <= n <= i2.len() {
162 if i2.take(n) == i1.take(n) {
163 assert(self.safe_inv());
164 if let Some((n0, a)) = self.0.spec_parse(i1) {
165 if let Some((n1, b)) = self.1.spec_parse(i1.skip(n0)) {
166 assert(opt.safe_inv());
167 assert(self.1.safe_inv());
168 opt.lemma_parse_safe(i1);
169 self.1.lemma_parse_safe(i1.skip(n0));
170 assert(i2.take(n0) == i1.take(n0));
171 opt.lemma_opt_no_lookahead(i1, i2);
172 assert(i2.skip(n0).take(n1) == i1.skip(n0).take(n1)) by {
173 lemma_take_skip(i1, n0, n1);
174 lemma_take_skip(i2, n0, n1);
175 };
176 self.1.lemma_no_lookahead(i1.skip(n0), i2.skip(n0));
177 }
178 } else if let Some((n1, b)) = self.1.spec_parse(i1) {
179 assert(disjoint_domains(self.0, self.1));
180 assert(self.1.safe_inv());
181 self.1.lemma_no_lookahead(i1, i2);
182 }
183 }
184 }
185 }
186 }
187}
188
189impl<A: Productive, B: Productive> Productive for super::Optional<A, B> {
190 open spec fn productive_inv(&self) -> bool {
191 self.1.productive_inv()
192 }
193
194 proof fn lemma_productive(&self, s: Seq<u8>) {
195 if let Some((n, _v)) = self.spec_parse(s) {
196 let (n1, _v1) = super::Opt(self.0).spec_parse(s)->0;
197 let (n2, _v2) = self.1.spec_parse(s.skip(n1))->0;
198 super::Opt(self.0).lemma_parse_safe(s);
199 self.1.lemma_productive(s.skip(n1));
200 }
201 }
202}
203
204impl<
205 A: EquivSerializersGeneral,
206 B: EquivSerializersGeneral,
207> EquivSerializersGeneral for super::Optional<A, B> {
208 open spec fn equiv_general_inv(&self) -> bool {
209 &&& self.0.equiv_general_inv()
210 &&& self.1.equiv_general_inv()
211 }
212
213 proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
214 Pair(super::Opt(self.0), self.1).lemma_serialize_equiv(v, obuf);
215 }
216}
217
218impl<A: EquivSerializersGeneral, B: EquivSerializers> EquivSerializers for super::Optional<A, B> {
219 open spec fn equiv_inv(&self) -> bool {
220 &&& self.0.equiv_general_inv()
221 &&& self.1.equiv_inv()
222 }
223
224 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
225 Pair(super::Opt(self.0), self.1).lemma_serialize_equiv_on_empty(v);
226 }
227}
228
229}