1use alloc::vec::Vec;
2
3use crate::{
4 properties::*,
5 regular::{
6 bytes::Fixed,
7 modifier::{
8 Cond, PartialIso, Pred, Refined, SpecPartialIso, SpecPartialIsoProof, SpecPred, TryMap,
9 },
10 sequence::{Continuation, POrSType, Pair, SpecPair},
11 uints::*,
12 variant::*,
13 },
14};
15use vstd::prelude::*;
16
17verus! {
18
19pub struct BtcVarint;
21
22impl View for BtcVarint {
23 type V = BtcVarint;
24
25 open spec fn view(&self) -> Self::V {
26 *self
27 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum VarInt {
33 U8(u8),
35 U16(u16),
37 U32(u32),
39 U64(u64),
41}
42
43impl View for VarInt {
44 type V = Self;
45
46 open spec fn view(&self) -> Self::V {
47 *self
48 }
49}
50
51impl SpecFrom<VarInt> for usize {
52 open spec fn spec_from(t: VarInt) -> usize {
53 match t {
54 VarInt::U8(t) => t as usize,
55 VarInt::U16(t) => t as usize,
56 VarInt::U32(t) => t as usize,
57 VarInt::U64(t) => t as usize,
58 }
59 }
60}
61
62impl From<VarInt> for usize {
63 fn ex_from(t: VarInt) -> usize {
64 match t {
65 VarInt::U8(t) => t as usize,
66 VarInt::U16(t) => t as usize,
67 VarInt::U32(t) => t as usize,
68 VarInt::U64(t) => t as usize,
69 }
70 }
71}
72
73impl VarInt {
74 pub open spec fn spec_as_usize(self) -> usize {
76 self.spec_into()
77 }
78
79 pub fn as_usize(self) -> (o: usize)
81 ensures
82 o@ == self.spec_as_usize(),
83 {
84 self.ex_into()
85 }
86}
87
88type VarintChoice = Choice<
89 Cond<Fixed<0>>,
90 Choice<
91 Cond<Refined<U16Le, PredU16LeFit>>,
92 Choice<Cond<Refined<U32Le, PredU32LeFit>>, Cond<Refined<U64Le, PredU64LeFit>>>,
93 >,
94>;
95
96type SpecBtcVarintInner = TryMap<SpecPair<U8, VarintChoice>, VarIntMapper>;
97
98type BtcVarintInner = TryMap<Pair<U8, VarintChoice, BtVarintCont>, VarIntMapper>;
99
100pub spec const SPEC_TAG_U16: u8 = 0xFD;
101
102pub spec const SPEC_TAG_U32: u8 = 0xFE;
103
104pub spec const SPEC_TAG_U64: u8 = 0xFF;
105
106pub exec static TAG_U16: u8
107 ensures
108 TAG_U16 == SPEC_TAG_U16,
109{
110 0xFD
111}
112
113pub exec static TAG_U32: u8
114 ensures
115 TAG_U32 == SPEC_TAG_U32,
116{
117 0xFE
118}
119
120pub exec static TAG_U64: u8
121 ensures
122 TAG_U64 == SPEC_TAG_U64,
123{
124 0xFF
125}
126
127pub exec static EMPTY_SLICE: &'static [u8]
128 ensures
129 EMPTY_SLICE@ == Seq::<u8>::empty(),
130{
131 assert(<_ as View>::view(&[]) =~= Seq::<u8>::empty());
132 &[]
133}
134
135pub exec static EMPTY: &'static &'static [u8]
136 ensures
137 EMPTY@ == Seq::<u8>::empty(),
138{
139 &EMPTY_SLICE
140}
141
142pub open spec fn spec_btc_varint_inner() -> SpecBtcVarintInner {
144 TryMap {
145 inner: Pair::spec_new(
146 U8,
147 |t: u8|
148 ord_choice!(
149 Cond { cond: t <= 0xFC, inner: Fixed::<0> },
150 Cond { cond: t == SPEC_TAG_U16, inner: Refined { inner: U16Le, predicate: PredU16LeFit } },
151 Cond { cond: t == SPEC_TAG_U32, inner: Refined { inner: U32Le, predicate: PredU32LeFit } },
152 Cond { cond: t == SPEC_TAG_U64, inner: Refined { inner: U64Le, predicate: PredU64LeFit } },
153 ),
154 ),
155 mapper: VarIntMapper,
156 }
157}
158
159fn btc_varint_inner() -> (o: BtcVarintInner)
160 ensures
161 o@ == spec_btc_varint_inner(),
162{
163 TryMap { inner: Pair::new(U8, BtVarintCont), mapper: VarIntMapper }
164}
165
166pub struct PredU16LeFit;
168
169impl View for PredU16LeFit {
170 type V = Self;
171
172 open spec fn view(&self) -> Self::V {
173 *self
174 }
175}
176
177impl Pred<u16> for PredU16LeFit {
178 fn apply(&self, i: &u16) -> bool {
179 *i >= 0xFD
180 }
181}
182
183impl SpecPred<u16> for PredU16LeFit {
184 open spec fn spec_apply(&self, i: &u16) -> bool {
185 *i >= 0xFD
186 }
187}
188
189pub struct PredU32LeFit;
191
192impl View for PredU32LeFit {
193 type V = Self;
194
195 open spec fn view(&self) -> Self::V {
196 *self
197 }
198}
199
200impl Pred<u32> for PredU32LeFit {
201 fn apply(&self, i: &u32) -> bool {
202 *i >= 0x10000
203 }
204}
205
206impl SpecPred<u32> for PredU32LeFit {
207 open spec fn spec_apply(&self, i: &u32) -> bool {
208 *i >= 0x10000
209 }
210}
211
212pub struct PredU64LeFit;
214
215impl View for PredU64LeFit {
216 type V = Self;
217
218 open spec fn view(&self) -> Self::V {
219 *self
220 }
221}
222
223impl Pred<u64> for PredU64LeFit {
224 fn apply(&self, i: &u64) -> bool {
225 *i >= 0x100000000
226 }
227}
228
229impl SpecPred<u64> for PredU64LeFit {
230 open spec fn spec_apply(&self, i: &u64) -> bool {
231 *i >= 0x100000000
232 }
233}
234
235impl SpecTryFrom<(u8, Either<Seq<u8>, Either<u16, Either<u32, u64>>>)> for VarInt {
236 type Error = ();
237
238 open spec fn spec_try_from(t: (u8, Either<Seq<u8>, Either<u16, Either<u32, u64>>>)) -> Result<
239 Self,
240 Self::Error,
241 > {
242 match t.1 {
243 inj_ord_choice_pat!(x, *, *, *) => {
244 if x == Seq::<u8>::empty() {
245 Ok(VarInt::U8(t.0))
246 } else {
247 Err(())
248 }
249 },
250 inj_ord_choice_pat!(*, x, *, *) => {
251 if t.0 == SPEC_TAG_U16 {
252 Ok(VarInt::U16(x))
253 } else {
254 Err(())
255 }
256 },
257 inj_ord_choice_pat!(*, *, x, *) => {
258 if t.0 == SPEC_TAG_U32 {
259 Ok(VarInt::U32(x))
260 } else {
261 Err(())
262 }
263 },
264 inj_ord_choice_pat!(*, *, *, x) => {
265 if t.0 == SPEC_TAG_U64 {
266 Ok(VarInt::U64(x))
267 } else {
268 Err(())
269 }
270 },
271 }
272 }
273}
274
275impl TryFrom<(u8, Either<&[u8], Either<u16, Either<u32, u64>>>)> for VarInt {
276 type Error = ();
277
278 fn ex_try_from(t: (u8, Either<&[u8], Either<u16, Either<u32, u64>>>)) -> Result<
279 Self,
280 Self::Error,
281 > {
282 match t.1 {
283 inj_ord_choice_pat!(x, *, *, *) => {
284 if compare_slice(EMPTY, x) {
285 assert(x@ == Seq::<u8>::empty());
286 Ok(VarInt::U8(t.0))
287 } else {
288 Err(())
289 }
290 },
291 inj_ord_choice_pat!(*, x, *, *) => {
292 if t.0 == TAG_U16 {
293 Ok(VarInt::U16(x))
294 } else {
295 Err(())
296 }
297 },
298 inj_ord_choice_pat!(*, *, x, *) => {
299 if t.0 == TAG_U32 {
300 Ok(VarInt::U32(x))
301 } else {
302 Err(())
303 }
304 },
305 inj_ord_choice_pat!(*, *, *, x) => {
306 if t.0 == TAG_U64 {
307 Ok(VarInt::U64(x))
308 } else {
309 Err(())
310 }
311 },
312 }
313 }
314}
315
316impl SpecTryFrom<VarInt> for (u8, Either<Seq<u8>, Either<u16, Either<u32, u64>>>) {
317 type Error = ();
318
319 open spec fn spec_try_from(t: VarInt) -> Result<Self, Self::Error> {
320 match t {
321 VarInt::U8(t) => Ok((t, inj_ord_choice_result!(Seq::<u8>::empty(), *, *, *))),
322 VarInt::U16(x) => Ok((SPEC_TAG_U16, inj_ord_choice_result!(*, x, *, *))),
323 VarInt::U32(x) => Ok((SPEC_TAG_U32, inj_ord_choice_result!(*, *, x, *))),
324 VarInt::U64(x) => Ok((SPEC_TAG_U64, inj_ord_choice_result!(*, *, *, x))),
325 }
326 }
327}
328
329impl<'x> TryFrom<&'x VarInt> for (
330 &'x u8,
331 Either<&'x &'x [u8], Either<&'x u16, Either<&'x u32, &'x u64>>>,
332) {
333 type Error = ();
334
335 fn ex_try_from(t: &'x VarInt) -> Result<Self, Self::Error> {
336 match t {
337 VarInt::U8(t) => { Ok((t, inj_ord_choice_result!(EMPTY, *, *, *))) },
338 VarInt::U16(x) => Ok((&TAG_U16, inj_ord_choice_result!(*, x, *, *))),
339 VarInt::U32(x) => Ok((&TAG_U32, inj_ord_choice_result!(*, *, x, *))),
340 VarInt::U64(x) => Ok((&TAG_U64, inj_ord_choice_result!(*, *, *, x))),
341 }
342 }
343}
344
345pub struct VarIntMapper;
347
348impl View for VarIntMapper {
349 type V = Self;
350
351 open spec fn view(&self) -> Self::V {
352 *self
353 }
354}
355
356impl SpecPartialIso for VarIntMapper {
357 type Src = (u8, Either<Seq<u8>, Either<u16, Either<u32, u64>>>);
358
359 type Dst = VarInt;
360}
361
362impl SpecPartialIsoProof for VarIntMapper {
363 proof fn spec_iso(s: Self::Src) {
364 }
365
366 proof fn spec_iso_rev(s: Self::Dst) {
367 }
368}
369
370impl<'x> PartialIso<'x> for VarIntMapper {
371 type Src = (u8, Either<&'x [u8], Either<u16, Either<u32, u64>>>);
372
373 type Dst = VarInt;
374
375 type RefSrc = (&'x u8, Either<&'x &'x [u8], Either<&'x u16, Either<&'x u32, &'x u64>>>);
376}
377
378impl SpecCombinator for BtcVarint {
379 type Type = VarInt;
380
381 open spec fn requires(&self) -> bool {
382 spec_btc_varint_inner().requires()
383 }
384
385 open spec fn wf(&self, v: Self::Type) -> bool {
386 spec_btc_varint_inner().wf(v)
387 }
388
389 open spec fn spec_parse(&self, s: Seq<u8>) -> Option<(int, Self::Type)> {
390 spec_btc_varint_inner().spec_parse(s)
391 }
392
393 open spec fn spec_serialize(&self, v: Self::Type) -> Seq<u8> {
394 spec_btc_varint_inner().spec_serialize(v)
395 }
396}
397
398impl SecureSpecCombinator for BtcVarint {
399 open spec fn is_prefix_secure() -> bool {
400 SpecBtcVarintInner::is_prefix_secure()
401 }
402
403 open spec fn is_productive(&self) -> bool {
404 spec_btc_varint_inner().is_productive()
405 }
406
407 proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
408 spec_btc_varint_inner().lemma_prefix_secure(s1, s2);
409 }
410
411 proof fn theorem_serialize_parse_roundtrip(&self, v: Self::Type) {
412 spec_btc_varint_inner().theorem_serialize_parse_roundtrip(v);
413 }
414
415 proof fn theorem_parse_serialize_roundtrip(&self, s: Seq<u8>) {
416 spec_btc_varint_inner().theorem_parse_serialize_roundtrip(s);
417 }
418
419 proof fn lemma_parse_length(&self, s: Seq<u8>) {
420 spec_btc_varint_inner().lemma_parse_length(s);
421 }
422
423 proof fn lemma_parse_productive(&self, s: Seq<u8>) {
424 spec_btc_varint_inner().lemma_parse_productive(s);
425 }
426}
427
428pub struct BtVarintCont;
430
431impl View for BtVarintCont {
432 type V = spec_fn(u8) -> VarintChoice;
433
434 open spec fn view(&self) -> Self::V {
435 spec_btc_varint_inner().inner.snd
436 }
437}
438
439impl<'a> Continuation<POrSType<&'a u8, &u8>> for BtVarintCont {
440 type Output = VarintChoice;
441
442 open spec fn requires(&self, t: POrSType<&'a u8, &u8>) -> bool {
443 true
444 }
445
446 open spec fn ensures(&self, t: POrSType<&'a u8, &u8>, o: Self::Output) -> bool {
447 o@ == (self@)(t@)
449 }
450
451 fn apply(&self, t: POrSType<&'a u8, &u8>) -> Self::Output {
452 let t = match t {
453 POrSType::P(t) => t,
454 POrSType::S(t) => t,
455 };
456 ord_choice!(
457 Cond { cond: *t <= 0xFC, inner: Fixed::<0> },
458 Cond { cond: *t == 0xFD, inner: Refined { inner: U16Le, predicate: PredU16LeFit } },
459 Cond { cond: *t == 0xFE, inner: Refined { inner: U32Le, predicate: PredU32LeFit } },
460 Cond { cond: *t == 0xFF, inner: Refined { inner: U64Le, predicate: PredU64LeFit } },
461 )
462 }
463}
464
465impl<'a> Combinator<'a, &'a [u8], Vec<u8>> for BtcVarint {
466 type Type = VarInt;
467
468 type SType = &'a VarInt;
469
470 fn length(&self, v: Self::SType) -> usize {
471 match v {
472 VarInt::U8(_) => 1,
473 VarInt::U16(_) => 3,
474 VarInt::U32(_) => 5,
475 VarInt::U64(_) => 9,
476 }
477 }
478
479 fn parse(&self, s: &'a [u8]) -> (res: Result<(usize, Self::Type), ParseError>) {
480 <_ as Combinator<'a, &'a [u8], Vec<u8>>>::parse(&btc_varint_inner(), s)
481 }
482
483 fn serialize(&self, v: Self::SType, data: &mut Vec<u8>, pos: usize) -> (res: Result<
484 usize,
485 SerializeError,
486 >) {
487 btc_varint_inner().serialize(v, data, pos)
488 }
489}
490
491#[cfg(test)]
493mod tests {
494 use super::*;
495
496 proof fn well_formed_varint() {
497 let good1 = VarInt::U8(0xFC);
498 let good2 = VarInt::U16(0xFD);
499 let good3 = VarInt::U32(0x10000);
500 let good4 = VarInt::U64(0x100000000);
501 assert(BtcVarint.wf(good1));
502 assert(BtcVarint.wf(good2));
503 assert(BtcVarint.wf(good3));
504 assert(BtcVarint.wf(good4));
505
506 let bad1 = VarInt::U8(0xFD);
507 let bad2 = VarInt::U16(0xFC);
508 let bad3 = VarInt::U32(0xFFFF);
509 let bad4 = VarInt::U64(0xFFFFFFFF);
510 assert(!BtcVarint.wf(bad1));
511 assert(!BtcVarint.wf(bad2));
512 assert(!BtcVarint.wf(bad3));
513 assert(!BtcVarint.wf(bad4));
514 }
515
516}
517
518}