vest/regular/tag.rs
1use super::refined::{Pred, Refined, SpecPred};
2use super::uints::FromToBytes;
3use crate::properties::*;
4use vstd::prelude::*;
5
6verus! {
7
8/// tag predicate that matches the input with a given value
9pub struct TagPred<T>(pub T);
10
11impl<T: View> View for TagPred<T> {
12 type V = TagPred<T::V>;
13
14 open spec fn view(&self) -> Self::V {
15 TagPred(self.0@)
16 }
17}
18
19impl<T> SpecPred for TagPred<T> {
20 type Input = T;
21
22 open spec fn spec_apply(&self, i: &Self::Input) -> bool {
23 *i == self.0
24 }
25}
26
27impl<T: FromToBytes> Pred for TagPred<T> {
28 type Input<'a> = T;
29
30 type InputOwned = T;
31
32 fn apply(&self, i: &Self::Input<'_>) -> bool {
33 self.0.eq(i)
34 }
35}
36
37impl<const N: usize> Pred for TagPred<[u8; N]> {
38 type Input<'b> = &'b [u8];
39
40 type InputOwned = Vec<u8>;
41
42 fn apply(&self, i: &Self::Input<'_>) -> bool {
43 compare_slice(self.0.as_slice(), *i)
44 }
45}
46
47impl<'a> Pred for TagPred<&'a [u8]> {
48 type Input<'b> = &'b [u8];
49
50 type InputOwned = Vec<u8>;
51
52 fn apply(&self, i: &Self::Input<'_>) -> bool {
53 compare_slice(self.0, *i)
54 }
55}
56
57/// Generic tag combinator that matches the input with a given value and discards it
58/// e.g. `Tag(Int::<u8>, 0)` matches the byte `0`; `Tag(Bytes::<3>, &[1, 2, 3])` matches the
59/// bytes `[1, 2, 3]`
60pub struct Tag<Inner, T>(pub Refined<Inner, TagPred<T>>);
61
62impl<Inner, T> Tag<Inner, T> {
63 /// Creates a new `Tag` combinator.
64 pub fn new(inner: Inner, tag: T) -> (o: Self)
65 ensures
66 o == Tag(Refined { inner, predicate: TagPred(tag) }),
67 {
68 Tag(Refined { inner, predicate: TagPred(tag) })
69 }
70
71 /// Creates a new `Tag` combinator.
72 pub open spec fn spec_new(inner: Inner, tag: T) -> Self {
73 Tag(Refined { inner, predicate: TagPred(tag) })
74 }
75}
76
77impl<Inner: View, T: View> View for Tag<Inner, T> {
78 type V = Tag<Inner::V, T::V>;
79
80 open spec fn view(&self) -> Self::V {
81 Tag(self.0@)
82 }
83}
84
85impl<Inner: SpecCombinator<SpecResult = T>, T> SpecCombinator for Tag<Inner, T> {
86 type SpecResult = ();
87
88 open spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
89 if let Ok((n, _)) = self.0.spec_parse(s) {
90 Ok((n, ()))
91 } else {
92 Err(())
93 }
94 }
95
96 open spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
97 self.0.spec_serialize(self.0.predicate.0)
98 }
99
100 proof fn spec_parse_wf(&self, s: Seq<u8>) {
101 self.0.spec_parse_wf(s);
102 }
103}
104
105impl<Inner: SecureSpecCombinator<SpecResult = T>, T> SecureSpecCombinator for Tag<Inner, T> {
106 open spec fn is_prefix_secure() -> bool {
107 Inner::is_prefix_secure()
108 }
109
110 proof fn theorem_serialize_parse_roundtrip(&self, v: Self::SpecResult) {
111 self.0.theorem_serialize_parse_roundtrip(self.0.predicate.0);
112 }
113
114 proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
115 self.0.theorem_parse_serialize_roundtrip(buf);
116 }
117
118 proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
119 self.0.lemma_prefix_secure(s1, s2);
120 assert(Self::is_prefix_secure() ==> self.spec_parse(s1).is_ok() ==> self.spec_parse(
121 s1.add(s2),
122 ) == self.spec_parse(s1));
123 }
124}
125
126impl<Inner, T> Combinator for Tag<Inner, T> where
127 Inner: for <'a>Combinator<Result<'a> = T, Owned = T>,
128 Inner::V: SecureSpecCombinator<SpecResult = T::V>, T: FromToBytes
129 {
130 type Result<'a> = ();
131
132 type Owned = ();
133
134 open spec fn spec_length(&self) -> Option<usize> {
135 self.0.spec_length()
136 }
137
138 fn length(&self) -> Option<usize> {
139 self.0.length()
140 }
141
142 open spec fn parse_requires(&self) -> bool {
143 self.0.parse_requires()
144 }
145
146 fn parse<'a>(&self, s: &'a [u8]) -> Result<(usize, Self::Result<'a>), ParseError> {
147 let (n, _) = self.0.parse(s)?;
148 Ok((n, ()))
149 }
150
151 open spec fn serialize_requires(&self) -> bool {
152 self.0.serialize_requires()
153 }
154
155 fn serialize(&self, _v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> Result<
156 usize,
157 SerializeError,
158 > {
159 self.0.serialize(self.0.predicate.0, data, pos)
160 }
161}
162
163impl<Inner, const N: usize> Combinator for Tag<Inner, [u8; N]> where
164 Inner: for <'b>Combinator<Result<'b> = &'b [u8], Owned = Vec<u8>>,
165 Inner::V: SecureSpecCombinator<SpecResult = Seq<u8>>
166 {
167 type Result<'b> = ();
168
169 type Owned = ();
170
171 open spec fn spec_length(&self) -> Option<usize> {
172 self.0.spec_length()
173 }
174
175 fn length(&self) -> Option<usize> {
176 self.0.length()
177 }
178
179 open spec fn parse_requires(&self) -> bool {
180 self.0.parse_requires()
181 }
182
183 fn parse<'b>(&self, s: &'b [u8]) -> Result<(usize, Self::Result<'b>), ParseError> {
184 let (n, _) = self.0.parse(s)?;
185 Ok((n, ()))
186 }
187
188 open spec fn serialize_requires(&self) -> bool {
189 self.0.serialize_requires()
190 }
191
192 fn serialize(&self, _v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> Result<
193 usize,
194 SerializeError,
195 > {
196 self.0.serialize(self.0.predicate.0.as_slice(), data, pos)
197 }
198}
199
200impl<Inner, 'a> Combinator for Tag<Inner, &'a [u8]> where
201 Inner: for <'b>Combinator<Result<'b> = &'b [u8], Owned = Vec<u8>>,
202 Inner::V: SecureSpecCombinator<SpecResult = Seq<u8>>
203 {
204 type Result<'b> = ();
205
206 type Owned = ();
207
208 open spec fn spec_length(&self) -> Option<usize> {
209 self.0.spec_length()
210 }
211
212 fn length(&self) -> Option<usize> {
213 self.0.length()
214 }
215
216 open spec fn parse_requires(&self) -> bool {
217 self.0.parse_requires()
218 }
219
220 fn parse<'b>(&self, s: &'b [u8]) -> Result<(usize, Self::Result<'b>), ParseError> {
221 let (n, _) = self.0.parse(s)?;
222 Ok((n, ()))
223 }
224
225 open spec fn serialize_requires(&self) -> bool {
226 self.0.serialize_requires()
227 }
228
229 fn serialize(&self, _v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> Result<
230 usize,
231 SerializeError,
232 > {
233 self.0.serialize(self.0.predicate.0, data, pos)
234 }
235}
236
237#[cfg(test)]
238#[allow(unused)]
239mod test {
240 use crate::regular::choice::OrdChoice;
241 use super::*;
242 use super::super::uints::{U8};
243 use super::super::bytes::Bytes;
244 use super::super::bytes_n::BytesN;
245
246 proof fn test(s: Seq<u8>)
247 requires
248 s.len() <= usize::MAX,
249 {
250 let tag = Tag::spec_new(BytesN::<3>, seq![0u8, 0, 0]);
251 if let Ok((n, v)) = tag.spec_parse(s) {
252 if let Ok(buf) = tag.spec_serialize(v) {
253 tag.theorem_parse_serialize_roundtrip(s);
254 assert(buf == s.subrange(0, n as int));
255 }
256 }
257 }
258
259 fn test1(s: &[u8])
260 requires
261 s@.len() <= usize::MAX,
262 {
263 let bytes = [0u8, 0, 0];
264 let tag = Tag::new(BytesN::<3>, bytes.as_slice());
265 proof {
266 let spec_tag = Tag::spec_new(BytesN::<3>, bytes@);
267 assert(tag@ == spec_tag);
268 }
269 if let Ok((n, v)) = tag.parse(s) {
270 let mut buf = Vec::new();
271 buf.push(0);
272 if let Ok(m) = tag.serialize(v, &mut buf, 0) {
273 proof {
274 tag@.theorem_parse_serialize_roundtrip(s@);
275 }
276 assert(buf@ == s@.subrange(0, n as int));
277 }
278 }
279 }
280
281 proof fn test3(s: Seq<u8>)
282 requires
283 s.len() <= usize::MAX,
284 {
285 let tag1 = Tag::spec_new(U8, 0x42);
286 let tag2 = Tag::spec_new(U8, 0x43);
287 let ord = OrdChoice(tag1, tag2);
288 if let Ok((n, v)) = ord.spec_parse(s) {
289 if let Ok(buf) = ord.spec_serialize(v) {
290 ord.theorem_parse_serialize_roundtrip(s);
291 assert(buf == s.subrange(0, n as int));
292 }
293 }
294 let tag3 = Tag::spec_new(BytesN::<3>, seq![1u8, 0, 0]);
295 let tag4 = Tag::spec_new(BytesN::<3>, seq![2u8, 0, 0]);
296 let ord2 = OrdChoice(tag3, tag4);
297 if let Ok((n, v)) = ord2.spec_parse(s) {
298 if let Ok(buf) = ord2.spec_serialize(v) {
299 ord2.theorem_parse_serialize_roundtrip(s);
300 assert(buf == s.subrange(0, n as int));
301 }
302 }
303 }
304
305 fn test4(s: &[u8])
306 requires
307 s@.len() <= usize::MAX,
308 {
309 let tag1 = Tag::new(U8, 0x42);
310 let tag2 = Tag::new(U8, 0x43);
311 let ord = OrdChoice(tag1, tag2);
312 if let Ok((n, v)) = ord.parse(s) {
313 let mut buf = Vec::new();
314 buf.push(0);
315 if let Ok(m) = ord.serialize(v, &mut buf, 0) {
316 proof {
317 ord@.theorem_parse_serialize_roundtrip(s@);
318 }
319 assert(buf@ == s@.subrange(0, n as int));
320 }
321 }
322 let b1 = [0u8, 0, 0];
323 let b2 = [1u8, 0, 0];
324 let tag3 = Tag::new(Bytes(3), b1.as_slice());
325 let tag4 = Tag::new(Bytes(3), b2.as_slice());
326 let ord2 = OrdChoice(tag3, tag4);
327 if let Ok((n, v)) = ord2.parse(s) {
328 let mut buf = Vec::new();
329 buf.push(0);
330 buf.push(0);
331 buf.push(0);
332 if let Ok(m) = ord2.serialize(v, &mut buf, 0) {
333 proof {
334 ord2@.theorem_parse_serialize_roundtrip(s@);
335 }
336 assert(buf@ == s@.subrange(0, n as int));
337 }
338 }
339 }
340
341}
342
343// old code
344// /// generic tag combinator that matches the input with a given value and discards it
345// /// e.g. `Tag(Int::<u8>, 0)` matches the byte `0`; `Tag(Bytes::<3>, &[1, 2, 3])` matches the bytes `[1, 2, 3]`
346// pub struct Tag<Inner, T>(pub Inner, pub T);
347//
348// impl<Inner, T> View for Tag<Inner, T> where Inner: View, T: View {
349// type V = Tag<Inner::V, T::V>;
350//
351// open spec fn view(&self) -> Self::V {
352// Tag(self.0@, self.1@)
353// }
354// }
355//
356// impl<Inner, T> SpecCombinator for Tag<Inner, T> where Inner: SpecCombinator<SpecResult = T> {
357// type SpecResult = ();
358//
359// open spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
360// match self.0.spec_parse(s) {
361// Ok((n, v)) if v == self.1 => Ok((n, ())),
362// _ => Err(()),
363// }
364// }
365//
366// open spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
367// self.0.spec_serialize(self.1)
368// }
369//
370// proof fn spec_parse_wf(&self, s: Seq<u8>) {
371// self.0.spec_parse_wf(s);
372// }
373// }
374//
375// impl<Inner, T> SecureSpecCombinator for Tag<Inner, T> where
376// Inner: SecureSpecCombinator<SpecResult = T>,
377// {
378// open spec fn spec_is_prefix_secure() -> bool {
379// Inner::spec_is_prefix_secure()
380// }
381//
382// proof fn theorem_serialize_parse_roundtrip(&self, v: ()) {
383// self.0.theorem_serialize_parse_roundtrip(self.1);
384// }
385//
386// proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
387// self.0.theorem_parse_serialize_roundtrip(buf);
388// }
389//
390// proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
391// self.0.lemma_prefix_secure(s1, s2);
392// }
393// }
394//
395// // the line `for <'a, 'b>Inner::Result<'a>: Compare<Inner::Result<'b>> + From<T>`
396// // says that `Inner::Result<'a>` must impl `From<T> for all lifetimes `'a`
397// // at the type level, this means even a static `Inner::Result<'static>` can be converted from
398// // `T`, which in turn mandates that `T: 'static` (if both `T` and `Inner::Result<'a>` are
399// // types without actual lifetimes, e.g. `u8`, then it's fine)
400// //
401// // it would be nice if Rust supports "existential" lifetimes like:
402// // `exist <'a>Inner::Result<'a>: From<T>`
403// impl<Inner, T> Combinator for Tag<Inner, T> where
404// Inner: Combinator,
405// Inner::V: SecureSpecCombinator<SpecResult = T::V>,
406// T: View<V = <Inner::Owned as View>::V> + Copy,
407// for <'a, 'b>Inner::Result<'a>: Compare<Inner::Result<'b>> + From<T>,
408// {
409// type Result<'a> = ();
410//
411// type Owned = ();
412//
413// open spec fn spec_length(&self) -> Option<usize> {
414// self.0.spec_length()
415// }
416//
417// fn length(&self) -> Option<usize> {
418// self.0.length()
419// }
420//
421// fn exec_is_prefix_secure() -> bool {
422// Inner::exec_is_prefix_secure()
423// }
424//
425// open spec fn parse_requires(&self) -> bool {
426// self.0.parse_requires()
427// }
428//
429// fn parse(&self, s: &[u8]) -> (res: Result<(usize, ()), ()>) {
430// match self.0.parse(s) {
431// Ok((n, v)) if v.compare(&self.1.ex_into()) => Ok((n, ())),
432// _ => Err(()),
433// }
434// }
435//
436// open spec fn serialize_requires(&self) -> bool {
437// self.0.serialize_requires()
438// }
439//
440// fn serialize(&self, v: (), data: &mut Vec<u8>, pos: usize) -> (res: Result<usize, ()>) {
441// self.0.serialize(self.1.ex_into(), data, pos)
442// }
443// }
444//
445// pub type U8Tag = Tag<Int<u8>, u8>;
446//
447// pub type U16Tag = Tag<Int<u16>, u16>;
448//
449// pub type U32Tag = Tag<Int<u32>, u32>;
450//
451// pub type U64Tag = Tag<Int<u64>, u64>;
452//
453// pub type SpecStaticBytesTag<const N: usize> = Tag<BytesN<N>, Seq<u8>>;
454//
455// pub type StaticBytesTag<const N: usize> = Tag<BytesN<N>, &'static [u8; N]>;
456//
457// /// combinator for matching a dynamic byte slice
458// ///
459// /// **Note**: due to the current limitations of Rust borrow checker
460// /// the generic `Tag` combinator cannot be used with dynamic byte slices (`Tag<Bytes, &'a [u8]>`)
461// pub struct DynamicBytesTag<'a>(pub Bytes, pub &'a [u8]);
462//
463// pub struct SpecDynamicBytesTag(pub Bytes, pub Seq<u8>);
464//
465// impl<'a> View for DynamicBytesTag<'a> {
466// type V = SpecDynamicBytesTag;
467//
468// open spec fn view(&self) -> Self::V {
469// SpecDynamicBytesTag(self.0@, self.1@)
470// }
471// }
472//
473// impl SpecCombinator for SpecDynamicBytesTag {
474// type SpecResult = ();
475//
476// open spec fn spec_parse(&self, s: Seq<u8>) -> Result<(usize, Self::SpecResult), ()> {
477// match self.0.spec_parse(s) {
478// Ok((n, v)) if n == self.1.len() && v == self.1 => Ok((n, ())),
479// _ => Err(()),
480// }
481// }
482//
483// open spec fn spec_serialize(&self, v: Self::SpecResult) -> Result<Seq<u8>, ()> {
484// self.0.spec_serialize(self.1)
485// }
486//
487// proof fn spec_parse_wf(&self, s: Seq<u8>) {
488// }
489// }
490//
491// impl SecureSpecCombinator for SpecDynamicBytesTag {
492// open spec fn spec_is_prefix_secure() -> bool {
493// Bytes::spec_is_prefix_secure()
494// }
495//
496// proof fn theorem_serialize_parse_roundtrip(&self, v: ()) {
497// self.0.theorem_serialize_parse_roundtrip(self.1);
498// }
499//
500// proof fn theorem_parse_serialize_roundtrip(&self, buf: Seq<u8>) {
501// self.0.theorem_parse_serialize_roundtrip(buf);
502// }
503//
504// proof fn lemma_prefix_secure(&self, s1: Seq<u8>, s2: Seq<u8>) {
505// self.0.lemma_prefix_secure(s1, s2);
506// }
507// }
508//
509// impl<'a> Combinator for DynamicBytesTag<'a> {
510// type Result<'b> = ();
511//
512// type Owned = ();
513//
514// open spec fn spec_length(&self) -> Option<usize> {
515// Some(self.0.0)
516// }
517//
518// fn length(&self) -> Option<usize> {
519// Some(self.0.0)
520// }
521//
522// fn exec_is_prefix_secure() -> bool {
523// Bytes::exec_is_prefix_secure()
524// }
525//
526// fn parse(&self, s: &[u8]) -> (res: Result<(usize, Self::Result<'_>), ()>) {
527// match self.0.parse(s) {
528// Ok((n, v)) if compare_slice(v, self.1) => Ok((n, ())),
529// _ => Err(()),
530// }
531// }
532//
533// fn serialize(&self, v: Self::Result<'_>, data: &mut Vec<u8>, pos: usize) -> (res: Result<
534// usize,
535// (),
536// >) {
537// self.0.serialize(self.1, data, pos)
538// }
539// }
540//
541// #[cfg(test)]
542// mod test {
543// use super::*;
544//
545// const MAGIC: u8 = 0x42;
546//
547// spec const SPEC_BYTES_123: Seq<u8> = seq![1, 2, 3];
548//
549// exec static BYTES_123: [u8; 3]
550// ensures
551// BYTES_123@ == SPEC_BYTES_123,
552// {
553// let a: [u8; 3] = [1, 2, 3];
554// assert(a@ == SPEC_BYTES_123);
555// a
556// }
557//
558// spec fn spec_tag(input: Seq<u8>) -> (U8Tag, SpecStaticBytesTag<3>) {
559// let t1: U8Tag = Tag(U8, MAGIC);
560// let t2: SpecStaticBytesTag<3> = Tag(BytesN::<3>, SPEC_BYTES_123);
561// (t1, t2)
562// }
563//
564// fn tag(input: &[u8]) -> (res: (U8Tag, StaticBytesTag<3>))
565// ensures
566// res@ == spec_tag(input@),
567// {
568// let tem_magic: u8 = 0x42;
569// let t1: U8Tag = Tag(U8, tem_magic); // ok
570// let t1: U8Tag = Tag(U8, MAGIC); // ok
571// let t2: StaticBytesTag<3> = Tag(BytesN::<3>, &BYTES_123);
572// (t1, t2)
573// }
574//
575// fn tag2<'a>(input: &'a [u8]) {
576// // let tmp_bytes_123: [u8; 3] = [1, 2, 3];
577// // let t1 = Tag(BytesN::<3>, &tmp_bytes_123); // err: TMP_BYTES_123 does not live long enough
578// // it's required that `tmp_bytes_123` is borrowed for `'static`
579// // let t1 = Tag(Bytes(3), &TMP_BYTES_123); // same err
580// let t1 = Tag(Bytes(3), &BYTES_123); // ok
581// let _ = t1.parse(input);
582// }
583//
584// fn tag3<'a, 'b>(input: &'a [u8], tmp_bytes_123: &'b [u8; 3]) where 'b: 'a {
585// // let t1 = Tag(BytesN::<3>, tmp_bytes_123); // err: TMP_BYTES_123 does not live long enough
586// // let t1 = Tag(Bytes(3), tmp_bytes_123); // same err
587// let t1 = Tag(Bytes(3), &BYTES_123); // ok
588// let _ = t1.parse(input);
589// }
590//
591// }
592} // verus!