1use crate::core::exec::input::InputBuf;
3use crate::core::exec::parser::*;
4use crate::{
5 combinators::{mapped::spec::*, recursive::*, Alt, FixWith, Mapped, Pair, Refined, U8},
6 core::{proof::*, spec::*},
7};
8use vstd::arithmetic::div_mod::*;
9use vstd::arithmetic::mul::*;
10use vstd::prelude::*;
11
12verus! {
13
14pub type ULeb128Fmt<const MINIMAL: bool, const RECLIMIT: usize> = FixWith<
15 RECLIMIT,
16 ULeb128RecBody<MINIMAL>,
17 (),
18>;
19
20pub open spec fn uleb128_fmt<const MINIMAL: bool, const N: usize>() -> ULeb128Fmt<MINIMAL, N> {
21 FixWith(ULeb128RecBody::<MINIMAL>, ())
22}
23
24pub struct ULeb128RecBody<const MINIMAL: bool>;
25
26impl<const MINIMAL: bool> SpecRecBody for ULeb128RecBody<MINIMAL> {
27 type Param = ();
28
29 type T = nat;
30
31 type Body = Alt<
32 TerminalByteNat,
33 Mapped<
34 Pair<ContinuationByte, Refined<BundledSpecs<nat>, PredFnSpec<nat>>>,
35 FnSpecMapper<(u8, nat), nat>,
36 >,
37 >;
38
39 open spec fn spec_body(
43 &self,
44 _param: (),
45 rec: ParamRecSpecs<Self::Param, Self::T>,
46 ) -> Self::Body {
47 Alt(
48 terminal_byte_nat(),
49 Mapped {
50 inner: Pair(continuation_byte(), Refined(rec(()), |v: nat| MINIMAL ==> v > 0)),
52 mapper: (
55 |pair: (u8, nat)| 128 * pair.1 + pair.0 as nat,
56 |o: nat| ((o % 128) as u8, o / 128),
57 ),
58 },
59 )
60 }
61}
62
63pub type TerminalByteNat = Mapped<TerminalByte, TermByteFromToNat>;
64
65pub type TerminalByte = Refined<U8, PredFnSpec<u8>>;
66
67pub type ContinuationByte = Mapped<Refined<U8, PredFnSpec<u8>>, LowBitsMask>;
68
69pub const CONTINUATION_BIT: u8 = 0x80;
70
71pub open spec fn terminal_byte_nat() -> TerminalByteNat {
73 Mapped { inner: terminal_byte(), mapper: TermByteFromToNat }
74}
75
76pub open spec fn terminal_byte() -> TerminalByte {
78 Refined(U8, |b: u8| b < CONTINUATION_BIT)
79}
80
81pub open spec fn continuation_byte() -> ContinuationByte {
83 Mapped { inner: Refined(U8, |b: u8| b >= CONTINUATION_BIT), mapper: LowBitsMask }
84}
85
86pub struct TermByteFromToNat;
87
88impl SpecMapper for TermByteFromToNat {
89 type In = u8;
90
91 type Out = nat;
92
93 open spec fn wf_in(&self, i: Self::In) -> bool {
94 i < CONTINUATION_BIT
95 }
96
97 open spec fn wf_out(&self, o: Self::Out) -> bool {
98 o < CONTINUATION_BIT
99 }
100
101 open spec fn spec_map(&self, i: Self::In) -> Self::Out {
102 i as nat
103 }
104
105 open spec fn spec_map_rev(&self, o: Self::Out) -> Self::In {
106 o as u8
107 }
108}
109
110pub struct LowBitsMask;
111
112impl SpecMapper for LowBitsMask {
113 type In = u8;
114
115 type Out = u8;
116
117 open spec fn wf_in(&self, i: Self::In) -> bool {
118 i >= CONTINUATION_BIT
119 }
120
121 open spec fn wf_out(&self, o: Self::Out) -> bool {
122 o < CONTINUATION_BIT
123 }
124
125 open spec fn spec_map(&self, i: Self::In) -> Self::Out {
126 (i - CONTINUATION_BIT) as u8
129 }
130
131 open spec fn spec_map_rev(&self, o: Self::Out) -> Self::In {
132 (o + CONTINUATION_BIT) as u8
135 }
136}
137
138impl LossyMapper for TermByteFromToNat {
139 proof fn lemma_sound_mapper(&self, o: Self::Out) {
140 }
141
142 proof fn lemma_mapper_wf_out_in(&self, o: Self::Out) {
143 }
144}
145
146impl LosslessMapper for TermByteFromToNat {
147 proof fn lemma_lossless_mapper(&self, i: Self::In) {
148 }
149
150 proof fn lemma_mapper_wf_in_out(&self, i: Self::In) {
151 }
152}
153
154impl LossyMapper for LowBitsMask {
155 proof fn lemma_sound_mapper(&self, o: Self::Out) {
156 }
157
158 proof fn lemma_mapper_wf_out_in(&self, o: Self::Out) {
159 }
160}
161
162impl LosslessMapper for LowBitsMask {
163 proof fn lemma_lossless_mapper(&self, i: Self::In) {
164 }
165
166 proof fn lemma_mapper_wf_in_out(&self, i: Self::In) {
167 }
168}
169
170pub struct ULeb128<const MINIMAL: bool, const N: usize>;
171
172mod leb128_derived_specs {
173 use super::*;
174
175 impl<const MINIMAL: bool, const N: usize> SpecParser for ULeb128<MINIMAL, N> {
176 type PVal = nat;
177
178 open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
179 uleb128_fmt::<MINIMAL, N>().spec_parse(ibuf)
180 }
181 }
182
183 impl<const MINIMAL: bool, const N: usize> Consistency for ULeb128<MINIMAL, N> {
184 type Val = nat;
185
186 open spec fn consistent(&self, v: Self::Val) -> bool {
187 uleb128_fmt::<MINIMAL, N>().consistent(v)
188 }
189 }
190
191 impl<const MINIMAL: bool, const N: usize> SpecSerializerDps for ULeb128<MINIMAL, N> {
192 type SValue = nat;
193
194 open spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
195 uleb128_fmt::<MINIMAL, N>().spec_serialize_dps(v, obuf)
196 }
197 }
198
199 impl<const MINIMAL: bool, const N: usize> SpecSerializer for ULeb128<MINIMAL, N> {
200 type SVal = nat;
201
202 open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
203 uleb128_fmt::<MINIMAL, N>().spec_serialize(v)
204 }
205 }
206
207 impl<const MINIMAL: bool, const N: usize> SpecByteLen for ULeb128<MINIMAL, N> {
208 type T = nat;
209
210 open spec fn byte_len(&self, v: Self::T) -> nat {
211 uleb128_fmt::<MINIMAL, N>().byte_len(v)
212 }
213 }
214
215}
216
217mod leb128_derived_proofs {
218 use super::*;
219
220 impl<const MINIMAL: bool> SafeParserRecBody for ULeb128RecBody<MINIMAL> {
221 proof fn lemma_body_safe_inv_preservation(
222 &self,
223 _param: (),
224 rec: ParamRecSpecs<Self::Param, Self::T>,
225 ) {
226 }
227 }
228
229 impl SoundParserRecBody for ULeb128RecBody<true> {
230 proof fn lemma_body_sound_inv_preservation(
231 &self,
232 _param: (),
233 rec: ParamRecSpecs<Self::Param, Self::T>,
234 ) {
235 }
236 }
237
238 impl<const MINIMAL: bool> NoLookAheadRecBody for ULeb128RecBody<MINIMAL> {
239 proof fn lemma_body_no_lookahead_inv_preservation(
240 &self,
241 _param: (),
242 rec: ParamRecSpecs<Self::Param, Self::T>,
243 ) {
244 reveal(disjoint_domains);
245 }
246 }
247
248 impl<const MINIMAL: bool> ProductiveRecBody for ULeb128RecBody<MINIMAL> {
249 proof fn lemma_body_productive_inv_preservation(
250 &self,
251 param: Self::Param,
252 rec: ParamRecSpecs<Self::Param, Self::T>,
253 ) {
254 }
255 }
256
257 impl NonMalleableRecBody for ULeb128RecBody<true> {
258 proof fn lemma_body_nonmal_inv_preservation(
259 &self,
260 _param: (),
261 rec: ParamRecSpecs<Self::Param, Self::T>,
262 ) {
263 }
264 }
265
266 impl<const MINIMAL: bool> GoodSerializerRecBody for ULeb128RecBody<MINIMAL> {
267 proof fn lemma_s_body_serialize_inv_preservation(
268 &self,
269 _param: (),
270 rec: ParamRecSpecs<Self::Param, Self::T>,
271 ) {
272 }
273 }
274
275 impl<const MINIMAL: bool> NonTailFmtRecBody for ULeb128RecBody<MINIMAL> {
276 proof fn lemma_s_body_dps_serialize_dps_inv_preservation(
277 &self,
278 _param: (),
279 rec: ParamRecSpecs<Self::Param, Self::T>,
280 ) {
281 }
282 }
283
284 impl<const MINIMAL: bool> SPRoundTripDpsRecBody for ULeb128RecBody<MINIMAL> {
285 proof fn lemma_body_sp_roundtrip_dps_inv_preservation(
286 &self,
287 _param: (),
288 rec: ParamRecSpecs<Self::Param, Self::T>,
289 ) {
290 reveal(disjoint_domains);
291 }
292 }
293
294 impl<const MINIMAL: bool> EquivSerializersGeneralRecBody for ULeb128RecBody<MINIMAL> {
295 proof fn lemma_s_body_equiv_general_inv_preservation(
296 &self,
297 _param: (),
298 rec: ParamRecSpecs<Self::Param, Self::T>,
299 ) {
300 }
301 }
302
303 impl<const MINIMAL: bool, const N: usize> SafeParser for ULeb128<MINIMAL, N> {
304 proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
305 uleb128_fmt::<MINIMAL, N>().lemma_parse_safe(ibuf);
306 }
307 }
308
309 impl<const MINIMAL: bool, const N: usize> Productive for ULeb128<MINIMAL, N> {
310 proof fn lemma_productive(&self, s: Seq<u8>) {
311 uleb128_fmt::<MINIMAL, N>().lemma_productive(s);
312 }
313 }
314
315 impl<const N: usize> SoundParser for ULeb128<true, N> {
316 proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
317 uleb128_fmt::<true, N>().lemma_parse_sound_consumption(ibuf);
318 }
319
320 proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
321 uleb128_fmt::<true, N>().lemma_parse_sound_value(ibuf);
322 }
323 }
324
325 impl<const MINIMAL: bool, const N: usize> NonTailFmt for ULeb128<MINIMAL, N> {
326 proof fn lemma_serialize_dps_prepend(&self, v: Self::SValue, obuf: Seq<u8>) {
327 uleb128_fmt::<MINIMAL, N>().lemma_serialize_dps_prepend(v, obuf);
328 }
329
330 proof fn lemma_serialize_dps_len(&self, v: Self::SValue, obuf: Seq<u8>) {
331 uleb128_fmt::<MINIMAL, N>().lemma_serialize_dps_len(v, obuf);
332 }
333 }
334
335 impl<const MINIMAL: bool, const N: usize> GoodSerializer for ULeb128<MINIMAL, N> {
336 proof fn lemma_serialize_len(&self, v: Self::SVal) {
337 uleb128_fmt::<MINIMAL, N>().lemma_serialize_len(v);
338 }
339 }
340
341 impl<const MINIMAL: bool, const N: usize> SPRoundTripDps for ULeb128<MINIMAL, N> {
342 proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
343 uleb128_fmt::<MINIMAL, N>().theorem_serialize_dps_parse_roundtrip(v, obuf);
344 }
345 }
346
347 impl<const MINIMAL: bool, const N: usize> NoLookAhead for ULeb128<MINIMAL, N> {
348 proof fn lemma_no_lookahead(&self, i1: Seq<u8>, i2: Seq<u8>) {
349 uleb128_fmt::<MINIMAL, N>().lemma_no_lookahead(i1, i2);
350 }
351 }
352
353 impl<const N: usize> NonMalleable for ULeb128<true, N> {
354 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
355 uleb128_fmt::<true, N>().lemma_parse_non_malleable(buf1, buf2);
356 }
357 }
358
359 impl<const MINIMAL: bool, const N: usize> EquivSerializersGeneral for ULeb128<MINIMAL, N> {
360 proof fn lemma_serialize_equiv(&self, v: Self::SVal, obuf: Seq<u8>) {
361 uleb128_fmt::<MINIMAL, N>().lemma_serialize_equiv(v, obuf);
362 }
363 }
364
365 impl<const MINIMAL: bool, const N: usize> EquivSerializers for ULeb128<MINIMAL, N> {
366 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
367 uleb128_fmt::<MINIMAL, N>().lemma_serialize_equiv_on_empty(v);
368 }
369 }
370
371}
372
373}