Skip to main content

vest_lib/combinators/
congruence.rs

1//! Congruence lemmas for parser, serializer, and preparation specifications.
2use crate::combinators::bits::Bits;
3use crate::combinators::bytes::{AndThen, ExactLen, Fixed, Varied};
4use crate::combinators::mapped::spec::{BiMap, BiMapper, FnSpecMapper, SpecMap};
5use crate::combinators::named::Named;
6use crate::combinators::reference::Ref;
7use crate::combinators::tail::{Eof, RepeatTillEnd, Tail};
8use crate::combinators::AsLen;
9use crate::combinators::Optional;
10use crate::combinators::OptionalEnd;
11use crate::combinators::{
12    Alt, Array, Bind, Choice, Cond, Const, Mapped, Opt, Pair, Preceded, PrefixTagged, Refined,
13    Repeat, RepeatN, Star, SuffixTagged, Sum, Terminated,
14};
15use crate::core::exec::fns::FnParser;
16use crate::core::exec::parser::PResult;
17use crate::core::spec::{
18    BytesCombinator, Consistency, SafeParser, SpecByteLen, SpecParser, SpecPred, SpecSerializer,
19    SpecSerializerDps,
20};
21use vstd::prelude::*;
22
23verus! {
24
25/// Pointwise equality of parser denotations. The format types may differ, but their parsed value
26/// types must agree.
27#[verifier::opaque]
28pub open spec fn parser_congruent<A, B>(a: A, b: B) -> bool where
29    A: SpecParser,
30    B: SpecParser<PVal = A::PVal>,
31 {
32    forall|input: Seq<u8>| a.spec_parse(input) == b.spec_parse(input)
33}
34
35/// Equality of the two semantic components used by executable preparation.
36#[verifier::opaque]
37pub open spec fn prepare_congruent<A, B>(a: A, b: B) -> bool where
38    A: Consistency + SpecByteLen<T = A::Val>,
39    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
40 {
41    &&& forall|v: A::Val| a.consistent(v) <==> b.consistent(v)
42    &&& forall|v: A::Val| a.byte_len(v) == b.byte_len(v)
43}
44
45/// Equality of the full semantic interface used by executable serialization.
46#[verifier::opaque]
47pub open spec fn serializer_congruent<A, B>(a: A, b: B) -> bool where
48    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
49    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
50 {
51    &&& prepare_congruent(a, b)
52    &&& forall|v: A::Val| a.spec_serialize(v) == b.spec_serialize(v)
53}
54
55pub broadcast proof fn lemma_parser_congruent_apply<A, B>(a: A, b: B, input: Seq<u8>) where
56    A: SpecParser,
57    B: SpecParser<PVal = A::PVal>,
58
59    requires
60        parser_congruent(a, b),
61    ensures
62        #[trigger] a.spec_parse(input) == #[trigger] b.spec_parse(input),
63{
64    reveal(parser_congruent);
65}
66
67pub broadcast proof fn lemma_parser_congruent_intro<A, B>(a: A, b: B) where
68    A: SpecParser,
69    B: SpecParser<PVal = A::PVal>,
70
71    requires
72        forall|input: Seq<u8>| #[trigger] a.spec_parse(input) == b.spec_parse(input),
73    ensures
74        #[trigger] parser_congruent(a, b),
75{
76    reveal(parser_congruent);
77}
78
79/// Connects an executable parser callback, through the Rust reference adapter, directly to its
80/// ghost parser. This packages the otherwise repetitive pointwise `spec_parse` proof.
81pub broadcast proof fn lemma_ref_fn_parser_congruence<I, O, Spec, Exec>(
82    parser: &FnParser<I, O, Spec, Exec>,
83) where I: View<V = Seq<u8>>, O: DeepView, Spec: SpecParser<PVal = O::V>, Exec: Fn(&I) -> PResult<O>
84    ensures
85        #[trigger] parser_congruent(parser, parser.spec_fn@),
86{
87    reveal(parser_congruent);
88    assert forall|input: Seq<u8>| #[trigger]
89        (&parser).spec_parse(input) == parser.spec_fn@.spec_parse(input) by {
90        crate::core::exec::fns::lemma_ref_fn_parser_spec_parse(parser, input);
91    }
92}
93
94pub broadcast proof fn lemma_prepare_congruent_intro<A, B>(a: A, b: B) where
95    A: Consistency + SpecByteLen<T = A::Val>,
96    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
97
98    requires
99        forall|v: A::Val| #[trigger] a.consistent(v) <==> b.consistent(v),
100        forall|v: A::Val| #[trigger] a.byte_len(v) == b.byte_len(v),
101    ensures
102        #[trigger] prepare_congruent(a, b),
103{
104    reveal(prepare_congruent);
105}
106
107pub broadcast proof fn lemma_serializer_congruent_intro<A, B>(a: A, b: B) where
108    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
109    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
110
111    requires
112        prepare_congruent(a, b),
113        forall|v: A::Val| #[trigger] a.spec_serialize(v) == b.spec_serialize(v),
114    ensures
115        #[trigger] serializer_congruent(a, b),
116{
117    reveal(serializer_congruent);
118}
119
120pub broadcast proof fn lemma_prepare_congruent_consistent<A, B>(a: A, b: B, v: A::Val) where
121    A: Consistency + SpecByteLen<T = A::Val>,
122    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
123
124    requires
125        prepare_congruent(a, b),
126    ensures
127        #[trigger] a.consistent(v) <==> #[trigger] b.consistent(v),
128{
129    reveal(prepare_congruent);
130}
131
132pub broadcast proof fn lemma_prepare_congruent_byte_len<A, B>(a: A, b: B, v: A::Val) where
133    A: Consistency + SpecByteLen<T = A::Val>,
134    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
135
136    requires
137        prepare_congruent(a, b),
138    ensures
139        #[trigger] a.byte_len(v) == #[trigger] b.byte_len(v),
140{
141    reveal(prepare_congruent);
142}
143
144pub broadcast proof fn lemma_serializer_congruent_prepare<A, B>(a: A, b: B) where
145    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
146    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
147
148    requires
149        serializer_congruent(a, b),
150    ensures
151        #[trigger] prepare_congruent(a, b),
152{
153    reveal(serializer_congruent);
154}
155
156pub broadcast proof fn lemma_serializer_congruent_serialize<A, B>(a: A, b: B, v: A::Val) where
157    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
158    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
159
160    requires
161        serializer_congruent(a, b),
162    ensures
163        #[trigger] a.spec_serialize(v) == #[trigger] b.spec_serialize(v),
164{
165    reveal(serializer_congruent);
166}
167
168pub broadcast proof fn lemma_parser_congruent_reflexive<A: SpecParser>(a: A)
169    ensures
170        #[trigger] parser_congruent(a, a),
171{
172    reveal(parser_congruent);
173}
174
175// Symmetry and transitivity stay explicit: broadcasting them would compute an unrestricted
176// congruence closure (including symmetric ping-pong and quadratic transitive instantiations).
177pub proof fn lemma_parser_congruent_symmetric<A, B>(a: A, b: B) where
178    A: SpecParser,
179    B: SpecParser<PVal = A::PVal>,
180
181    requires
182        parser_congruent(a, b),
183    ensures
184        parser_congruent(b, a),
185{
186    reveal(parser_congruent);
187}
188
189pub proof fn lemma_parser_congruent_transitive<A, B, C>(a: A, b: B, c: C) where
190    A: SpecParser,
191    B: SpecParser<PVal = A::PVal>,
192    C: SpecParser<PVal = A::PVal>,
193
194    requires
195        parser_congruent(a, b),
196        parser_congruent(b, c),
197    ensures
198        parser_congruent(a, c),
199{
200    reveal(parser_congruent);
201}
202
203pub broadcast proof fn lemma_prepare_congruent_reflexive<A>(a: A) where
204    A: Consistency + SpecByteLen<T = A::Val>,
205
206    ensures
207        #[trigger] prepare_congruent(a, a),
208{
209    reveal(prepare_congruent);
210}
211
212pub proof fn lemma_prepare_congruent_symmetric<A, B>(a: A, b: B) where
213    A: Consistency + SpecByteLen<T = A::Val>,
214    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
215
216    requires
217        prepare_congruent(a, b),
218    ensures
219        prepare_congruent(b, a),
220{
221    reveal(prepare_congruent);
222}
223
224pub proof fn lemma_prepare_congruent_transitive<A, B, C>(a: A, b: B, c: C) where
225    A: Consistency + SpecByteLen<T = A::Val>,
226    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
227    C: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
228
229    requires
230        prepare_congruent(a, b),
231        prepare_congruent(b, c),
232    ensures
233        prepare_congruent(a, c),
234{
235    reveal(prepare_congruent);
236}
237
238pub broadcast proof fn lemma_serializer_congruent_reflexive<A>(a: A) where
239    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
240
241    ensures
242        #[trigger] serializer_congruent(a, a),
243{
244    reveal(serializer_congruent);
245    lemma_prepare_congruent_reflexive(a);
246}
247
248pub proof fn lemma_serializer_congruent_symmetric<A, B>(a: A, b: B) where
249    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
250    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
251
252    requires
253        serializer_congruent(a, b),
254    ensures
255        serializer_congruent(b, a),
256{
257    reveal(serializer_congruent);
258    lemma_prepare_congruent_symmetric(a, b);
259}
260
261pub proof fn lemma_serializer_congruent_transitive<A, B, C>(a: A, b: B, c: C) where
262    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
263    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
264    C: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
265
266    requires
267        serializer_congruent(a, b),
268        serializer_congruent(b, c),
269    ensures
270        serializer_congruent(a, c),
271{
272    reveal(serializer_congruent);
273    lemma_prepare_congruent_transitive(a, b, c);
274}
275
276// ----------------------------------------------------
277// ExactLen
278// ----------------------------------------------------
279pub proof fn lemma_exact_len_spec_parse_congruence<
280    Inner: SpecParser,
281    Inner2: SpecParser<PVal = Inner::PVal>,
282    Len: AsLen,
283>(len: Len, inner: Inner, inner2: Inner2)
284    requires
285        forall|x: Seq<u8>| #[trigger] inner.spec_parse(x) == inner2.spec_parse(x),
286    ensures
287        forall|x: Seq<u8>| #[trigger]
288            ExactLen(len, inner).spec_parse(x) == ExactLen(len, inner2).spec_parse(x),
289{
290}
291
292// ----------------------------------------------------
293// AndThen
294// ----------------------------------------------------
295pub proof fn lemma_and_then_spec_parse_congruence<
296    Tail1: SpecParser<PVal = Seq<u8>>,
297    Tail2: SpecParser<PVal = Seq<u8>>,
298    Then1: SpecParser,
299    Then2: SpecParser<PVal = Then1::PVal>,
300>(tail1: Tail1, tail2: Tail2, then1: Then1, then2: Then2)
301    requires
302        forall|x: Seq<u8>| #[trigger] tail1.spec_parse(x) == tail2.spec_parse(x),
303        forall|x: Seq<u8>| #[trigger] then1.spec_parse(x) == then2.spec_parse(x),
304    ensures
305        forall|x: Seq<u8>| #[trigger]
306            AndThen(tail1, then1).spec_parse(x) == AndThen(tail2, then2).spec_parse(x),
307{
308}
309
310// ----------------------------------------------------
311// Mapped
312// ----------------------------------------------------
313pub proof fn lemma_mapped_spec_parse_congruence<
314    Inner1: SpecParser,
315    Inner2: SpecParser<PVal = Inner1::PVal>,
316    M1: crate::combinators::mapped::spec::SpecMapper<In = Inner1::PVal>,
317    M2: crate::combinators::mapped::spec::SpecMapper<In = Inner2::PVal, Out = M1::Out>,
318>(inner1: Inner1, inner2: Inner2, mapper1: M1, mapper2: M2)
319    requires
320        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
321        forall|v: Inner1::PVal| #[trigger] mapper1.spec_map(v) == mapper2.spec_map(v),
322    ensures
323        forall|x: Seq<u8>| #[trigger]
324            (Mapped { inner: inner1, mapper: mapper1 }).spec_parse(x) == (Mapped {
325                inner: inner2,
326                mapper: mapper2,
327            }).spec_parse(x),
328{
329}
330
331// ----------------------------------------------------
332// Refined
333// ----------------------------------------------------
334pub proof fn lemma_refined_spec_parse_congruence<
335    Inner1: SpecParser,
336    Inner2: SpecParser<PVal = Inner1::PVal>,
337    Pred: SpecPred<Inner1::PVal>,
338>(inner1: Inner1, inner2: Inner2, pred: Pred)
339    requires
340        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
341    ensures
342        forall|x: Seq<u8>| #[trigger]
343            Refined(inner1, pred).spec_parse(x) == Refined(inner2, pred).spec_parse(x),
344{
345}
346
347// ----------------------------------------------------
348// Const
349// ----------------------------------------------------
350pub proof fn lemma_const_spec_parse_congruence<
351    Inner1: SpecParser<PVal = T>,
352    Inner2: SpecParser<PVal = T>,
353    T,
354>(inner1: Inner1, inner2: Inner2, val: T)
355    requires
356        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
357    ensures
358        forall|x: Seq<u8>| #[trigger]
359            Const(inner1, val).spec_parse(x) == Const(inner2, val).spec_parse(x),
360{
361}
362
363// ----------------------------------------------------
364// Cond
365// ----------------------------------------------------
366pub proof fn lemma_cond_spec_parse_congruence<
367    Inner1: SpecParser,
368    Inner2: SpecParser<PVal = Inner1::PVal>,
369>(cond: bool, inner1: Inner1, inner2: Inner2)
370    requires
371        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
372    ensures
373        forall|x: Seq<u8>| #[trigger]
374            Cond(cond, inner1).spec_parse(x) == Cond(cond, inner2).spec_parse(x),
375{
376}
377
378// ----------------------------------------------------
379// Choice
380// ----------------------------------------------------
381pub proof fn lemma_choice_spec_parse_congruence<
382    A1: SpecParser,
383    A2: SpecParser<PVal = A1::PVal>,
384    B1: SpecParser,
385    B2: SpecParser<PVal = B1::PVal>,
386>(a1: A1, a2: A2, b1: B1, b2: B2)
387    requires
388        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
389        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
390    ensures
391        forall|x: Seq<u8>| #[trigger] Choice(a1, b1).spec_parse(x) == Choice(a2, b2).spec_parse(x),
392{
393}
394
395// ----------------------------------------------------
396// Alt
397// ----------------------------------------------------
398pub proof fn lemma_alt_spec_parse_congruence<
399    const NONDETERMINISTIC: bool,
400    A1: SpecParser,
401    A2: SpecParser<PVal = A1::PVal>,
402    B1: SpecParser<PVal = A1::PVal>,
403    B2: SpecParser<PVal = A1::PVal>,
404>(a1: A1, a2: A2, b1: B1, b2: B2)
405    requires
406        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
407        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
408    ensures
409        forall|x: Seq<u8>| #[trigger]
410            Alt::<A1, B1, NONDETERMINISTIC>(a1, b1).spec_parse(x) == Alt::<
411                A2,
412                B2,
413                NONDETERMINISTIC,
414            >(a2, b2).spec_parse(x),
415{
416}
417
418// ----------------------------------------------------
419// Sum
420// ----------------------------------------------------
421pub proof fn lemma_sum_spec_parse_congruence<
422    A1: SpecParser,
423    A2: SpecParser<PVal = A1::PVal>,
424    B1: SpecParser,
425    B2: SpecParser<PVal = B1::PVal>,
426>(a1: A1, a2: A2, b1: B1, b2: B2)
427    requires
428        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
429        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
430    ensures
431        forall|x: Seq<u8>| #[trigger]
432            Sum::<A1, B1>::Inl(a1).spec_parse(x) == Sum::<A2, B2>::Inl(a2).spec_parse(x),
433        forall|x: Seq<u8>| #[trigger]
434            Sum::<A1, B1>::Inr(b1).spec_parse(x) == Sum::<A2, B2>::Inr(b2).spec_parse(x),
435{
436}
437
438// ----------------------------------------------------
439// Opt
440// ----------------------------------------------------
441pub proof fn lemma_opt_spec_parse_congruence<A: SpecParser, B: SpecParser<PVal = A::PVal>>(
442    a: A,
443    b: B,
444)
445    requires
446        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
447    ensures
448        forall|x: Seq<u8>| #[trigger] Opt(a).spec_parse(x) == Opt(b).spec_parse(x),
449{
450}
451
452// ----------------------------------------------------
453// Optional
454// ----------------------------------------------------
455pub proof fn lemma_optional_spec_parse_congruence<
456    A1: SpecParser,
457    A2: SpecParser<PVal = A1::PVal>,
458    B1: SpecParser,
459    B2: SpecParser<PVal = B1::PVal>,
460>(a1: A1, a2: A2, b1: B1, b2: B2)
461    requires
462        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
463        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
464    ensures
465        forall|x: Seq<u8>| #[trigger]
466            Optional(a1, b1).spec_parse(x) == Optional(a2, b2).spec_parse(x),
467{
468    lemma_opt_spec_parse_congruence(a1, a2);
469    lemma_pair_spec_parse_congruence(Opt(a1), Opt(a2), b1, b2);
470}
471
472// ----------------------------------------------------
473// OptionalEnd
474// ----------------------------------------------------
475pub proof fn lemma_optional_end_spec_parse_congruence<
476    Inner1: SpecParser,
477    Inner2: SpecParser<PVal = Inner1::PVal>,
478>(inner1: Inner1, inner2: Inner2)
479    requires
480        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
481    ensures
482        forall|x: Seq<u8>| #[trigger]
483            OptionalEnd(inner1).spec_parse(x) == OptionalEnd(inner2).spec_parse(x),
484{
485    lemma_optional_spec_parse_congruence(inner1, inner2, Eof, Eof);
486}
487
488// ----------------------------------------------------
489// Preceded
490// ----------------------------------------------------
491pub proof fn lemma_preceded_spec_parse_congruence<
492    const CHECK: bool,
493    A1: SpecParser<PVal = AVal>,
494    A2: SpecParser<PVal = AVal>,
495    B1: SpecParser,
496    B2: SpecParser<PVal = B1::PVal>,
497    AVal,
498>(a1: A1, a2: A2, b1: B1, b2: B2, a_val: AVal)
499    requires
500        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
501        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
502    ensures
503        forall|x: Seq<u8>| #[trigger]
504            (Preceded::<A1, AVal, B1, CHECK> { a: a1, b: b1, a_val }).spec_parse(x) == (Preceded::<
505                A2,
506                AVal,
507                B2,
508                CHECK,
509            > { a: a2, b: b2, a_val }).spec_parse(x),
510{
511    lemma_pair_spec_parse_congruence(a1, a2, b1, b2);
512}
513
514// ----------------------------------------------------
515// Terminated
516// ----------------------------------------------------
517pub proof fn lemma_terminated_spec_parse_congruence<
518    const CHECK: bool,
519    A1: SpecParser,
520    A2: SpecParser<PVal = A1::PVal>,
521    B1: SpecParser<PVal = BVal>,
522    B2: SpecParser<PVal = BVal>,
523    BVal,
524>(a1: A1, a2: A2, b1: B1, b2: B2, b_val: BVal)
525    requires
526        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
527        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
528    ensures
529        forall|x: Seq<u8>| #[trigger]
530            (Terminated::<A1, B1, BVal, CHECK> { a: a1, b: b1, b_val }).spec_parse(x) == (
531            Terminated::<A2, B2, BVal, CHECK> { a: a2, b: b2, b_val }).spec_parse(x),
532{
533    lemma_pair_spec_parse_congruence(a1, a2, b1, b2);
534}
535
536// ----------------------------------------------------
537// Pair
538// ----------------------------------------------------
539pub proof fn lemma_pair_spec_parse_congruence<
540    A1: SpecParser,
541    A2: SpecParser<PVal = A1::PVal>,
542    B1: SpecParser,
543    B2: SpecParser<PVal = B1::PVal>,
544>(a1: A1, a2: A2, b1: B1, b2: B2)
545    requires
546        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
547        forall|x: Seq<u8>| #[trigger] b1.spec_parse(x) == b2.spec_parse(x),
548    ensures
549        forall|x: Seq<u8>| #[trigger] Pair(a1, b1).spec_parse(x) == Pair(a2, b2).spec_parse(x),
550{
551}
552
553// ----------------------------------------------------
554// Bind
555// ----------------------------------------------------
556pub proof fn lemma_bind_spec_parse_congruence<
557    A1: SpecParser,
558    A2: SpecParser<PVal = A1::PVal>,
559    B1: SpecMap<Input = A1::PVal>,
560    B2: SpecMap<Input = A2::PVal>,
561    OutVal,
562>(a1: A1, a2: A2, b1: B1, b2: B2) where
563    B1::Output: SpecParser<PVal = OutVal>,
564    B2::Output: SpecParser<PVal = OutVal>,
565
566    requires
567        forall|x: Seq<u8>| #[trigger] a1.spec_parse(x) == a2.spec_parse(x),
568        forall|key: A1::PVal, x: Seq<u8>| #[trigger]
569            b1.spec_map(key).spec_parse(x) == b2.spec_map(key).spec_parse(x),
570    ensures
571        forall|x: Seq<u8>| #[trigger] Bind(a1, b1).spec_parse(x) == Bind(a2, b2).spec_parse(x),
572{
573}
574
575// ----------------------------------------------------
576// Ref
577// ----------------------------------------------------
578pub proof fn lemma_ref_spec_parse_congruence<
579    Inner1: SpecParser,
580    Inner2: SpecParser<PVal = Inner1::PVal>,
581>(inner1: Inner1, inner2: Inner2)
582    requires
583        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
584    ensures
585        forall|x: Seq<u8>| #[trigger] Ref(inner1).spec_parse(x) == Ref(inner2).spec_parse(x),
586{
587}
588
589// ----------------------------------------------------
590// Named
591// ----------------------------------------------------
592pub proof fn lemma_named_spec_parse_congruence<
593    Inner1: SpecParser,
594    Inner2: SpecParser<PVal = Inner1::PVal>,
595>(name: &'static str, inner1: Inner1, inner2: Inner2)
596    requires
597        forall|x: Seq<u8>| #[trigger] inner1.spec_parse(x) == inner2.spec_parse(x),
598    ensures
599        forall|x: Seq<u8>| #[trigger]
600            Named(name, inner1).spec_parse(x) == Named(name, inner2).spec_parse(x),
601{
602}
603
604// ----------------------------------------------------
605// Star / Repeat / RepeatTillEnd
606// ----------------------------------------------------
607pub proof fn lemma_star_parse_rec_congruence<A: SpecParser, B: SpecParser<PVal = A::PVal>>(
608    a: A,
609    b: B,
610    ibuf: Seq<u8>,
611)
612    requires
613        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
614    ensures
615        Star(a).parse_rec(ibuf) == Star(b).parse_rec(ibuf),
616    decreases ibuf.len(),
617{
618    if let Some((n, _v)) = a.spec_parse(ibuf) {
619        if 0 < n <= ibuf.len() {
620            lemma_star_parse_rec_congruence(a, b, ibuf.skip(n));
621        }
622    }
623}
624
625pub proof fn lemma_star_spec_parse_congruence<A: SpecParser, B: SpecParser<PVal = A::PVal>>(
626    a: A,
627    b: B,
628)
629    requires
630        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
631    ensures
632        forall|x: Seq<u8>| #[trigger] Star(a).spec_parse(x) == Star(b).spec_parse(x),
633{
634    reveal(<Star::<_> as SpecParser>::spec_parse);
635    assert forall|x: Seq<u8>| #[trigger] Star(a).spec_parse(x) == Star(b).spec_parse(x) by {
636        lemma_star_parse_rec_congruence(a, b, x);
637    }
638}
639
640pub proof fn lemma_repeat_spec_parse_congruence<
641    A: SpecParser,
642    B: SpecParser<PVal = A::PVal>,
643    T: SpecParser,
644>(a: A, b: B, t: T)
645    requires
646        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
647    ensures
648        forall|x: Seq<u8>| #[trigger] Repeat(a, t).spec_parse(x) == Repeat(b, t).spec_parse(x),
649{
650    lemma_star_spec_parse_congruence(a, b);
651    lemma_pair_spec_parse_congruence(Star(a), Star(b), t, t);
652}
653
654pub proof fn lemma_repeat_till_end_spec_parse_congruence<
655    A: SpecParser,
656    B: SpecParser<PVal = A::PVal>,
657>(a: A, b: B)
658    requires
659        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
660    ensures
661        forall|x: Seq<u8>| #[trigger]
662            RepeatTillEnd(a).spec_parse(x) == RepeatTillEnd(b).spec_parse(x),
663{
664    lemma_repeat_spec_parse_congruence(a, b, Eof);
665}
666
667// ----------------------------------------------------
668// RepeatN
669// ----------------------------------------------------
670pub proof fn lemma_repeat_n_parse_n_rec_congruence<
671    A: SpecParser,
672    B: SpecParser<PVal = A::PVal>,
673    N: AsLen,
674>(a: &RepeatN<A, N>, b: &RepeatN<B, N>, count: nat, ibuf: Seq<u8>)
675    requires
676        forall|x: Seq<u8>| #[trigger] a.1.spec_parse(x) == b.1.spec_parse(x),
677    ensures
678        a.parse_n_rec(count, ibuf) == b.parse_n_rec(count, ibuf),
679    decreases count,
680{
681    if count == 0 {
682    } else {
683        assert(a.1.spec_parse(ibuf) == b.1.spec_parse(ibuf));
684        if let Some((n0, _)) = a.1.spec_parse(ibuf) {
685            lemma_repeat_n_parse_n_rec_congruence(a, b, (count - 1) as nat, ibuf.skip(n0));
686        }
687    }
688}
689
690pub proof fn lemma_repeat_n_spec_parse_congruence<
691    A: SpecParser,
692    B: SpecParser<PVal = A::PVal>,
693    N: AsLen,
694>(a: RepeatN<A, N>, b: RepeatN<B, N>)
695    requires
696        forall|x: Seq<u8>| #[trigger] a.1.spec_parse(x) == b.1.spec_parse(x),
697        a.0.as_nat() == b.0.as_nat(),
698    ensures
699        forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x),
700{
701    assert forall|x: Seq<u8>| #[trigger] a.spec_parse(x) == b.spec_parse(x) by {
702        lemma_repeat_n_parse_n_rec_congruence(&a, &b, a.0.as_nat(), x);
703    }
704}
705
706// ====================================================
707// Named parser-congruence lifting API
708// ====================================================
709pub broadcast proof fn lemma_exact_len_parser_congruence<
710    Inner1: SpecParser,
711    Inner2: SpecParser<PVal = Inner1::PVal>,
712    Len: AsLen,
713>(len: Len, inner1: Inner1, inner2: Inner2)
714    requires
715        parser_congruent(inner1, inner2),
716    ensures
717        #[trigger] parser_congruent(ExactLen(len, inner1), ExactLen(len, inner2)),
718{
719    reveal(parser_congruent);
720    lemma_exact_len_spec_parse_congruence(len, inner1, inner2);
721}
722
723pub broadcast proof fn lemma_pair_parser_congruence<
724    A1: SpecParser,
725    A2: SpecParser<PVal = A1::PVal>,
726    B1: SpecParser,
727    B2: SpecParser<PVal = B1::PVal>,
728>(a1: A1, a2: A2, b1: B1, b2: B2)
729    requires
730        parser_congruent(a1, a2),
731        parser_congruent(b1, b2),
732    ensures
733        #[trigger] parser_congruent(Pair(a1, b1), Pair(a2, b2)),
734{
735    reveal(parser_congruent);
736    lemma_pair_spec_parse_congruence(a1, a2, b1, b2);
737}
738
739pub broadcast proof fn lemma_ref_parser_congruence<
740    Inner1: SpecParser,
741    Inner2: SpecParser<PVal = Inner1::PVal>,
742>(inner1: Inner1, inner2: Inner2)
743    requires
744        parser_congruent(inner1, inner2),
745    ensures
746        #[trigger] parser_congruent(Ref(inner1), Ref(inner2)),
747{
748    reveal(parser_congruent);
749    lemma_ref_spec_parse_congruence(inner1, inner2);
750}
751
752pub broadcast proof fn lemma_named_parser_congruence<
753    Inner1: SpecParser,
754    Inner2: SpecParser<PVal = Inner1::PVal>,
755>(name1: &'static str, name2: &'static str, inner1: Inner1, inner2: Inner2)
756    requires
757        parser_congruent(inner1, inner2),
758    ensures
759        #[trigger] parser_congruent(Named(name1, inner1), Named(name2, inner2)),
760{
761    reveal(parser_congruent);
762}
763
764pub broadcast proof fn lemma_star_parser_congruence<A: SpecParser, B: SpecParser<PVal = A::PVal>>(
765    a: A,
766    b: B,
767)
768    requires
769        parser_congruent(a, b),
770    ensures
771        #[trigger] parser_congruent(Star(a), Star(b)),
772{
773    reveal(parser_congruent);
774    lemma_star_spec_parse_congruence(a, b);
775}
776
777pub broadcast proof fn lemma_repeat_parser_congruence<
778    A: SpecParser,
779    B: SpecParser<PVal = A::PVal>,
780    T1: SpecParser,
781    T2: SpecParser<PVal = T1::PVal>,
782>(a: A, b: B, t1: T1, t2: T2)
783    requires
784        parser_congruent(a, b),
785        parser_congruent(t1, t2),
786    ensures
787        #[trigger] parser_congruent(Repeat(a, t1), Repeat(b, t2)),
788{
789    reveal(parser_congruent);
790    lemma_star_spec_parse_congruence(a, b);
791    lemma_pair_spec_parse_congruence(Star(a), Star(b), t1, t2);
792}
793
794pub broadcast proof fn lemma_repeat_till_end_parser_congruence<
795    A: SpecParser,
796    B: SpecParser<PVal = A::PVal>,
797>(a: A, b: B)
798    requires
799        parser_congruent(a, b),
800    ensures
801        #[trigger] parser_congruent(RepeatTillEnd(a), RepeatTillEnd(b)),
802{
803    reveal(parser_congruent);
804    lemma_repeat_till_end_spec_parse_congruence(a, b);
805}
806
807pub broadcast proof fn lemma_repeat_n_parser_congruence<
808    A: SpecParser,
809    B: SpecParser<PVal = A::PVal>,
810    N: AsLen,
811>(a: RepeatN<A, N>, b: RepeatN<B, N>)
812    requires
813        parser_congruent(a.1, b.1),
814        a.0.as_nat() == b.0.as_nat(),
815    ensures
816        #[trigger] parser_congruent(a, b),
817{
818    reveal(parser_congruent);
819    lemma_repeat_n_spec_parse_congruence(a, b);
820}
821
822pub broadcast proof fn lemma_array_parser_congruence<
823    A: SpecParser,
824    B: SpecParser<PVal = A::PVal>,
825    const N: usize,
826>(a: A, b: B)
827    requires
828        parser_congruent(a, b),
829    ensures
830        #[trigger] parser_congruent(Array::<N, A>(a), Array::<N, B>(b)),
831{
832    reveal(parser_congruent);
833    lemma_repeat_n_spec_parse_congruence(RepeatN(N, a), RepeatN(N, b));
834}
835
836pub broadcast proof fn lemma_and_then_parser_congruence<
837    Tail1: SpecParser<PVal = Seq<u8>>,
838    Tail2: SpecParser<PVal = Seq<u8>>,
839    Then1: SpecParser,
840    Then2: SpecParser<PVal = Then1::PVal>,
841>(tail1: Tail1, tail2: Tail2, then1: Then1, then2: Then2)
842    requires
843        parser_congruent(tail1, tail2),
844        parser_congruent(then1, then2),
845    ensures
846        #[trigger] parser_congruent(AndThen(tail1, then1), AndThen(tail2, then2)),
847{
848    reveal(parser_congruent);
849    lemma_and_then_spec_parse_congruence(tail1, tail2, then1, then2);
850}
851
852pub broadcast proof fn lemma_mapped_parser_congruence<
853    Inner1: SpecParser,
854    Inner2: SpecParser<PVal = Inner1::PVal>,
855    M1: crate::combinators::mapped::spec::SpecMapper<In = Inner1::PVal>,
856    M2: crate::combinators::mapped::spec::SpecMapper<In = Inner2::PVal, Out = M1::Out>,
857>(inner1: Inner1, inner2: Inner2, mapper1: M1, mapper2: M2)
858    requires
859        parser_congruent(inner1, inner2),
860        forall|v: Inner1::PVal| #[trigger] mapper1.spec_map(v) == mapper2.spec_map(v),
861    ensures
862        #[trigger] parser_congruent(
863            Mapped { inner: inner1, mapper: mapper1 },
864            Mapped { inner: inner2, mapper: mapper2 },
865        ),
866{
867    reveal(parser_congruent);
868    lemma_mapped_spec_parse_congruence(inner1, inner2, mapper1, mapper2);
869}
870
871pub broadcast proof fn lemma_refined_parser_congruence<
872    Inner1: SpecParser,
873    Inner2: SpecParser<PVal = Inner1::PVal>,
874    P1: SpecPred<Inner1::PVal>,
875    P2: SpecPred<Inner1::PVal>,
876>(a: Refined<Inner1, P1>, b: Refined<Inner2, P2>)
877    requires
878        parser_congruent(a.0, b.0),
879        forall|v: Inner1::PVal| #[trigger] a.1.apply(v) <==> b.1.apply(v),
880    ensures
881        #[trigger] parser_congruent(a, b),
882{
883    reveal(parser_congruent);
884}
885
886pub broadcast proof fn lemma_const_parser_congruence<
887    Inner1: SpecParser<PVal = T>,
888    Inner2: SpecParser<PVal = T>,
889    T,
890>(a: Const<Inner1, T>, b: Const<Inner2, T>)
891    requires
892        parser_congruent(a.0, b.0),
893        a.1 == b.1,
894    ensures
895        #[trigger] parser_congruent(a, b),
896{
897    reveal(parser_congruent);
898}
899
900pub broadcast proof fn lemma_cond_parser_congruence<
901    Inner1: SpecParser,
902    Inner2: SpecParser<PVal = Inner1::PVal>,
903>(a: Cond<Inner1>, b: Cond<Inner2>)
904    requires
905        a.0 == b.0,
906        parser_congruent(a.1, b.1),
907    ensures
908        #[trigger] parser_congruent(a, b),
909{
910    reveal(parser_congruent);
911}
912
913pub broadcast proof fn lemma_choice_parser_congruence<
914    A1: SpecParser,
915    A2: SpecParser<PVal = A1::PVal>,
916    B1: SpecParser,
917    B2: SpecParser<PVal = B1::PVal>,
918>(a1: A1, a2: A2, b1: B1, b2: B2)
919    requires
920        parser_congruent(a1, a2),
921        parser_congruent(b1, b2),
922    ensures
923        #[trigger] parser_congruent(Choice(a1, b1), Choice(a2, b2)),
924{
925    reveal(parser_congruent);
926    lemma_choice_spec_parse_congruence(a1, a2, b1, b2);
927}
928
929pub broadcast proof fn lemma_alt_parser_congruence<
930    const NONDETERMINISTIC: bool,
931    A1: SpecParser,
932    A2: SpecParser<PVal = A1::PVal>,
933    B1: SpecParser<PVal = A1::PVal>,
934    B2: SpecParser<PVal = A1::PVal>,
935>(a1: A1, a2: A2, b1: B1, b2: B2)
936    requires
937        parser_congruent(a1, a2),
938        parser_congruent(b1, b2),
939    ensures
940        #[trigger] parser_congruent(
941            Alt::<A1, B1, NONDETERMINISTIC>(a1, b1),
942            Alt::<A2, B2, NONDETERMINISTIC>(a2, b2),
943        ),
944{
945    reveal(parser_congruent);
946    lemma_alt_spec_parse_congruence::<NONDETERMINISTIC, _, _, _, _>(a1, a2, b1, b2);
947}
948
949pub broadcast proof fn lemma_opt_parser_congruence<A: SpecParser, B: SpecParser<PVal = A::PVal>>(
950    a: A,
951    b: B,
952)
953    requires
954        parser_congruent(a, b),
955    ensures
956        #[trigger] parser_congruent(Opt(a), Opt(b)),
957{
958    reveal(parser_congruent);
959    lemma_opt_spec_parse_congruence(a, b);
960}
961
962pub broadcast proof fn lemma_optional_parser_congruence<
963    A1: SpecParser,
964    A2: SpecParser<PVal = A1::PVal>,
965    B1: SpecParser,
966    B2: SpecParser<PVal = B1::PVal>,
967>(a1: A1, a2: A2, b1: B1, b2: B2)
968    requires
969        parser_congruent(a1, a2),
970        parser_congruent(b1, b2),
971    ensures
972        #[trigger] parser_congruent(Optional(a1, b1), Optional(a2, b2)),
973{
974    reveal(parser_congruent);
975    lemma_optional_spec_parse_congruence(a1, a2, b1, b2);
976}
977
978pub broadcast proof fn lemma_optional_end_parser_congruence<
979    A: SpecParser,
980    B: SpecParser<PVal = A::PVal>,
981>(a: A, b: B)
982    requires
983        parser_congruent(a, b),
984    ensures
985        #[trigger] parser_congruent(OptionalEnd(a), OptionalEnd(b)),
986{
987    reveal(parser_congruent);
988    lemma_optional_end_spec_parse_congruence(a, b);
989}
990
991pub broadcast proof fn lemma_preceded_parser_congruence<
992    const CHECK: bool,
993    A1: SpecParser<PVal = AVal>,
994    A2: SpecParser<PVal = AVal>,
995    B1: SpecParser,
996    B2: SpecParser<PVal = B1::PVal>,
997    AVal,
998>(a: Preceded<A1, AVal, B1, CHECK>, b: Preceded<A2, AVal, B2, CHECK>)
999    requires
1000        parser_congruent(a.a, b.a),
1001        parser_congruent(a.b, b.b),
1002        a.a_val == b.a_val,
1003    ensures
1004        #[trigger] parser_congruent(a, b),
1005{
1006    reveal(parser_congruent);
1007    lemma_preceded_spec_parse_congruence::<CHECK, _, _, _, _, _>(a.a, b.a, a.b, b.b, a.a_val);
1008}
1009
1010pub broadcast proof fn lemma_terminated_parser_congruence<
1011    const CHECK: bool,
1012    A1: SpecParser,
1013    A2: SpecParser<PVal = A1::PVal>,
1014    B1: SpecParser<PVal = BVal>,
1015    B2: SpecParser<PVal = BVal>,
1016    BVal,
1017>(a: Terminated<A1, B1, BVal, CHECK>, b: Terminated<A2, B2, BVal, CHECK>)
1018    requires
1019        parser_congruent(a.a, b.a),
1020        parser_congruent(a.b, b.b),
1021        a.b_val == b.b_val,
1022    ensures
1023        #[trigger] parser_congruent(a, b),
1024{
1025    reveal(parser_congruent);
1026    lemma_terminated_spec_parse_congruence::<CHECK, _, _, _, _, _>(a.a, b.a, a.b, b.b, a.b_val);
1027}
1028
1029pub broadcast proof fn lemma_bind_parser_congruence<
1030    A1: SpecParser,
1031    A2: SpecParser<PVal = A1::PVal>,
1032    B1: SpecMap<Input = A1::PVal>,
1033    B2: SpecMap<Input = A2::PVal>,
1034>(a: Bind<A1, B1>, b: Bind<A2, B2>) where
1035    B1::Output: SpecParser,
1036    B2::Output: SpecParser<PVal = <B1::Output as SpecParser>::PVal>,
1037
1038    requires
1039        parser_congruent(a.0, b.0),
1040        forall|key: A1::PVal| #[trigger] parser_congruent(a.1.spec_map(key), b.1.spec_map(key)),
1041    ensures
1042        #[trigger] parser_congruent(a, b),
1043{
1044    reveal(parser_congruent);
1045    broadcast use lemma_parser_congruent_apply;
1046
1047    lemma_bind_spec_parse_congruence(a.0, b.0, a.1, b.1);
1048}
1049
1050pub broadcast proof fn lemma_sum_parser_congruence<
1051    A1: SpecParser,
1052    A2: SpecParser<PVal = A1::PVal>,
1053    B1: SpecParser,
1054    B2: SpecParser<PVal = B1::PVal>,
1055>(a: Sum<A1, B1>, b: Sum<A2, B2>)
1056    requires
1057        match (a, b) {
1058            (Sum::Inl(a), Sum::Inl(b)) => parser_congruent(a, b),
1059            (Sum::Inr(a), Sum::Inr(b)) => parser_congruent(a, b),
1060            _ => false,
1061        },
1062    ensures
1063        #[trigger] parser_congruent(a, b),
1064{
1065    reveal(parser_congruent);
1066    match (a, b) {
1067        (Sum::Inl(a), Sum::Inl(b)) => lemma_sum_spec_parse_congruence(a, b, a, b),
1068        (Sum::Inr(a), Sum::Inr(b)) => lemma_sum_spec_parse_congruence(a, b, a, b),
1069        _ => {},
1070    }
1071}
1072
1073// ====================================================
1074// Preparation / serializer congruence: unary formats
1075// ====================================================
1076pub broadcast proof fn lemma_exact_len_prepare_congruence<A, B, L1, L2>(
1077    a: ExactLen<A, L1>,
1078    b: ExactLen<B, L2>,
1079) where
1080    A: Consistency + SpecByteLen<T = A::Val>,
1081    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1082    L1: AsLen,
1083    L2: AsLen,
1084
1085    requires
1086        prepare_congruent(a.1, b.1),
1087        a.0.as_nat() == b.0.as_nat(),
1088    ensures
1089        #[trigger] prepare_congruent(a, b),
1090{
1091    reveal(prepare_congruent);
1092}
1093
1094pub broadcast proof fn lemma_exact_len_serializer_congruence<A, B, L1, L2>(
1095    a: ExactLen<A, L1>,
1096    b: ExactLen<B, L2>,
1097) where
1098    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1099    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1100    L1: AsLen,
1101    L2: AsLen,
1102
1103    requires
1104        serializer_congruent(a.1, b.1),
1105        a.0.as_nat() == b.0.as_nat(),
1106    ensures
1107        #[trigger] serializer_congruent(a, b),
1108{
1109    reveal(serializer_congruent);
1110    lemma_exact_len_prepare_congruence(a, b);
1111}
1112
1113pub broadcast proof fn lemma_refined_prepare_congruence<A, B, P1, P2>(
1114    a: Refined<A, P1>,
1115    b: Refined<B, P2>,
1116) where
1117    A: Consistency + SpecByteLen<T = A::Val>,
1118    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1119    P1: SpecPred<A::Val>,
1120    P2: SpecPred<A::Val>,
1121
1122    requires
1123        prepare_congruent(a.0, b.0),
1124        forall|v: A::Val| #[trigger] a.1.apply(v) <==> b.1.apply(v),
1125    ensures
1126        #[trigger] prepare_congruent(a, b),
1127{
1128    reveal(prepare_congruent);
1129}
1130
1131pub broadcast proof fn lemma_refined_serializer_congruence<A, B, P1, P2>(
1132    a: Refined<A, P1>,
1133    b: Refined<B, P2>,
1134) where
1135    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1136    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1137    P1: SpecPred<A::Val>,
1138    P2: SpecPred<A::Val>,
1139
1140    requires
1141        serializer_congruent(a.0, b.0),
1142        forall|v: A::Val| #[trigger] a.1.apply(v) <==> b.1.apply(v),
1143    ensures
1144        #[trigger] serializer_congruent(a, b),
1145{
1146    reveal(serializer_congruent);
1147    lemma_refined_prepare_congruence(a, b);
1148}
1149
1150pub broadcast proof fn lemma_cond_prepare_congruence<A, B>(a: Cond<A>, b: Cond<B>) where
1151    A: Consistency + SpecByteLen<T = A::Val>,
1152    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1153
1154    requires
1155        a.0 == b.0,
1156        prepare_congruent(a.1, b.1),
1157    ensures
1158        #[trigger] prepare_congruent(a, b),
1159{
1160    reveal(prepare_congruent);
1161}
1162
1163pub broadcast proof fn lemma_cond_serializer_congruence<A, B>(a: Cond<A>, b: Cond<B>) where
1164    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1165    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1166
1167    requires
1168        a.0 == b.0,
1169        serializer_congruent(a.1, b.1),
1170    ensures
1171        #[trigger] serializer_congruent(a, b),
1172{
1173    reveal(serializer_congruent);
1174    lemma_cond_prepare_congruence(a, b);
1175}
1176
1177pub broadcast proof fn lemma_const_prepare_congruence<A, B>(
1178    a: Const<A, A::Val>,
1179    b: Const<B, A::Val>,
1180) where
1181    A: Consistency + SpecByteLen<T = A::Val>,
1182    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1183
1184    requires
1185        a.1 == b.1,
1186        prepare_congruent(a.0, b.0),
1187    ensures
1188        #[trigger] prepare_congruent(a, b),
1189{
1190    reveal(prepare_congruent);
1191}
1192
1193pub broadcast proof fn lemma_const_serializer_congruence<A, B>(
1194    a: Const<A, A::Val>,
1195    b: Const<B, A::Val>,
1196) where
1197    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1198    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1199
1200    requires
1201        a.1 == b.1,
1202        serializer_congruent(a.0, b.0),
1203    ensures
1204        #[trigger] serializer_congruent(a, b),
1205{
1206    reveal(serializer_congruent);
1207    lemma_const_prepare_congruence(a, b);
1208}
1209
1210pub broadcast proof fn lemma_opt_prepare_congruence<A, B>(a: Opt<A>, b: Opt<B>) where
1211    A: Consistency + SpecByteLen<T = A::Val>,
1212    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1213
1214    requires
1215        prepare_congruent(a.0, b.0),
1216    ensures
1217        #[trigger] prepare_congruent(a, b),
1218{
1219    reveal(prepare_congruent);
1220}
1221
1222pub broadcast proof fn lemma_opt_serializer_congruence<A, B>(a: Opt<A>, b: Opt<B>) where
1223    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1224    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1225
1226    requires
1227        serializer_congruent(a.0, b.0),
1228    ensures
1229        #[trigger] serializer_congruent(a, b),
1230{
1231    reveal(serializer_congruent);
1232    lemma_opt_prepare_congruence(a, b);
1233}
1234
1235pub broadcast proof fn lemma_ref_prepare_congruence<A, B>(a: Ref<A>, b: Ref<B>) where
1236    A: Consistency + SpecByteLen<T = A::Val>,
1237    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1238
1239    requires
1240        prepare_congruent(a.0, b.0),
1241    ensures
1242        #[trigger] prepare_congruent(a, b),
1243{
1244    reveal(prepare_congruent);
1245}
1246
1247pub broadcast proof fn lemma_ref_serializer_congruence<A, B>(a: Ref<A>, b: Ref<B>) where
1248    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1249    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1250
1251    requires
1252        serializer_congruent(a.0, b.0),
1253    ensures
1254        #[trigger] serializer_congruent(a, b),
1255{
1256    reveal(serializer_congruent);
1257    lemma_ref_prepare_congruence(a, b);
1258}
1259
1260pub broadcast proof fn lemma_named_prepare_congruence<A, B>(a: Named<A>, b: Named<B>) where
1261    A: Consistency + SpecByteLen<T = A::Val>,
1262    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1263
1264    requires
1265        prepare_congruent(a.1, b.1),
1266    ensures
1267        #[trigger] prepare_congruent(a, b),
1268{
1269    reveal(prepare_congruent);
1270}
1271
1272pub broadcast proof fn lemma_named_serializer_congruence<A, B>(a: Named<A>, b: Named<B>) where
1273    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1274    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1275
1276    requires
1277        serializer_congruent(a.1, b.1),
1278    ensures
1279        #[trigger] serializer_congruent(a, b),
1280{
1281    reveal(serializer_congruent);
1282    lemma_named_prepare_congruence(a, b);
1283}
1284
1285// ====================================================
1286// Preparation / serializer congruence: compositions
1287// ====================================================
1288proof fn lemma_star_byte_len_congruence_rec<A, B>(a: A, b: B, vs: Seq<A::Val>) where
1289    A: Consistency + SpecByteLen<T = A::Val>,
1290    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1291
1292    requires
1293        prepare_congruent(a, b),
1294    ensures
1295        Star(a).byte_len(vs) == Star(b).byte_len(vs),
1296    decreases vs.len(),
1297{
1298    reveal(prepare_congruent);
1299    reveal(<Star::<_> as SpecByteLen>::byte_len);
1300    if vs.len() > 0 {
1301        lemma_star_byte_len_congruence_rec(a, b, vs.drop_last());
1302    }
1303}
1304
1305proof fn lemma_star_serialize_congruence_rec<A, B>(a: A, b: B, vs: Seq<A::Val>) where
1306    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1307    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1308
1309    requires
1310        serializer_congruent(a, b),
1311    ensures
1312        Star(a).spec_serialize(vs) == Star(b).spec_serialize(vs),
1313    decreases vs.len(),
1314{
1315    reveal(serializer_congruent);
1316    reveal(<Star::<_> as SpecSerializer>::spec_serialize);
1317    if vs.len() > 0 {
1318        lemma_star_serialize_congruence_rec(a, b, vs.drop_last());
1319    }
1320}
1321
1322pub broadcast proof fn lemma_star_prepare_congruence<A, B>(a: Star<A>, b: Star<B>) where
1323    A: Consistency + SpecByteLen<T = A::Val>,
1324    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1325
1326    requires
1327        prepare_congruent(a.0, b.0),
1328    ensures
1329        #[trigger] prepare_congruent(a, b),
1330{
1331    reveal(prepare_congruent);
1332    reveal(<Star::<_> as Consistency>::consistent);
1333    assert forall|vs: Seq<A::Val>| #[trigger] a.byte_len(vs) == b.byte_len(vs) by {
1334        lemma_star_byte_len_congruence_rec(a.0, b.0, vs);
1335    }
1336}
1337
1338pub broadcast proof fn lemma_star_serializer_congruence<A, B>(a: Star<A>, b: Star<B>) where
1339    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1340    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1341
1342    requires
1343        serializer_congruent(a.0, b.0),
1344    ensures
1345        #[trigger] serializer_congruent(a, b),
1346{
1347    reveal(serializer_congruent);
1348    lemma_star_prepare_congruence(a, b);
1349    assert forall|vs: Seq<A::Val>| #[trigger] a.spec_serialize(vs) == b.spec_serialize(vs) by {
1350        lemma_star_serialize_congruence_rec(a.0, b.0, vs);
1351    }
1352}
1353
1354pub broadcast proof fn lemma_pair_prepare_congruence<A1, A2, B1, B2>(
1355    a: Pair<A1, B1>,
1356    b: Pair<A2, B2>,
1357) where
1358    A1: Consistency + SpecByteLen<T = A1::Val>,
1359    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1360    B1: Consistency + SpecByteLen<T = B1::Val>,
1361    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1362
1363    requires
1364        prepare_congruent(a.0, b.0),
1365        prepare_congruent(a.1, b.1),
1366    ensures
1367        #[trigger] prepare_congruent(a, b),
1368{
1369    reveal(prepare_congruent);
1370}
1371
1372pub broadcast proof fn lemma_pair_serializer_congruence<A1, A2, B1, B2>(
1373    a: Pair<A1, B1>,
1374    b: Pair<A2, B2>,
1375) where
1376    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1377    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1378    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1379    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1380
1381    requires
1382        serializer_congruent(a.0, b.0),
1383        serializer_congruent(a.1, b.1),
1384    ensures
1385        #[trigger] serializer_congruent(a, b),
1386{
1387    reveal(serializer_congruent);
1388    lemma_pair_prepare_congruence(a, b);
1389}
1390
1391pub broadcast proof fn lemma_choice_prepare_congruence<A1, A2, B1, B2>(
1392    a: Choice<A1, B1>,
1393    b: Choice<A2, B2>,
1394) where
1395    A1: Consistency + SpecByteLen<T = A1::Val>,
1396    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1397    B1: Consistency + SpecByteLen<T = B1::Val>,
1398    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1399
1400    requires
1401        prepare_congruent(a.0, b.0),
1402        prepare_congruent(a.1, b.1),
1403    ensures
1404        #[trigger] prepare_congruent(a, b),
1405{
1406    reveal(prepare_congruent);
1407}
1408
1409pub broadcast proof fn lemma_choice_serializer_congruence<A1, A2, B1, B2>(
1410    a: Choice<A1, B1>,
1411    b: Choice<A2, B2>,
1412) where
1413    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1414    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1415    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1416    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1417
1418    requires
1419        serializer_congruent(a.0, b.0),
1420        serializer_congruent(a.1, b.1),
1421    ensures
1422        #[trigger] serializer_congruent(a, b),
1423{
1424    reveal(serializer_congruent);
1425    lemma_choice_prepare_congruence(a, b);
1426}
1427
1428pub broadcast proof fn lemma_optional_prepare_congruence<A1, A2, B1, B2>(
1429    a: Optional<A1, B1>,
1430    b: Optional<A2, B2>,
1431) where
1432    A1: Consistency + SpecByteLen<T = A1::Val>,
1433    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1434    B1: Consistency + SpecByteLen<T = B1::Val>,
1435    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1436
1437    requires
1438        prepare_congruent(a.0, b.0),
1439        prepare_congruent(a.1, b.1),
1440    ensures
1441        #[trigger] prepare_congruent(a, b),
1442{
1443    reveal(prepare_congruent);
1444    lemma_opt_prepare_congruence(Opt(a.0), Opt(b.0));
1445    lemma_pair_prepare_congruence(Pair(Opt(a.0), a.1), Pair(Opt(b.0), b.1));
1446}
1447
1448pub broadcast proof fn lemma_optional_serializer_congruence<A1, A2, B1, B2>(
1449    a: Optional<A1, B1>,
1450    b: Optional<A2, B2>,
1451) where
1452    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1453    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1454    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1455    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1456
1457    requires
1458        serializer_congruent(a.0, b.0),
1459        serializer_congruent(a.1, b.1),
1460    ensures
1461        #[trigger] serializer_congruent(a, b),
1462{
1463    reveal(serializer_congruent);
1464    lemma_optional_prepare_congruence(a, b);
1465}
1466
1467pub broadcast proof fn lemma_repeat_prepare_congruence<A1, A2, B1, B2>(
1468    a: Repeat<A1, B1>,
1469    b: Repeat<A2, B2>,
1470) where
1471    A1: Consistency + SpecByteLen<T = A1::Val>,
1472    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1473    B1: Consistency + SpecByteLen<T = B1::Val>,
1474    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1475
1476    requires
1477        prepare_congruent(a.0, b.0),
1478        prepare_congruent(a.1, b.1),
1479    ensures
1480        #[trigger] prepare_congruent(a, b),
1481{
1482    reveal(prepare_congruent);
1483    lemma_star_prepare_congruence(Star(a.0), Star(b.0));
1484    lemma_pair_prepare_congruence(Pair(Star(a.0), a.1), Pair(Star(b.0), b.1));
1485}
1486
1487pub broadcast proof fn lemma_repeat_serializer_congruence<A1, A2, B1, B2>(
1488    a: Repeat<A1, B1>,
1489    b: Repeat<A2, B2>,
1490) where
1491    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1492    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1493    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1494    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1495
1496    requires
1497        serializer_congruent(a.0, b.0),
1498        serializer_congruent(a.1, b.1),
1499    ensures
1500        #[trigger] serializer_congruent(a, b),
1501{
1502    reveal(serializer_congruent);
1503    lemma_repeat_prepare_congruence(a, b);
1504    lemma_star_serializer_congruence(Star(a.0), Star(b.0));
1505}
1506
1507pub broadcast proof fn lemma_repeat_n_prepare_congruence<A, B, N1, N2>(
1508    a: RepeatN<A, N1>,
1509    b: RepeatN<B, N2>,
1510) where
1511    A: Consistency + SpecByteLen<T = A::Val>,
1512    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1513    N1: AsLen,
1514    N2: AsLen,
1515
1516    requires
1517        prepare_congruent(a.1, b.1),
1518        a.0.as_nat() == b.0.as_nat(),
1519    ensures
1520        #[trigger] prepare_congruent(a, b),
1521{
1522    reveal(prepare_congruent);
1523    lemma_star_prepare_congruence(Star(a.1), Star(b.1));
1524}
1525
1526pub broadcast proof fn lemma_repeat_n_serializer_congruence<A, B, N1, N2>(
1527    a: RepeatN<A, N1>,
1528    b: RepeatN<B, N2>,
1529) where
1530    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1531    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1532    N1: AsLen,
1533    N2: AsLen,
1534
1535    requires
1536        serializer_congruent(a.1, b.1),
1537        a.0.as_nat() == b.0.as_nat(),
1538    ensures
1539        #[trigger] serializer_congruent(a, b),
1540{
1541    reveal(serializer_congruent);
1542    reveal(<Star::<_> as SpecSerializer>::spec_serialize);
1543    broadcast use lemma_serializer_congruent_serialize;
1544
1545    lemma_repeat_n_prepare_congruence(a, b);
1546    lemma_star_serializer_congruence(Star(a.1), Star(b.1));
1547    assert forall|vs: Seq<A::Val>| #[trigger] a.spec_serialize(vs) == b.spec_serialize(vs) by {
1548        lemma_star_serialize_congruence_rec(a.1, b.1, vs);
1549    }
1550}
1551
1552pub broadcast proof fn lemma_array_prepare_congruence<A, B, const N: usize>(
1553    a: Array<N, A>,
1554    b: Array<N, B>,
1555) where
1556    A: Consistency + SpecByteLen<T = A::Val>,
1557    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1558
1559    requires
1560        prepare_congruent(a.0, b.0),
1561    ensures
1562        #[trigger] prepare_congruent(a, b),
1563{
1564    reveal(prepare_congruent);
1565    lemma_repeat_n_prepare_congruence(RepeatN(N, a.0), RepeatN(N, b.0));
1566}
1567
1568pub broadcast proof fn lemma_array_serializer_congruence<A, B, const N: usize>(
1569    a: Array<N, A>,
1570    b: Array<N, B>,
1571) where
1572    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1573    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1574
1575    requires
1576        serializer_congruent(a.0, b.0),
1577    ensures
1578        #[trigger] serializer_congruent(a, b),
1579{
1580    reveal(serializer_congruent);
1581    lemma_array_prepare_congruence(a, b);
1582    lemma_repeat_n_serializer_congruence(RepeatN(N, a.0), RepeatN(N, b.0));
1583}
1584
1585pub broadcast proof fn lemma_optional_end_prepare_congruence<A, B>(
1586    a: OptionalEnd<A>,
1587    b: OptionalEnd<B>,
1588) where
1589    A: Consistency + SpecByteLen<T = A::Val>,
1590    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1591
1592    requires
1593        prepare_congruent(a.0, b.0),
1594    ensures
1595        #[trigger] prepare_congruent(a, b),
1596{
1597    reveal(prepare_congruent);
1598    lemma_prepare_congruent_reflexive(Eof);
1599    lemma_optional_prepare_congruence(Optional(a.0, Eof), Optional(b.0, Eof));
1600}
1601
1602pub broadcast proof fn lemma_optional_end_serializer_congruence<A, B>(
1603    a: OptionalEnd<A>,
1604    b: OptionalEnd<B>,
1605) where
1606    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1607    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1608
1609    requires
1610        serializer_congruent(a.0, b.0),
1611    ensures
1612        #[trigger] serializer_congruent(a, b),
1613{
1614    reveal(serializer_congruent);
1615    lemma_optional_end_prepare_congruence(a, b);
1616    lemma_serializer_congruent_reflexive(Eof);
1617    lemma_optional_serializer_congruence(Optional(a.0, Eof), Optional(b.0, Eof));
1618}
1619
1620pub broadcast proof fn lemma_repeat_till_end_prepare_congruence<A, B>(
1621    a: RepeatTillEnd<A>,
1622    b: RepeatTillEnd<B>,
1623) where
1624    A: Consistency + SpecByteLen<T = A::Val>,
1625    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1626
1627    requires
1628        prepare_congruent(a.0, b.0),
1629    ensures
1630        #[trigger] prepare_congruent(a, b),
1631{
1632    reveal(prepare_congruent);
1633    lemma_prepare_congruent_reflexive(Eof);
1634    lemma_repeat_prepare_congruence(Repeat(a.0, Eof), Repeat(b.0, Eof));
1635}
1636
1637pub broadcast proof fn lemma_repeat_till_end_serializer_congruence<A, B>(
1638    a: RepeatTillEnd<A>,
1639    b: RepeatTillEnd<B>,
1640) where
1641    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1642    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1643
1644    requires
1645        serializer_congruent(a.0, b.0),
1646    ensures
1647        #[trigger] serializer_congruent(a, b),
1648{
1649    reveal(serializer_congruent);
1650    lemma_repeat_till_end_prepare_congruence(a, b);
1651    lemma_serializer_congruent_reflexive(Eof);
1652    lemma_repeat_serializer_congruence(Repeat(a.0, Eof), Repeat(b.0, Eof));
1653}
1654
1655pub broadcast proof fn lemma_preceded_prepare_congruence<A1, A2, B1, B2, const CHECK: bool>(
1656    a: Preceded<A1, A1::Val, B1, CHECK>,
1657    b: Preceded<A2, A1::Val, B2, CHECK>,
1658) where
1659    A1: Consistency + SpecByteLen<T = A1::Val>,
1660    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1661    B1: Consistency + SpecByteLen<T = B1::Val>,
1662    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1663
1664    requires
1665        prepare_congruent(a.a, b.a),
1666        prepare_congruent(a.b, b.b),
1667        a.a_val == b.a_val,
1668    ensures
1669        #[trigger] prepare_congruent(a, b),
1670{
1671    reveal(prepare_congruent);
1672}
1673
1674pub broadcast proof fn lemma_preceded_serializer_congruence<A1, A2, B1, B2, const CHECK: bool>(
1675    a: Preceded<A1, A1::Val, B1, CHECK>,
1676    b: Preceded<A2, A1::Val, B2, CHECK>,
1677) where
1678    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1679    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1680    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1681    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1682
1683    requires
1684        serializer_congruent(a.a, b.a),
1685        serializer_congruent(a.b, b.b),
1686        a.a_val == b.a_val,
1687    ensures
1688        #[trigger] serializer_congruent(a, b),
1689{
1690    reveal(serializer_congruent);
1691    lemma_preceded_prepare_congruence(a, b);
1692}
1693
1694pub broadcast proof fn lemma_terminated_prepare_congruence<A1, A2, B1, B2, const CHECK: bool>(
1695    a: Terminated<A1, B1, B1::Val, CHECK>,
1696    b: Terminated<A2, B2, B1::Val, CHECK>,
1697) where
1698    A1: Consistency + SpecByteLen<T = A1::Val>,
1699    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1700    B1: Consistency + SpecByteLen<T = B1::Val>,
1701    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1702
1703    requires
1704        prepare_congruent(a.a, b.a),
1705        prepare_congruent(a.b, b.b),
1706        a.b_val == b.b_val,
1707    ensures
1708        #[trigger] prepare_congruent(a, b),
1709{
1710    reveal(prepare_congruent);
1711}
1712
1713pub broadcast proof fn lemma_terminated_serializer_congruence<A1, A2, B1, B2, const CHECK: bool>(
1714    a: Terminated<A1, B1, B1::Val, CHECK>,
1715    b: Terminated<A2, B2, B1::Val, CHECK>,
1716) where
1717    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1718    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1719    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1720    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1721
1722    requires
1723        serializer_congruent(a.a, b.a),
1724        serializer_congruent(a.b, b.b),
1725        a.b_val == b.b_val,
1726    ensures
1727        #[trigger] serializer_congruent(a, b),
1728{
1729    reveal(serializer_congruent);
1730    lemma_terminated_prepare_congruence(a, b);
1731}
1732
1733pub broadcast proof fn lemma_and_then_prepare_congruence<A1, A2, B1, B2>(
1734    a: AndThen<A1, B1>,
1735    b: AndThen<A2, B2>,
1736) where
1737    A1: BytesCombinator + Consistency<Val = Seq<u8>>,
1738    A2: BytesCombinator + Consistency<Val = Seq<u8>>,
1739    B1: Consistency + SpecByteLen<T = B1::Val>,
1740    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1741
1742    requires
1743        prepare_congruent(a.0, b.0),
1744        prepare_congruent(a.1, b.1),
1745    ensures
1746        #[trigger] prepare_congruent(a, b),
1747{
1748    reveal(prepare_congruent);
1749}
1750
1751pub broadcast proof fn lemma_and_then_serializer_congruence<A1, A2, B1, B2>(
1752    a: AndThen<A1, B1>,
1753    b: AndThen<A2, B2>,
1754) where
1755    A1: BytesCombinator + Consistency<Val = Seq<u8>> + SpecSerializer<SVal = Seq<u8>>,
1756    A2: BytesCombinator + Consistency<Val = Seq<u8>> + SpecSerializer<SVal = Seq<u8>>,
1757    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1758    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1759
1760    requires
1761        serializer_congruent(a.0, b.0),
1762        serializer_congruent(a.1, b.1),
1763    ensures
1764        #[trigger] serializer_congruent(a, b),
1765{
1766    reveal(serializer_congruent);
1767    lemma_and_then_prepare_congruence(a, b);
1768}
1769
1770pub broadcast proof fn lemma_alt_prepare_congruence<A1, A2, B1, B2, const NONDETERMINISTIC: bool>(
1771    a: Alt<A1, B1, NONDETERMINISTIC>,
1772    b: Alt<A2, B2, NONDETERMINISTIC>,
1773) where
1774    A1: Consistency + SpecByteLen<T = A1::Val>,
1775    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1776    B1: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1777    B2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1778
1779    requires
1780        prepare_congruent(a.0, b.0),
1781        prepare_congruent(a.1, b.1),
1782    ensures
1783        #[trigger] prepare_congruent(a, b),
1784{
1785    reveal(prepare_congruent);
1786}
1787
1788pub broadcast proof fn lemma_alt_serializer_congruence<
1789    A1,
1790    A2,
1791    B1,
1792    B2,
1793    const NONDETERMINISTIC: bool,
1794>(a: Alt<A1, B1, NONDETERMINISTIC>, b: Alt<A2, B2, NONDETERMINISTIC>) where
1795    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1796    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1797    B1: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1798    B2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1799
1800    requires
1801        serializer_congruent(a.0, b.0),
1802        serializer_congruent(a.1, b.1),
1803    ensures
1804        #[trigger] serializer_congruent(a, b),
1805{
1806    reveal(serializer_congruent);
1807    broadcast use lemma_serializer_congruent_prepare;
1808    broadcast use lemma_prepare_congruent_consistent;
1809    broadcast use lemma_serializer_congruent_serialize;
1810
1811    lemma_alt_prepare_congruence(a, b);
1812}
1813
1814pub broadcast proof fn lemma_mapped_prepare_congruence<A, B, M1, M2>(
1815    a: Mapped<A, M1>,
1816    b: Mapped<B, M2>,
1817) where
1818    A: Consistency + SpecByteLen<T = A::Val>,
1819    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val>,
1820    M1: crate::combinators::mapped::spec::SpecMapper<In = A::Val>,
1821    M2: crate::combinators::mapped::spec::SpecMapper<In = A::Val, Out = M1::Out>,
1822
1823    requires
1824        prepare_congruent(a.inner, b.inner),
1825        forall|v: M1::Out| #[trigger] a.mapper.spec_map_rev(v) == b.mapper.spec_map_rev(v),
1826        forall|v: M1::Out| #[trigger] a.mapper.wf_out(v) <==> b.mapper.wf_out(v),
1827    ensures
1828        #[trigger] prepare_congruent(a, b),
1829{
1830    reveal(prepare_congruent);
1831}
1832
1833pub broadcast proof fn lemma_mapped_serializer_congruence<A, B, M1, M2>(
1834    a: Mapped<A, M1>,
1835    b: Mapped<B, M2>,
1836) where
1837    A: Consistency + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1838    B: Consistency<Val = A::Val> + SpecByteLen<T = A::Val> + SpecSerializer<SVal = A::Val>,
1839    M1: crate::combinators::mapped::spec::SpecMapper<In = A::Val>,
1840    M2: crate::combinators::mapped::spec::SpecMapper<In = A::Val, Out = M1::Out>,
1841
1842    requires
1843        serializer_congruent(a.inner, b.inner),
1844        forall|v: M1::Out| #[trigger] a.mapper.spec_map_rev(v) == b.mapper.spec_map_rev(v),
1845        forall|v: M1::Out| #[trigger] a.mapper.wf_out(v) <==> b.mapper.wf_out(v),
1846    ensures
1847        #[trigger] serializer_congruent(a, b),
1848{
1849    reveal(serializer_congruent);
1850    lemma_mapped_prepare_congruence(a, b);
1851}
1852
1853// ====================================================
1854// Dependent and sum formats
1855// ====================================================
1856pub broadcast proof fn lemma_bind_prepare_congruence<A1, A2, B1, B2>(
1857    a: Bind<A1, B1>,
1858    b: Bind<A2, B2>,
1859) where
1860    A1: Consistency + SpecByteLen<T = A1::Val>,
1861    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1862    B1: SpecMap<Input = A1::Val>,
1863    B2: SpecMap<Input = A1::Val>,
1864    B1::Output: Consistency + SpecByteLen<T = <B1::Output as Consistency>::Val>,
1865    B2::Output: Consistency<Val = <B1::Output as Consistency>::Val> + SpecByteLen<
1866        T = <B1::Output as Consistency>::Val,
1867    >,
1868
1869    requires
1870        prepare_congruent(a.0, b.0),
1871        forall|key: A1::Val| #[trigger] prepare_congruent(a.1.spec_map(key), b.1.spec_map(key)),
1872    ensures
1873        #[trigger] prepare_congruent(a, b),
1874{
1875    reveal(prepare_congruent);
1876    broadcast use lemma_prepare_congruent_consistent;
1877    broadcast use lemma_prepare_congruent_byte_len;
1878
1879}
1880
1881pub broadcast proof fn lemma_bind_serializer_congruence<A1, A2, B1, B2>(
1882    a: Bind<A1, B1>,
1883    b: Bind<A2, B2>,
1884) where
1885    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1886    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1887    B1: SpecMap<Input = A1::Val>,
1888    B2: SpecMap<Input = A1::Val>,
1889    B1::Output: Consistency + SpecByteLen<T = <B1::Output as Consistency>::Val> + SpecSerializer<
1890        SVal = <B1::Output as Consistency>::Val,
1891    >,
1892    B2::Output: Consistency<Val = <B1::Output as Consistency>::Val> + SpecByteLen<
1893        T = <B1::Output as Consistency>::Val,
1894    > + SpecSerializer<SVal = <B1::Output as Consistency>::Val>,
1895
1896    requires
1897        serializer_congruent(a.0, b.0),
1898        forall|key: A1::Val| #[trigger] serializer_congruent(a.1.spec_map(key), b.1.spec_map(key)),
1899    ensures
1900        #[trigger] serializer_congruent(a, b),
1901{
1902    reveal(serializer_congruent);
1903    broadcast use lemma_serializer_congruent_prepare;
1904    broadcast use lemma_serializer_congruent_serialize;
1905
1906    lemma_bind_prepare_congruence(a, b);
1907}
1908
1909pub broadcast proof fn lemma_sum_prepare_congruence<A1, A2, B1, B2>(
1910    a: Sum<A1, B1>,
1911    b: Sum<A2, B2>,
1912) where
1913    A1: Consistency + SpecByteLen<T = A1::Val>,
1914    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val>,
1915    B1: Consistency + SpecByteLen<T = B1::Val>,
1916    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val>,
1917
1918    requires
1919        match (a, b) {
1920            (Sum::Inl(a), Sum::Inl(b)) => prepare_congruent(a, b),
1921            (Sum::Inr(a), Sum::Inr(b)) => prepare_congruent(a, b),
1922            _ => false,
1923        },
1924    ensures
1925        #[trigger] prepare_congruent(a, b),
1926{
1927    reveal(prepare_congruent);
1928    broadcast use lemma_prepare_congruent_consistent;
1929    broadcast use lemma_prepare_congruent_byte_len;
1930
1931}
1932
1933pub broadcast proof fn lemma_sum_serializer_congruence<A1, A2, B1, B2>(
1934    a: Sum<A1, B1>,
1935    b: Sum<A2, B2>,
1936) where
1937    A1: Consistency + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1938    A2: Consistency<Val = A1::Val> + SpecByteLen<T = A1::Val> + SpecSerializer<SVal = A1::Val>,
1939    B1: Consistency + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1940    B2: Consistency<Val = B1::Val> + SpecByteLen<T = B1::Val> + SpecSerializer<SVal = B1::Val>,
1941
1942    requires
1943        match (a, b) {
1944            (Sum::Inl(a), Sum::Inl(b)) => serializer_congruent(a, b),
1945            (Sum::Inr(a), Sum::Inr(b)) => serializer_congruent(a, b),
1946            _ => false,
1947        },
1948    ensures
1949        #[trigger] serializer_congruent(a, b),
1950{
1951    reveal(serializer_congruent);
1952    broadcast use lemma_serializer_congruent_prepare;
1953    broadcast use lemma_serializer_congruent_serialize;
1954
1955    lemma_sum_prepare_congruence(a, b);
1956}
1957
1958// ====================================================
1959// Prefix/suffix tagging (derived through Const + Preceded/Terminated)
1960// ====================================================
1961pub broadcast proof fn lemma_prefix_tagged_parser_congruence<Tg1, Tg2, Of1, Of2>(
1962    a: PrefixTagged<Tg1, Tg1::T, Of1>,
1963    b: PrefixTagged<Tg2, Tg1::T, Of2>,
1964) where
1965    Tg1: SpecByteLen + SpecParser<PVal = Tg1::T>,
1966    Tg2: SpecByteLen<T = Tg1::T> + SpecParser<PVal = Tg1::T>,
1967    Of1: SpecParser,
1968    Of2: SpecParser<PVal = Of1::PVal>,
1969
1970    requires
1971        parser_congruent(a.0, b.0),
1972        parser_congruent(a.2, b.2),
1973        a.1 == b.1,
1974    ensures
1975        #[trigger] parser_congruent(a, b),
1976{
1977    reveal(parser_congruent);
1978    lemma_const_parser_congruence(Const(a.0, a.1), Const(b.0, b.1));
1979    lemma_preceded_parser_congruence(
1980        Preceded::<_, _, _, false> { a: Const(a.0, a.1), b: a.2, a_val: a.1 },
1981        Preceded::<_, _, _, false> { a: Const(b.0, b.1), b: b.2, a_val: b.1 },
1982    );
1983}
1984
1985pub broadcast proof fn lemma_suffix_tagged_parser_congruence<Tg1, Tg2, Of1, Of2>(
1986    a: SuffixTagged<Of1, Tg1, Tg1::T>,
1987    b: SuffixTagged<Of2, Tg2, Tg1::T>,
1988) where
1989    Tg1: SpecByteLen + SpecParser<PVal = Tg1::T>,
1990    Tg2: SpecByteLen<T = Tg1::T> + SpecParser<PVal = Tg1::T>,
1991    Of1: SpecParser,
1992    Of2: SpecParser<PVal = Of1::PVal>,
1993
1994    requires
1995        parser_congruent(a.0, b.0),
1996        parser_congruent(a.1, b.1),
1997        a.2 == b.2,
1998    ensures
1999        #[trigger] parser_congruent(a, b),
2000{
2001    reveal(parser_congruent);
2002    lemma_const_parser_congruence(Const(a.1, a.2), Const(b.1, b.2));
2003    lemma_terminated_parser_congruence(
2004        Terminated::<_, _, _, false> { a: a.0, b: Const(a.1, a.2), b_val: a.2 },
2005        Terminated::<_, _, _, false> { a: b.0, b: Const(b.1, b.2), b_val: b.2 },
2006    );
2007}
2008
2009pub broadcast proof fn lemma_prefix_tagged_prepare_congruence<Tg1, Tg2, Of1, Of2>(
2010    a: PrefixTagged<Tg1, Tg1::Val, Of1>,
2011    b: PrefixTagged<Tg2, Tg1::Val, Of2>,
2012) where
2013    Tg1: Consistency + SpecByteLen<T = Tg1::Val>,
2014    Tg2: Consistency<Val = Tg1::Val> + SpecByteLen<T = Tg1::Val>,
2015    Of1: Consistency + SpecByteLen<T = Of1::Val>,
2016    Of2: Consistency<Val = Of1::Val> + SpecByteLen<T = Of1::Val>,
2017
2018    requires
2019        prepare_congruent(a.0, b.0),
2020        prepare_congruent(a.2, b.2),
2021        a.1 == b.1,
2022    ensures
2023        #[trigger] prepare_congruent(a, b),
2024{
2025    reveal(prepare_congruent);
2026    lemma_const_prepare_congruence(Const(a.0, a.1), Const(b.0, b.1));
2027    lemma_preceded_prepare_congruence(
2028        Preceded::<_, _, _, false> { a: Const(a.0, a.1), b: a.2, a_val: a.1 },
2029        Preceded::<_, _, _, false> { a: Const(b.0, b.1), b: b.2, a_val: b.1 },
2030    );
2031}
2032
2033pub broadcast proof fn lemma_prefix_tagged_serializer_congruence<Tg1, Tg2, Of1, Of2>(
2034    a: PrefixTagged<Tg1, Tg1::Val, Of1>,
2035    b: PrefixTagged<Tg2, Tg1::Val, Of2>,
2036) where
2037    Tg1: Consistency + SpecByteLen<T = Tg1::Val> + SpecSerializer<SVal = Tg1::Val>,
2038    Tg2: Consistency<Val = Tg1::Val> + SpecByteLen<T = Tg1::Val> + SpecSerializer<SVal = Tg1::Val>,
2039    Of1: Consistency + SpecByteLen<T = Of1::Val> + SpecSerializer<SVal = Of1::Val>,
2040    Of2: Consistency<Val = Of1::Val> + SpecByteLen<T = Of1::Val> + SpecSerializer<SVal = Of1::Val>,
2041
2042    requires
2043        serializer_congruent(a.0, b.0),
2044        serializer_congruent(a.2, b.2),
2045        a.1 == b.1,
2046    ensures
2047        #[trigger] serializer_congruent(a, b),
2048{
2049    reveal(serializer_congruent);
2050    lemma_const_serializer_congruence(Const(a.0, a.1), Const(b.0, b.1));
2051    lemma_preceded_serializer_congruence(
2052        Preceded::<_, _, _, false> { a: Const(a.0, a.1), b: a.2, a_val: a.1 },
2053        Preceded::<_, _, _, false> { a: Const(b.0, b.1), b: b.2, a_val: b.1 },
2054    );
2055    lemma_prefix_tagged_prepare_congruence(a, b);
2056}
2057
2058pub broadcast proof fn lemma_suffix_tagged_prepare_congruence<Tg1, Tg2, Of1, Of2>(
2059    a: SuffixTagged<Of1, Tg1, Tg1::Val>,
2060    b: SuffixTagged<Of2, Tg2, Tg1::Val>,
2061) where
2062    Tg1: Consistency + SpecByteLen<T = Tg1::Val>,
2063    Tg2: Consistency<Val = Tg1::Val> + SpecByteLen<T = Tg1::Val>,
2064    Of1: Consistency + SpecByteLen<T = Of1::Val>,
2065    Of2: Consistency<Val = Of1::Val> + SpecByteLen<T = Of1::Val>,
2066
2067    requires
2068        prepare_congruent(a.0, b.0),
2069        prepare_congruent(a.1, b.1),
2070        a.2 == b.2,
2071    ensures
2072        #[trigger] prepare_congruent(a, b),
2073{
2074    reveal(prepare_congruent);
2075    lemma_const_prepare_congruence(Const(a.1, a.2), Const(b.1, b.2));
2076    lemma_terminated_prepare_congruence(
2077        Terminated::<_, _, _, false> { a: a.0, b: Const(a.1, a.2), b_val: a.2 },
2078        Terminated::<_, _, _, false> { a: b.0, b: Const(b.1, b.2), b_val: b.2 },
2079    );
2080}
2081
2082pub broadcast proof fn lemma_suffix_tagged_serializer_congruence<Tg1, Tg2, Of1, Of2>(
2083    a: SuffixTagged<Of1, Tg1, Tg1::Val>,
2084    b: SuffixTagged<Of2, Tg2, Tg1::Val>,
2085) where
2086    Tg1: Consistency + SpecByteLen<T = Tg1::Val> + SpecSerializer<SVal = Tg1::Val>,
2087    Tg2: Consistency<Val = Tg1::Val> + SpecByteLen<T = Tg1::Val> + SpecSerializer<SVal = Tg1::Val>,
2088    Of1: Consistency + SpecByteLen<T = Of1::Val> + SpecSerializer<SVal = Of1::Val>,
2089    Of2: Consistency<Val = Of1::Val> + SpecByteLen<T = Of1::Val> + SpecSerializer<SVal = Of1::Val>,
2090
2091    requires
2092        serializer_congruent(a.0, b.0),
2093        serializer_congruent(a.1, b.1),
2094        a.2 == b.2,
2095    ensures
2096        #[trigger] serializer_congruent(a, b),
2097{
2098    reveal(serializer_congruent);
2099    lemma_const_serializer_congruence(Const(a.1, a.2), Const(b.1, b.2));
2100    lemma_terminated_serializer_congruence(
2101        Terminated::<_, _, _, false> { a: a.0, b: Const(a.1, a.2), b_val: a.2 },
2102        Terminated::<_, _, _, false> { a: b.0, b: Const(b.1, b.2), b_val: b.2 },
2103    );
2104    lemma_suffix_tagged_prepare_congruence(a, b);
2105}
2106
2107// ====================================================
2108// Bit-field mapping
2109// ====================================================
2110pub broadcast proof fn lemma_bits_parser_congruence<R1, R2, Tuple, Nominal>(
2111    a: Bits<R1, Tuple, Nominal>,
2112    b: Bits<R2, Tuple, Nominal>,
2113) where
2114    R1: SpecByteLen + SpecParser<PVal = R1::T>,
2115    R2: SpecByteLen<T = R1::T> + SpecParser<PVal = R1::T>,
2116
2117    requires
2118        parser_congruent(a.repr, b.repr),
2119        a.unpack == b.unpack,
2120        a.pack == b.pack,
2121        a.refinement == b.refinement,
2122        a.ctor == b.ctor,
2123        a.dtor == b.dtor,
2124        a.consistent == b.consistent,
2125    ensures
2126        #[trigger] parser_congruent(a, b),
2127{
2128    reveal(parser_congruent);
2129    broadcast use lemma_parser_congruent_apply;
2130
2131}
2132
2133pub broadcast proof fn lemma_bits_prepare_congruence<R1, R2, Tuple, Nominal>(
2134    a: Bits<R1, Tuple, Nominal>,
2135    b: Bits<R2, Tuple, Nominal>,
2136) where
2137    R1: SpecByteLen + Consistency<Val = R1::T>,
2138    R2: SpecByteLen<T = R1::T> + Consistency<Val = R1::T>,
2139
2140    requires
2141        prepare_congruent(a.repr, b.repr),
2142        a.unpack == b.unpack,
2143        a.pack == b.pack,
2144        a.refinement == b.refinement,
2145        a.ctor == b.ctor,
2146        a.dtor == b.dtor,
2147        a.consistent == b.consistent,
2148    ensures
2149        #[trigger] prepare_congruent(a, b),
2150{
2151    reveal(prepare_congruent);
2152    broadcast use lemma_prepare_congruent_consistent;
2153    broadcast use lemma_prepare_congruent_byte_len;
2154
2155}
2156
2157pub broadcast proof fn lemma_bits_serializer_congruence<R1, R2, Tuple, Nominal>(
2158    a: Bits<R1, Tuple, Nominal>,
2159    b: Bits<R2, Tuple, Nominal>,
2160) where
2161    R1: SpecByteLen + Consistency<Val = R1::T> + SpecSerializer<SVal = R1::T>,
2162    R2: SpecByteLen<T = R1::T> + Consistency<Val = R1::T> + SpecSerializer<SVal = R1::T>,
2163
2164    requires
2165        serializer_congruent(a.repr, b.repr),
2166        a.unpack == b.unpack,
2167        a.pack == b.pack,
2168        a.refinement == b.refinement,
2169        a.ctor == b.ctor,
2170        a.dtor == b.dtor,
2171        a.consistent == b.consistent,
2172    ensures
2173        #[trigger] serializer_congruent(a, b),
2174{
2175    reveal(serializer_congruent);
2176    broadcast use lemma_serializer_congruent_prepare;
2177    broadcast use lemma_serializer_congruent_serialize;
2178
2179    lemma_bits_prepare_congruence(a, b);
2180}
2181
2182// ====================================================
2183// Opt-in broadcast groups
2184// ====================================================
2185pub broadcast group parser_congruence_lemmas {
2186    lemma_parser_congruent_intro,
2187    lemma_ref_fn_parser_congruence,
2188    lemma_parser_congruent_reflexive,
2189    lemma_parser_congruent_apply,
2190    lemma_exact_len_parser_congruence,
2191    lemma_pair_parser_congruence,
2192    lemma_ref_parser_congruence,
2193    lemma_named_parser_congruence,
2194    lemma_star_parser_congruence,
2195    lemma_repeat_parser_congruence,
2196    lemma_repeat_till_end_parser_congruence,
2197    lemma_repeat_n_parser_congruence,
2198    lemma_array_parser_congruence,
2199    lemma_and_then_parser_congruence,
2200    lemma_mapped_parser_congruence,
2201    lemma_refined_parser_congruence,
2202    lemma_const_parser_congruence,
2203    lemma_cond_parser_congruence,
2204    lemma_choice_parser_congruence,
2205    lemma_alt_parser_congruence,
2206    lemma_sum_parser_congruence,
2207    lemma_opt_parser_congruence,
2208    lemma_optional_parser_congruence,
2209    lemma_optional_end_parser_congruence,
2210    lemma_preceded_parser_congruence,
2211    lemma_terminated_parser_congruence,
2212    lemma_bind_parser_congruence,
2213    lemma_prefix_tagged_parser_congruence,
2214    lemma_suffix_tagged_parser_congruence,
2215    lemma_bits_parser_congruence,
2216}
2217
2218pub broadcast group prepare_congruence_lemmas {
2219    lemma_prepare_congruent_intro,
2220    lemma_prepare_congruent_reflexive,
2221    lemma_prepare_congruent_consistent,
2222    lemma_prepare_congruent_byte_len,
2223    lemma_exact_len_prepare_congruence,
2224    lemma_refined_prepare_congruence,
2225    lemma_cond_prepare_congruence,
2226    lemma_const_prepare_congruence,
2227    lemma_opt_prepare_congruence,
2228    lemma_ref_prepare_congruence,
2229    lemma_named_prepare_congruence,
2230    lemma_star_prepare_congruence,
2231    lemma_pair_prepare_congruence,
2232    lemma_choice_prepare_congruence,
2233    lemma_optional_prepare_congruence,
2234    lemma_repeat_prepare_congruence,
2235    lemma_repeat_n_prepare_congruence,
2236    lemma_array_prepare_congruence,
2237    lemma_optional_end_prepare_congruence,
2238    lemma_repeat_till_end_prepare_congruence,
2239    lemma_preceded_prepare_congruence,
2240    lemma_terminated_prepare_congruence,
2241    lemma_and_then_prepare_congruence,
2242    lemma_alt_prepare_congruence,
2243    lemma_mapped_prepare_congruence,
2244    lemma_bind_prepare_congruence,
2245    lemma_sum_prepare_congruence,
2246    lemma_prefix_tagged_prepare_congruence,
2247    lemma_suffix_tagged_prepare_congruence,
2248    lemma_bits_prepare_congruence,
2249}
2250
2251pub broadcast group serializer_congruence_lemmas {
2252    lemma_serializer_congruent_intro,
2253    lemma_serializer_congruent_reflexive,
2254    lemma_serializer_congruent_prepare,
2255    lemma_serializer_congruent_serialize,
2256    lemma_exact_len_serializer_congruence,
2257    lemma_refined_serializer_congruence,
2258    lemma_cond_serializer_congruence,
2259    lemma_const_serializer_congruence,
2260    lemma_opt_serializer_congruence,
2261    lemma_ref_serializer_congruence,
2262    lemma_named_serializer_congruence,
2263    lemma_star_serializer_congruence,
2264    lemma_pair_serializer_congruence,
2265    lemma_choice_serializer_congruence,
2266    lemma_optional_serializer_congruence,
2267    lemma_repeat_serializer_congruence,
2268    lemma_repeat_n_serializer_congruence,
2269    lemma_array_serializer_congruence,
2270    lemma_optional_end_serializer_congruence,
2271    lemma_repeat_till_end_serializer_congruence,
2272    lemma_preceded_serializer_congruence,
2273    lemma_terminated_serializer_congruence,
2274    lemma_and_then_serializer_congruence,
2275    lemma_alt_serializer_congruence,
2276    lemma_mapped_serializer_congruence,
2277    lemma_bind_serializer_congruence,
2278    lemma_sum_serializer_congruence,
2279    lemma_prefix_tagged_serializer_congruence,
2280    lemma_suffix_tagged_serializer_congruence,
2281    lemma_bits_serializer_congruence,
2282}
2283
2284} // verus!