Skip to main content

vest_lib/asn1/
length.rs

1//! ASN.1 definite and BER indefinite length octets.
2use crate::combinators::{Bind, Empty, Sum, Void};
3use crate::core::exec::input::*;
4use crate::core::exec::output::*;
5use crate::core::exec::{parser::*, serializer::*, ParseError, ParseErrorKind};
6use crate::primitives::base256::*;
7use crate::Never;
8use crate::{
9    combinators::{
10        implicit::*,
11        length::AsLen,
12        mapped::spec::{FnSpecMapper, LosslessMapper, LossyMapper, SpecMapper},
13        Alt, Choice, Const, Implicit, Mapped, Refined, TryMap, Varied, U8,
14    },
15    core::{proof::*, spec::*},
16};
17use vstd::arithmetic::power::*;
18use vstd::prelude::*;
19use OutputBuf;
20use Sum::Inl as L;
21use Sum::Inr as R;
22
23verus! {
24
25pub const SHORT_FORM_MAX: u8 = 0x7F;
26
27pub const LONG_FORM_MIN_COUNT: u8 = 1;
28
29pub const LONG_FORM_MAX_COUNT: u8 = 126;
30
31type LengthWireFmt<const DER: bool, const BOUNDED: bool = false> = Bind<
32    U8,
33    spec_fn(u8) -> Sum<Empty, Sum<Refined<Varied<u8>, PredFnSpec<Seq<u8>>>, Void>>,
34>;
35
36type NatLengthFmt<const DER: bool> = Mapped<
37    LengthWireFmt<DER>,
38    FnSpecMapper<(u8, Sum<(), Sum<Seq<u8>, Never>>), nat>,
39>;
40
41type LengthFmt<const DER: bool> = Mapped<
42    LengthWireFmt<DER, true>,
43    FnSpecMapper<(u8, Sum<(), Sum<Seq<u8>, Never>>), usize>,
44>;
45
46type BerLengthFmt__ = Mapped<
47    Choice<Const<U8, u8>, super::LengthFmt<false>>,
48    FnSpecMapper<Sum<u8, usize>, super::BerLength>,
49>;
50
51pub open spec fn ber_length_fmt() -> BerLengthFmt__ {
52    Mapped {
53        inner: Choice(Const(U8, 0x80u8), super::LengthFmt::<false>),
54        mapper: (
55            |v: Sum<u8, usize>|
56                match v {
57                    L(_) => super::BerLength::Indefinite,
58                    R(n) => super::BerLength::Definite(n),
59                },
60            |v: super::BerLength|
61                match v {
62                    super::BerLength::Indefinite => L(0x80u8),
63                    super::BerLength::Definite(n) => R(n),
64                },
65        ),
66    }
67}
68
69/// 8.1.3.5 In the long form, the length octets shall consist of an initial octet and **one or more** subsequent octets. The initial
70/// octet shall be encoded as follows:
71///
72/// a) bit 8 shall be one;
73/// b) bits 7 to 1 shall encode the number of subsequent octets in the length octets, as an unsigned binary integer with
74/// bit 7 as the most significant bit;
75/// c) the value 11111111 shall not be used.
76#[verusfmt::skip]
77pub(super) open(super) spec fn length_wire<const DER: bool, const BOUNDED: bool>() -> LengthWireFmt<DER, BOUNDED > {
78    Bind(U8, |b1: u8| {
79        match b1 {
80            b if b <= SHORT_FORM_MAX => L(Empty),
81            b if 0b1000_0000 < b < 0b1111_1111 => R(L(
82                Refined(Varied(b & 0b0111_1111),  // clear the high bit to get the count
83                    |bytes: Seq<u8>| {
84                        &&& DER ==> der_long_len_bytes_minimal(bytes)
85                        &&& BOUNDED ==> bytes.len() <= size_of_usize()
86                    }),
87                ),
88            ),
89            _ => R(R(Void("Invalid first byte for ASN1 length"))),
90        }
91    })
92}
93
94pub(super) open(super) spec fn nat_length_fmt<const DER: bool>() -> NatLengthFmt<DER> {
95    Mapped {
96        inner: length_wire::<DER, false>(),
97        mapper: (
98            |r: (u8, Sum<(), Sum<Seq<u8>, Never>>)|
99                {
100                    let (b1, rest) = r;
101                    match rest {
102                        L(()) => b1 as nat,
103                        R(L(bytes)) => nat_from_be_bytes(bytes),
104                        _ => arbitrary(),  // unreachable
105                    }
106                },
107            |n: nat|
108                if n <= SHORT_FORM_MAX as nat {
109                    (n as u8, L(()))
110                } else {
111                    let bytes = nat_to_be_bytes(n);
112                    // set the high bit to indicate long form
113                    (0b1000_0000 | (bytes.len() as u8), R(L(bytes)))
114                },
115        ),
116    }
117}
118
119pub(super) open(super) spec fn length_fmt<const DER: bool>() -> LengthFmt<DER> {
120    Mapped {
121        inner: length_wire::<DER, true>(),
122        mapper: (
123            |r: (u8, Sum<(), Sum<Seq<u8>, Never>>)|
124                {
125                    let (b1, rest) = r;
126                    match rest {
127                        L(()) => b1 as usize,
128                        R(L(bytes)) => nat_from_be_bytes(bytes) as usize,
129                        _ => arbitrary(),  // unreachable
130                    }
131                },
132            |n: usize|
133                if n <= SHORT_FORM_MAX as usize {
134                    (n as u8, L(()))
135                } else {
136                    let bytes = nat_to_be_bytes(n as nat);
137                    (0b1000_0000 | (bytes.len() as u8), R(L(bytes)))
138                },
139        ),
140    }
141}
142
143/// DER requires minimality, so
144/// 1. for single-byte length in the long form, the value must be > 127 (i.e. not encodable in short form)
145/// 2. for multi-byte length in the long form, the first byte must be non-zero (i.e. no leading zeros)
146pub open spec fn der_long_len_bytes_minimal(bytes: Seq<u8>) -> bool {
147    &&& bytes.len() == 1 ==> bytes[0] > SHORT_FORM_MAX
148    &&& bytes.len() > 1 ==> bytes[0] != 0x00u8
149}
150
151proof fn lemma_length_wire_long_form_roundtrip(b1: u8, bytes: Seq<u8>)
152    requires
153        0b1000_0000u8 < b1 < 0b1111_1111u8,
154        der_long_len_bytes_minimal(bytes),
155        bytes.len() == (b1 & 0b0111_1111) as nat,
156    ensures
157        nat_to_be_bytes(nat_from_be_bytes(bytes)) == bytes,
158        (0b1000_0000u8 | (bytes.len() as u8)) == b1,
159{
160    assert(bytes.len() > 0) by {
161        assert((b1 & 0b0111_1111u8) >= 1u8) by (bit_vector)
162            requires
163                0b1000_0000u8 < b1 < 0b1111_1111u8,
164        ;
165    }
166    lemma_from_to_be_bytes_roundtrip(bytes);
167    assert((0b1000_0000u8 | (b1 & 0b0111_1111u8)) == b1) by (bit_vector)
168        requires
169            0b1000_0000u8 < b1 < 0b1111_1111u8,
170    ;
171}
172
173proof fn lemma_length_fmt_sound_nonmal_inv()
174    ensures
175        nat_length_fmt::<true>().sound_inv(),
176        nat_length_fmt::<true>().nonmal_inv(),
177{
178    assert forall|v| nat_length_fmt::<true>().inner.consistent(v) implies (nat_length_fmt::<
179        true,
180    >().mapper.1)((nat_length_fmt::<true>().mapper.0)(v)) == v by {
181        let (b1, rest) = v;
182        if b1 <= SHORT_FORM_MAX {
183        } else if 0b1000_0000 < b1 < 0b1111_1111 {
184            match rest {
185                R(L(bytes)) => {
186                    lemma_length_wire_long_form_roundtrip(b1, bytes);
187                },
188                _ => {},
189            }
190        }
191    }
192}
193
194proof fn lemma_length_fmt_unambiguous<const DER: bool>()
195    ensures
196        nat_length_fmt::<DER>().unambiguous(),
197{
198    assert forall|o: nat| nat_length_fmt::<DER>().consistent(o) implies (nat_length_fmt::<
199        DER,
200    >().mapper.0)((nat_length_fmt::<DER>().mapper.1)(o)) == o by {
201        if nat_length_fmt::<DER>().consistent(o) {
202            if o <= SHORT_FORM_MAX as nat {
203            } else {
204                lemma_to_from_be_bytes_roundtrip(o);
205            }
206        }
207    }
208}
209
210proof fn lemma_length_fmt_usize_sound_nonmal_inv()
211    ensures
212        length_fmt::<true>().sound_inv(),
213        length_fmt::<true>().nonmal_inv(),
214{
215    assert forall|v| length_fmt::<true>().inner.consistent(v) implies (length_fmt::<
216        true,
217    >().mapper.1)((length_fmt::<true>().mapper.0)(v)) == v by {
218        let (b1, rest) = v;
219        if b1 <= SHORT_FORM_MAX {
220        } else if 0b1000_0000 < b1 < 0b1111_1111 {
221            match rest {
222                R(L(bytes)) => {
223                    assert(bytes.len() <= size_of_usize());
224                    lemma_nat_from_be_bytes_fits_usize(bytes);
225                    lemma_length_wire_long_form_roundtrip(b1, bytes);
226                },
227                _ => {},
228            }
229        }
230    }
231}
232
233/// The usize unambiguous invariant reduces to the nat one via the cast identity.
234proof fn lemma_length_fmt_usize_unambiguous<const DER: bool>()
235    ensures
236        length_fmt::<DER>().unambiguous(),
237{
238    assert forall|o: usize| length_fmt::<DER>().consistent(o) implies (length_fmt::<
239        DER,
240    >().mapper.0)((length_fmt::<DER>().mapper.1)(o)) == o by {
241        if length_fmt::<DER>().consistent(o) {
242            if o <= SHORT_FORM_MAX as usize {
243            } else {
244                lemma_to_from_be_bytes_roundtrip(o as nat);
245            }
246        }
247    }
248}
249
250proof fn lemma_length_fmt_usize_props<const DER: bool>(o: usize)
251    ensures
252        length_fmt::<DER>().consistent(o),
253        length_fmt::<DER>().byte_len(o) == if o <= SHORT_FORM_MAX as usize {
254            1
255        } else {
256            1 + nat_to_be_bytes(o as nat).len()
257        },
258{
259    lemma_to_be_bytes_props(o as nat);
260    lemma_usize_to_be_bytes_len_bound(o);
261    if o <= SHORT_FORM_MAX as usize {
262    } else {
263        let bytes = nat_to_be_bytes(o as nat);
264        let count = bytes.len() as u8;
265        let b1 = 0b1000_0000u8 | count;
266        if DER {
267            assert(der_long_len_bytes_minimal(bytes)) by {
268                reveal_with_fuel(nat_to_be_bytes, 2);
269            }
270        }
271        assert(0b1000_0000u8 < b1 < 0b1111_1111u8 && (b1 & 0b0111_1111u8) == count) by (bit_vector)
272            requires
273                0u8 < count <= 8u8,
274                b1 == (0b1000_0000u8 | count),
275        ;
276    }
277}
278
279pub(crate) proof fn lemma_length_fmt_byte_len_bound<const DER: bool>(value: usize)
280    ensures
281        super::LengthFmt::<DER>.byte_len(value) <= 1 + size_of::<usize>(),
282{
283    lemma_length_fmt_usize_props::<DER>(value);
284    lemma_usize_to_be_bytes_len_bound(value);
285}
286
287pub(crate) broadcast proof fn lemma_length_fmt_short_byte_len<const DER: bool>(o: usize)
288    requires
289        o <= SHORT_FORM_MAX as usize,
290    ensures
291        #[trigger] super::LengthFmt::<DER>.byte_len(o) == 1,
292{
293    lemma_length_fmt_usize_props::<DER>(o);
294}
295
296mod derived_specs {
297    use super::*;
298    use super::super::{NatLengthFmt, LengthFmt};
299
300    impl<const DER: bool> SpecParser for NatLengthFmt<DER> {
301        type PVal = nat;
302
303        open(super) spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
304            nat_length_fmt::<DER>().spec_parse(ibuf)
305        }
306    }
307
308    impl<const DER: bool> Consistency for NatLengthFmt<DER> {
309        type Val = nat;
310
311        open(super) spec fn consistent(&self, v: Self::Val) -> bool {
312            nat_length_fmt::<DER>().consistent(v)
313        }
314    }
315
316    impl<const DER: bool> SpecSerializerDps for NatLengthFmt<DER> {
317        type SValue = nat;
318
319        open(super) spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
320            nat_length_fmt::<DER>().spec_serialize_dps(v, obuf)
321        }
322    }
323
324    impl<const DER: bool> SpecSerializer for NatLengthFmt<DER> {
325        type SVal = nat;
326
327        open(super) spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
328            nat_length_fmt::<DER>().spec_serialize(v)
329        }
330    }
331
332    impl<const DER: bool> SpecByteLen for NatLengthFmt<DER> {
333        type T = nat;
334
335        open(super) spec fn byte_len(&self, v: Self::T) -> nat {
336            nat_length_fmt::<DER>().byte_len(v)
337        }
338    }
339
340    impl<const DER: bool> SpecParser for LengthFmt<DER> {
341        type PVal = usize;
342
343        open(super) spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
344            length_fmt::<DER>().spec_parse(ibuf)
345        }
346    }
347
348    impl<const DER: bool> Consistency for LengthFmt<DER> {
349        type Val = usize;
350
351        open(super) spec fn consistent(&self, v: Self::Val) -> bool {
352            length_fmt::<DER>().consistent(v)
353        }
354    }
355
356    impl<const DER: bool> SpecSerializerDps for LengthFmt<DER> {
357        type SValue = usize;
358
359        open(super) spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
360            length_fmt::<DER>().spec_serialize_dps(v, obuf)
361        }
362    }
363
364    impl<const DER: bool> SpecSerializer for LengthFmt<DER> {
365        type SVal = usize;
366
367        open(super) spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
368            length_fmt::<DER>().spec_serialize(v)
369        }
370    }
371
372    impl<const DER: bool> SpecByteLen for LengthFmt<DER> {
373        type T = usize;
374
375        open(super) spec fn byte_len(&self, v: Self::T) -> nat {
376            length_fmt::<DER>().byte_len(v)
377        }
378    }
379
380}
381
382mod derived_proofs {
383    use super::*;
384    use super::super::{NatLengthFmt, LengthFmt};
385
386    impl<const DER: bool> SafeParser for NatLengthFmt<DER> {
387        proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
388            nat_length_fmt::<DER>().lemma_parse_safe(ibuf);
389        }
390    }
391
392    impl<const DER: bool> Productive for NatLengthFmt<DER> {
393        proof fn lemma_productive(&self, s: Seq<u8>) {
394            nat_length_fmt::<DER>().lemma_productive(s);
395        }
396    }
397
398    impl SoundParser for NatLengthFmt<true> {
399        proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
400            lemma_length_fmt_sound_nonmal_inv();
401            nat_length_fmt::<true>().lemma_parse_sound_consumption(ibuf);
402        }
403
404        proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
405            lemma_length_fmt_sound_nonmal_inv();
406            nat_length_fmt::<true>().lemma_parse_sound_value(ibuf);
407        }
408    }
409
410    impl<const DER: bool> NonTailFmt for NatLengthFmt<DER> {
411        proof fn lemma_serialize_dps_prepend(&self, v: Self::SValue, obuf: Seq<u8>) {
412            nat_length_fmt::<DER>().lemma_serialize_dps_prepend(v, obuf);
413        }
414
415        proof fn lemma_serialize_dps_len(&self, v: Self::SValue, obuf: Seq<u8>) {
416            nat_length_fmt::<DER>().lemma_serialize_dps_len(v, obuf);
417        }
418    }
419
420    impl<const DER: bool> GoodSerializer for NatLengthFmt<DER> {
421        proof fn lemma_serialize_len(&self, v: Self::SVal) {
422            nat_length_fmt::<DER>().lemma_serialize_len(v);
423        }
424    }
425
426    impl<const DER: bool> SPRoundTripDps for NatLengthFmt<DER> {
427        proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
428            lemma_length_fmt_unambiguous::<DER>();
429            nat_length_fmt::<DER>().theorem_serialize_dps_parse_roundtrip(v, obuf);
430        }
431    }
432
433    impl<const DER: bool> NoLookAhead for NatLengthFmt<DER> {
434        proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
435            nat_length_fmt::<DER>().lemma_no_lookahead(i1, i2);
436        }
437    }
438
439    impl NonMalleable for NatLengthFmt<true> {
440        proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
441            lemma_length_fmt_sound_nonmal_inv();
442            nat_length_fmt::<true>().lemma_parse_non_malleable(buf1, buf2);
443        }
444    }
445
446    impl<const DER: bool> EquivSerializersGeneral for NatLengthFmt<DER> {
447        proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
448            nat_length_fmt::<DER>().lemma_serialize_equiv(v, obuf);
449        }
450    }
451
452    impl<const DER: bool> EquivSerializers for NatLengthFmt<DER> {
453        proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
454            nat_length_fmt::<DER>().lemma_serialize_equiv_on_empty(v);
455        }
456    }
457
458    impl<const DER: bool> SafeParser for LengthFmt<DER> {
459        proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
460            length_fmt::<DER>().lemma_parse_safe(ibuf);
461        }
462    }
463
464    impl<const DER: bool> Productive for LengthFmt<DER> {
465        proof fn lemma_productive(&self, s: Seq<u8>) {
466            length_fmt::<DER>().lemma_productive(s);
467        }
468    }
469
470    impl SoundParser for LengthFmt<true> {
471        proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
472            lemma_length_fmt_usize_sound_nonmal_inv();
473            length_fmt::<true>().lemma_parse_sound_consumption(ibuf);
474        }
475
476        proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
477            lemma_length_fmt_usize_sound_nonmal_inv();
478            length_fmt::<true>().lemma_parse_sound_value(ibuf);
479        }
480    }
481
482    impl<const DER: bool> NonTailFmt for LengthFmt<DER> {
483        proof fn lemma_serialize_dps_prepend(&self, v: Self::SValue, obuf: Seq<u8>) {
484            length_fmt::<DER>().lemma_serialize_dps_prepend(v, obuf);
485        }
486
487        proof fn lemma_serialize_dps_len(&self, v: Self::SValue, obuf: Seq<u8>) {
488            length_fmt::<DER>().lemma_serialize_dps_len(v, obuf);
489        }
490    }
491
492    impl<const DER: bool> GoodSerializer for LengthFmt<DER> {
493        proof fn lemma_serialize_len(&self, v: Self::SVal) {
494            length_fmt::<DER>().lemma_serialize_len(v);
495        }
496    }
497
498    impl<const DER: bool> SPRoundTripDps for LengthFmt<DER> {
499        proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
500            lemma_length_fmt_usize_unambiguous::<DER>();
501            length_fmt::<DER>().theorem_serialize_dps_parse_roundtrip(v, obuf);
502        }
503    }
504
505    impl<const DER: bool> NoLookAhead for LengthFmt<DER> {
506        proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
507            length_fmt::<DER>().lemma_no_lookahead(i1, i2);
508        }
509    }
510
511    impl NonMalleable for LengthFmt<true> {
512        proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
513            lemma_length_fmt_usize_sound_nonmal_inv();
514            length_fmt::<true>().lemma_parse_non_malleable(buf1, buf2);
515        }
516    }
517
518    impl<const DER: bool> EquivSerializersGeneral for LengthFmt<DER> {
519        proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
520            length_fmt::<DER>().lemma_serialize_equiv(v, obuf);
521        }
522    }
523
524    impl<const DER: bool> EquivSerializers for LengthFmt<DER> {
525        proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
526            length_fmt::<DER>().lemma_serialize_equiv_on_empty(v);
527        }
528    }
529
530}
531
532impl<const DER: bool> Parser<&[u8]> for super::LengthFmt<DER> {
533    type PT = usize;
534
535    fn parse(&self, ibuf: &&[u8]) -> PResult<usize> {
536        broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
537        broadcast use crate::core::spec::SoundParser::lemma_parse_sound_value;
538
539        let (n1, b1): (usize, u8) = U8.parse(ibuf)?;
540        let rest = ibuf.skip(n1);
541
542        if b1 <= SHORT_FORM_MAX {
543            Ok((n1, b1 as usize))
544        } else if 0b1000_0000 < b1 && b1 < 0b1111_1111 {
545            let count = b1 & 0b0111_1111;
546            let (n2, len_bytes) = Varied(count).parse(&rest)?;
547            if DER {
548                if count == 1 && len_bytes[0] <= SHORT_FORM_MAX {
549                    return Err(ParseError::non_canonical());
550                }
551                if count > 1 && len_bytes[0] == 0x00u8 {
552                    return Err(ParseError::non_canonical());
553                }
554            }
555            match usize::BITS {
556                32 if len_bytes.len() > 4 => return Err(ParseError::overflow()),
557                64 if len_bytes.len() > 8 => return Err(ParseError::overflow()),
558                _ => {},
559            }
560            let value = usize_from_be_bytes_exec(len_bytes);
561            Ok((n1 + n2, value))
562        } else {
563            Err(ParseError::invalid_length())
564        }
565    }
566}
567
568impl<Output: OutputBuf, const DER: bool> Serializer<Output, usize> for super::LengthFmt<DER> {
569    fn serialize_into(&self, v: &usize, obuf: &mut Output) {
570        broadcast use crate::core::exec::output::outbuf_lemmas;
571
572        if *v <= SHORT_FORM_MAX as usize {
573            U8.serialize_into(&(*v as u8), obuf);
574        } else {
575            let count = usize_to_be_bytes_len(*v);
576            let mut bytes = [0u8;size_of::<usize>()];
577            let (encoded, _) = bytes.split_at_mut(count);
578            usize_to_be_bytes_in_place(*v, encoded);
579            U8.serialize_into(&(0b1000_0000 | (count as u8)), obuf);
580            Varied(count).serialize_into(&bytes[0..count], obuf);
581        }
582    }
583}
584
585impl<const DER: bool> Prepare<usize> for super::LengthFmt<DER> {
586    fn prepare(&self, v: &usize) -> Result<usize, PreSerializeError> {
587        proof {
588            lemma_length_fmt_usize_props::<DER>(*v);
589        }
590        if *v <= SHORT_FORM_MAX as usize {
591            Ok(1usize)
592        } else {
593            Ok(1 + usize_to_be_bytes_len(*v))
594        }
595    }
596}
597
598impl<const DER: bool> ByteLen<usize> for super::LengthFmt<DER> {
599    fn length(&self, v: &usize) -> usize {
600        proof {
601            lemma_length_fmt_usize_props::<DER>(*v);
602        }
603        if *v <= SHORT_FORM_MAX as usize {
604            1
605        } else {
606            1 + usize_to_be_bytes_len(*v)
607        }
608    }
609}
610
611impl SpecParser for super::BerLengthFmt {
612    type PVal = super::BerLength;
613
614    open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
615        ber_length_fmt().spec_parse(ibuf)
616    }
617}
618
619impl Consistency for super::BerLengthFmt {
620    type Val = super::BerLength;
621
622    open spec fn consistent(&self, v: Self::Val) -> bool {
623        ber_length_fmt().consistent(v)
624    }
625}
626
627impl SpecSerializerDps for super::BerLengthFmt {
628    type SValue = super::BerLength;
629
630    open spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
631        ber_length_fmt().spec_serialize_dps(v, obuf)
632    }
633}
634
635impl SpecSerializer for super::BerLengthFmt {
636    type SVal = super::BerLength;
637
638    open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
639        ber_length_fmt().spec_serialize(v)
640    }
641}
642
643impl SpecByteLen for super::BerLengthFmt {
644    type T = super::BerLength;
645
646    open spec fn byte_len(&self, v: Self::T) -> nat {
647        ber_length_fmt().byte_len(v)
648    }
649}
650
651impl SafeParser for super::BerLengthFmt {
652    proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
653        ber_length_fmt().lemma_parse_safe(ibuf)
654    }
655}
656
657impl Productive for super::BerLengthFmt {
658    proof fn lemma_productive(&self, ibuf: Seq<u8>) {
659        ber_length_fmt().lemma_productive(ibuf)
660    }
661}
662
663impl NonTailFmt for super::BerLengthFmt {
664    proof fn lemma_serialize_dps_prepend(&self, v: Self::SValue, obuf: Seq<u8>) {
665        ber_length_fmt().lemma_serialize_dps_prepend(v, obuf)
666    }
667
668    proof fn lemma_serialize_dps_len(&self, v: Self::SValue, obuf: Seq<u8>) {
669        ber_length_fmt().lemma_serialize_dps_len(v, obuf)
670    }
671}
672
673impl GoodSerializer for super::BerLengthFmt {
674    proof fn lemma_serialize_len(&self, v: Self::SVal) {
675        ber_length_fmt().lemma_serialize_len(v)
676    }
677}
678
679impl SPRoundTripDps for super::BerLengthFmt {
680    proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
681        reveal(disjoint_domains);
682        assert(disjoint_domains(Const(U8, 0x80u8), super::LengthFmt::<false>));
683        ber_length_fmt().theorem_serialize_dps_parse_roundtrip(v, obuf)
684    }
685}
686
687impl NoLookAhead for super::BerLengthFmt {
688    proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
689        reveal(disjoint_domains);
690        assert(disjoint_domains(Const(U8, 0x80u8), super::LengthFmt::<false>));
691        ber_length_fmt().lemma_no_lookahead(i1, i2)
692    }
693}
694
695impl EquivSerializersGeneral for super::BerLengthFmt {
696    proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
697        ber_length_fmt().lemma_serialize_equiv(v, obuf)
698    }
699}
700
701impl EquivSerializers for super::BerLengthFmt {
702    proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
703        ber_length_fmt().lemma_serialize_equiv_on_empty(v)
704    }
705}
706
707impl Parser<&[u8]> for super::BerLengthFmt {
708    type PT = super::BerLength;
709
710    fn parse(&self, ibuf: &&[u8]) -> PResult<Self::PT> {
711        let (n, first) = U8.parse(ibuf)?;
712        if first == 0x80u8 {
713            Ok((n, super::BerLength::Indefinite))
714        } else {
715            let (n, len) = super::LengthFmt::<false>.parse(ibuf)?;
716            Ok((n, super::BerLength::Definite(len)))
717        }
718    }
719}
720
721impl<Output: OutputBuf> Serializer<Output, super::BerLength> for super::BerLengthFmt {
722    fn serialize_into(&self, v: &super::BerLength, obuf: &mut Output) {
723        match v {
724            super::BerLength::Indefinite => U8.serialize_into(&0x80u8, obuf),
725            super::BerLength::Definite(n) => super::LengthFmt::<false>.serialize_into(n, obuf),
726        }
727    }
728}
729
730impl Prepare<super::BerLength> for super::BerLengthFmt {
731    fn prepare(&self, v: &super::BerLength) -> Result<usize, PreSerializeError> {
732        match v {
733            super::BerLength::Indefinite => Ok(1),
734            super::BerLength::Definite(n) => super::LengthFmt::<false>.prepare(n),
735        }
736    }
737}
738
739impl ByteLen<super::BerLength> for super::BerLengthFmt {
740    fn length(&self, v: &super::BerLength) -> usize {
741        match v {
742            super::BerLength::Indefinite => 1,
743            super::BerLength::Definite(n) => super::LengthFmt::<false>.length(n),
744        }
745    }
746}
747
748} // verus!