vest_lib/regular/
tag.rs

1use alloc::vec::Vec;
2
3use super::{
4    bytes,
5    leb128::{UInt, UnsignedLEB128},
6    modifier::{Pred, Refined, SpecPred},
7    uints::*,
8};
9use crate::properties::*;
10use vstd::prelude::*;
11
12verus! {
13
14/// tag predicate that matches the input with a given value
15pub struct TagPred<T>(pub T);
16
17impl<T: View> View for TagPred<T> {
18    type V = TagPred<T::V>;
19
20    open spec fn view(&self) -> Self::V {
21        TagPred(self.0@)
22    }
23}
24
25impl<T> SpecPred<T> for TagPred<T> {
26    open spec fn spec_apply(&self, i: &T) -> bool {
27        *i == self.0
28    }
29}
30
31/// Generic tag combinator that matches the input with a given value and discards it
32/// e.g. `Tag(U8, 0)` matches the byte `0`; `Tag(Fixed::<3>, &[1, 2, 3])` matches the
33/// bytes `[1, 2, 3]`
34pub struct Tag<Inner, T>(pub Refined<Inner, TagPred<T>>);
35
36impl<Inner, T> Tag<Inner, T> {
37    /// Creates a new `Tag` combinator.
38    pub fn new(inner: Inner, tag: T) -> (o: Self)
39        ensures
40            o == Tag(Refined { inner, predicate: TagPred(tag) }),
41    {
42        Tag(Refined { inner, predicate: TagPred(tag) })
43    }
44
45    /// Creates a new `Tag` combinator.
46    pub open spec fn spec_new(inner: Inner, tag: T) -> (o: Self) {
47        Tag(Refined { inner, predicate: TagPred(tag) })
48    }
49}
50
51impl<Inner: View, T: View> View for Tag<Inner, T> {
52    type V = Tag<Inner::V, T::V>;
53
54    open spec fn view(&self) -> Self::V {
55        Tag(self.0@)
56    }
57}
58
59impl<Inner: SpecCombinator<Type = T>, T> SpecCombinator for Tag<Inner, T> {
60    type Type = ();
61
62    open spec fn requires(&self) -> bool {
63        self.0.requires()
64    }
65
66    open spec fn wf(&self, v: Self::Type) -> bool {
67        self.0.wf(self.0.predicate.0)
68    }
69
70    open spec fn spec_parse(&self, s: Seq<u8>) -> Option<(int, Self::Type)> {
71        if let Some((n, _)) = self.0.spec_parse(s) {
72            Some((n, ()))
73        } else {
74            None
75        }
76    }
77
78    open spec fn spec_serialize(&self, v: Self::Type) -> Seq<u8> {
79        self.0.spec_serialize(self.0.predicate.0)
80    }
81}
82
83impl<Inner: SecureSpecCombinator<Type = T>, T> SecureSpecCombinator for Tag<Inner, T> {
84    open spec fn is_prefix_secure() -> bool {
85        Inner::is_prefix_secure()
86    }
87
88    open spec fn is_productive(&self) -> bool {
89        self.0.is_productive()
90    }
91
92    proof fn theorem_serialize_parse_roundtrip(&self, v: Self::Type) {
93        self.0.theorem_serialize_parse_roundtrip(self.0.predicate.0);
94    }
95
96    proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
97        self.0.theorem_parse_serialize_roundtrip(buf);
98    }
99
100    proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
101        self.0.lemma_prefix_secure(s1, s2);
102        assert(Self::is_prefix_secure() ==> self.spec_parse(s1) is Some ==> self.spec_parse(
103            s1.add(s2),
104        ) == self.spec_parse(s1));
105    }
106
107    proof fn lemma_parse_length(&self, s: Seq<u8>) {
108        self.0.lemma_parse_length(s);
109    }
110
111    proof fn lemma_parse_productive(&self, s: Seq<u8>) {
112        self.0.lemma_parse_productive(s);
113    }
114}
115
116impl Pred<u8> for TagPred<u8> {
117    fn apply(&self, i: &u8) -> bool {
118        *i == self.0
119    }
120}
121
122impl Pred<u16> for TagPred<u16> {
123    fn apply(&self, i: &u16) -> bool {
124        *i == self.0
125    }
126}
127
128impl Pred<u32> for TagPred<u32> {
129    fn apply(&self, i: &u32) -> bool {
130        *i == self.0
131    }
132}
133
134impl Pred<u64> for TagPred<u64> {
135    fn apply(&self, i: &u64) -> bool {
136        *i == self.0
137    }
138}
139
140impl<'a, const N: usize> Pred<&'a [u8]> for TagPred<[u8; N]> {
141    fn apply(&self, i: &&'a [u8]) -> bool {
142        self.0.as_slice().compare(i)
143    }
144}
145
146macro_rules! impl_combinator_for_uint_tag {
147    ($combinator:ty, $int_type:ty) => {
148        ::vstd::prelude::verus! {
149            impl<'x, I, O> Combinator<'x, I, O> for Tag<$combinator, $int_type> where
150                I: VestPublicInput,
151                O: VestPublicOutput<I>,
152            {
153                type Type = ();
154
155                type SType = ();
156
157                fn length(&self, v: Self::SType) -> usize {
158                    <_ as Combinator<I, O>>::length(&self.0, &self.0.predicate.0)
159                }
160
161                open spec fn ex_requires(&self) -> bool {
162                    <_ as Combinator<'x, I, O>>::ex_requires(&self.0)
163                }
164
165                fn parse(&self, s: I) -> Result<(usize, Self::Type), ParseError> {
166                    let (n, _) = <_ as Combinator<'x, I, O>>::parse(&self.0, s)?;
167                    Ok((n, ()))
168                }
169
170                fn serialize(&self, v: Self::SType, data: &mut O, pos: usize) -> Result<usize, SerializeError> {
171                    self.0.serialize(&self.0.predicate.0, data, pos)
172                }
173            }
174        } // verus!
175    };
176}
177
178impl_combinator_for_uint_tag!(U8, u8);
179
180impl_combinator_for_uint_tag!(U16Le, u16);
181
182// impl_combinator_for_uint_tag!(U24Le, u24);
183impl_combinator_for_uint_tag!(U32Le, u32);
184
185impl_combinator_for_uint_tag!(U64Le, u64);
186
187impl_combinator_for_uint_tag!(U16Be, u16);
188
189// impl_combinator_for_uint_tag!(U24Be, u24);
190impl_combinator_for_uint_tag!(U32Be, u32);
191
192impl_combinator_for_uint_tag!(U64Be, u64);
193
194impl_combinator_for_uint_tag!(UnsignedLEB128, UInt);
195
196impl<'x, const N: usize> Combinator<'x, &'x [u8], Vec<u8>> for Tag<
197    bytes::Fixed::<N>,
198    [u8; N],
199> where  {
200    type Type = ();
201
202    type SType = ();
203
204    fn length(&self, _v: Self::SType) -> usize {
205        N
206    }
207
208    open spec fn ex_requires(&self) -> bool {
209        <_ as Combinator<'x, &'x [u8], Vec<u8>>>::ex_requires(&self.0)
210    }
211
212    fn parse(&self, s: &'x [u8]) -> Result<(usize, Self::Type), ParseError> {
213        let (n, _) = <_ as Combinator<'x, &'x [u8], Vec<u8>>>::parse(&self.0, s)?;
214        Ok((n, ()))
215    }
216
217    fn serialize(&self, v: Self::SType, data: &mut Vec<u8>, pos: usize) -> Result<
218        usize,
219        SerializeError,
220    > {
221        self.0.serialize(&self.0.predicate.0.as_slice(), data, pos)
222    }
223}
224
225// old code
226// /// generic tag combinator that matches the input with a given value and discards it
227// /// e.g. `Tag(Int::<u8>, 0)` matches the byte `0`; `Tag(Bytes::<3>, &[1, 2, 3])` matches the bytes `[1, 2, 3]`
228// pub struct Tag<Inner, T>(pub Inner, pub T);
229//
230// impl<Inner, T> View for Tag<Inner, T> where Inner: View, T: View {
231//     type V = Tag<Inner::V, T::V>;
232//
233//     open spec fn view(&self) -> Self::V {
234//         Tag(self.0@, self.1@)
235//     }
236// }
237//
238// impl<Inner, T> SpecCombinator for Tag<Inner, T> where Inner: SpecCombinator<SpecResult = T> {
239//     type SpecResult = ();
240//
241//     open spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
242//         match self.0.spec_parse(s) {
243//             Ok((n, v)) if v == self.1 => Ok((n, ())),
244//             _ => Err(()),
245//         }
246//     }
247//
248//     open spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
249//         self.0.spec_serialize(self.1)
250//     }
251//
252//     proof fn spec_parse_wf(&self, s: Seq<u8>) {
253//         self.0.spec_parse_wf(s);
254//     }
255// }
256//
257// impl<Inner, T> SecureSpecCombinator for Tag<Inner, T> where
258//     Inner: SecureSpecCombinator<SpecResult = T>,
259//  {
260//     open spec fn spec_is_prefix_secure() -> bool {
261//         Inner::spec_is_prefix_secure()
262//     }
263//
264//     proof fn theorem_serialize_parse_roundtrip(&self, v: ()) {
265//         self.0.theorem_serialize_parse_roundtrip(self.1);
266//     }
267//
268//     proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
269//         self.0.theorem_parse_serialize_roundtrip(buf);
270//     }
271//
272//     proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
273//         self.0.lemma_prefix_secure(s1, s2);
274//     }
275// }
276//
277// // the line `for <'a, 'b>Inner::Result<'a>: Compare<Inner::Result<'b>> + From<T>`
278// // says that `Inner::Result<'a>` must impl `From<T> for all lifetimes `'a`
279// // at the type level, this means even a static `Inner::Result<'static>` can be converted from
280// // `T`, which in turn mandates that `T: 'static` (if both `T` and `Inner::Result<'a>` are
281// // types without actual lifetimes, e.g. `u8`, then it's fine)
282// //
283// // it would be nice if Rust supports "existential" lifetimes like:
284// // `exist <'a>Inner::Result<'a>: From<T>`
285// impl<Inner, T> Combinator for Tag<Inner, T> where
286//     Inner: Combinator,
287//     Inner::V: SecureSpecCombinator<SpecResult = T::V>,
288//     T: View<V = <Inner::Owned as View>::V> + Copy,
289//     for <'a, 'b>Inner::Result<'a>: Compare<Inner::Result<'b>> + From<T>,
290//  {
291//     type Result<'a> = ();
292//
293//     type Owned = ();
294//
295//     open spec fn spec_length(&self) -> Option<usize> {
296//         self.0.spec_length()
297//     }
298//
299//     fn length(&self) -> Option<usize> {
300//         self.0.length()
301//     }
302//
303//     fn exec_is_prefix_secure() -> bool {
304//         Inner::exec_is_prefix_secure()
305//     }
306//
307//     open spec fn parse_requires(&self) -> bool {
308//         self.0.parse_requires()
309//     }
310//
311//     fn parse(&self, s: &[u8]) -> (res: Result<(usize, ()), ()>) {
312//         match self.0.parse(s) {
313//             Ok((n, v)) if v.compare(&self.1.ex_into()) => Ok((n, ())),
314//             _ => Err(()),
315//         }
316//     }
317//
318//     open spec fn serialize_requires(&self) -> bool {
319//         self.0.serialize_requires()
320//     }
321//
322//     fn serialize(&self, v: (), data: &mut Vec<u8>, pos: usize) -> (res: Result<usize, ()>) {
323//         self.0.serialize(self.1.ex_into(), data, pos)
324//     }
325// }
326//
327// pub type U8Tag = Tag<Int<u8>, u8>;
328//
329// pub type U16Tag = Tag<Int<u16>, u16>;
330//
331// pub type U32Tag = Tag<Int<u32>, u32>;
332//
333// pub type U64Tag = Tag<Int<u64>, u64>;
334//
335// pub type SpecStaticBytesTag<const N: usize> = Tag<BytesN<N>, Seq<u8>>;
336//
337// pub type StaticBytesTag<const N: usize> = Tag<BytesN<N>, &'static [u8; N]>;
338//
339// /// combinator for matching a dynamic byte slice
340// ///
341// /// **Note**: due to the current limitations of Rust borrow checker
342// /// the generic `Tag` combinator cannot be used with dynamic byte slices (`Tag<Bytes, &'a [u8]>`)
343// pub struct DynamicBytesTag<'a>(pub Bytes, pub &'a [u8]);
344//
345// pub struct SpecDynamicBytesTag(pub Bytes, pub Seq<u8>);
346//
347// impl<'a> View for DynamicBytesTag<'a> {
348//     type V = SpecDynamicBytesTag;
349//
350//     open spec fn view(&self) -> Self::V {
351//         SpecDynamicBytesTag(self.0@, self.1@)
352//     }
353// }
354//
355// impl SpecCombinator for SpecDynamicBytesTag {
356//     type SpecResult = ();
357//
358//     open spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
359//         match self.0.spec_parse(s) {
360//             Ok((n, v)) if n == self.1.len() && v == self.1 => Ok((n, ())),
361//             _ => Err(()),
362//         }
363//     }
364//
365//     open spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
366//         self.0.spec_serialize(self.1)
367//     }
368//
369//     proof fn spec_parse_wf(&self, s: Seq<u8>) {
370//     }
371// }
372//
373// impl SecureSpecCombinator for SpecDynamicBytesTag {
374//     open spec fn spec_is_prefix_secure() -> bool {
375//         Bytes::spec_is_prefix_secure()
376//     }
377//
378//     proof fn theorem_serialize_parse_roundtrip(&self, v: ()) {
379//         self.0.theorem_serialize_parse_roundtrip(self.1);
380//     }
381//
382//     proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
383//         self.0.theorem_parse_serialize_roundtrip(buf);
384//     }
385//
386//     proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
387//         self.0.lemma_prefix_secure(s1, s2);
388//     }
389// }
390//
391// impl<'a> Combinator for DynamicBytesTag<'a> {
392//     type Result<'b> = ();
393//
394//     type Owned = ();
395//
396//     open spec fn spec_length(&self) -> Option<usize> {
397//         Some(self.0.0)
398//     }
399//
400//     fn length(&self) -> Option<usize> {
401//         Some(self.0.0)
402//     }
403//
404//     fn exec_is_prefix_secure() -> bool {
405//         Bytes::exec_is_prefix_secure()
406//     }
407//
408//     fn parse(&self, s: &[u8]) -> (res: Result<(usize, Self::Result), ()>) {
409//         match self.0.parse(s) {
410//             Ok((n, v)) if compare_slice(v, self.1) => Ok((n, ())),
411//             _ => Err(()),
412//         }
413//     }
414//
415//     fn serialize(&self, v: Self::Result, data: &mut Vec<u8>, pos: usize) -> (res: Result<
416//         usize,
417//         (),
418//     >) {
419//         self.0.serialize(self.1, data, pos)
420//     }
421// }
422//
423// #[cfg(test)]
424// mod test {
425//     use super::*;
426//
427//     const MAGIC: u8 = 0x42;
428//
429//     spec const SPEC_BYTES_123: Seq<u8> = seq![1, 2, 3];
430//
431//     exec static BYTES_123: [u8; 3]
432//         ensures
433//             BYTES_123@ == SPEC_BYTES_123,
434//     {
435//         let a: [u8; 3] = [1, 2, 3];
436//         assert(a@ == SPEC_BYTES_123);
437//         a
438//     }
439//
440//     spec fn spec_tag(input: Seq<u8>) -> (U8Tag, SpecStaticBytesTag<3>) {
441//         let t1: U8Tag = Tag(U8, MAGIC);
442//         let t2: SpecStaticBytesTag<3> = Tag(BytesN::<3>, SPEC_BYTES_123);
443//         (t1, t2)
444//     }
445//
446//     fn tag(input: &[u8]) -> (res: (U8Tag, StaticBytesTag<3>))
447//         ensures
448//             res@ == spec_tag(input@),
449//     {
450//         let tem_magic: u8 = 0x42;
451//         let t1: U8Tag = Tag(U8, tem_magic);  // ok
452//         let t1: U8Tag = Tag(U8, MAGIC);  // ok
453//         let t2: StaticBytesTag<3> = Tag(BytesN::<3>, &BYTES_123);
454//         (t1, t2)
455//     }
456//
457//     fn tag2<'a>(input: &'a [u8]) {
458//         // let tmp_bytes_123: [u8; 3] = [1, 2, 3];
459//         // let t1 = Tag(BytesN::<3>, &tmp_bytes_123); // err: TMP_BYTES_123 does not live long enough
460//         // it's required that `tmp_bytes_123` is borrowed for `'static`
461//         // let t1 = Tag(Bytes(3), &TMP_BYTES_123); // same err
462//         let t1 = Tag(Bytes(3), &BYTES_123);  // ok
463//         let _ = t1.parse(input);
464//     }
465//
466//     fn tag3<'a, 'b>(input: &'a [u8], tmp_bytes_123: &'b [u8; 3]) where 'b: 'a {
467//         // let t1 = Tag(BytesN::<3>, tmp_bytes_123); // err: TMP_BYTES_123 does not live long enough
468//         // let t1 = Tag(Bytes(3), tmp_bytes_123); // same err
469//         let t1 = Tag(Bytes(3), &BYTES_123);  // ok
470//         let _ = t1.parse(input);
471//     }
472//
473// }
474} // verus!