1use vstd::prelude::*;
2
3verus! {
4
5#[verifier::ext_equal]
6pub struct BitMapping<T, U> {
7 pub src: T,
8 pub dst: U,
9}
10
11} verus! {
13
14pub trait MapForwardTrait<Dst>: Sized {
15 spec fn map_forward_spec(self, bm: &[BitMapping<Self, Dst>]) -> Dst;
16
17 #[verifier::when_used_as_spec(map_forward_spec)]
18 fn map_forward(self, bm: &[BitMapping<Self, Dst>]) -> Dst
19 returns
20 self.map_forward_spec(bm),
21 ;
22
23 broadcast proof fn lemma_equal_map_froward(
24 x: Self,
25 y: Self,
26 bm1: &[BitMapping<Self, Dst>],
27 bm2: &[BitMapping<Self, Dst>],
28 )
29 requires
30 x == y,
31 bm1 == bm2,
32 ensures
33 #[trigger] x.map_forward_spec(bm1) == #[trigger] y.map_forward_spec(bm2),
34 ;
35}
36
37} macro_rules! impl_map_forward {
39 ($src:ty, $dst:ty) => {
40 verus! {
41 impl MapForwardTrait<$dst> for $src {
42 open spec fn map_forward_spec(self, bm: &[BitMapping<Self, $dst>]) -> $dst {
43 bm@.fold_left(0 as $dst, |acc: $dst, m: BitMapping<Self, $dst>| {
44 if self & m.src == m.src {
45 acc | m.dst
46 } else {
47 acc
48 }
49 })
50 }
51
52 #[verifier::external_body]
53 fn map_forward(self, bm: &[BitMapping<Self, $dst>]) -> $dst
54 {
55 bm.iter().fold(0 as $dst, |acc, m| {
56 if self & m.src == m.src {
57 acc | m.dst
58 } else {
59 acc
60 }
61 })
62 }
63
64 proof fn lemma_equal_map_froward(x: Self, y: Self,
65 bm1: &[BitMapping<Self, $dst>], bm2: &[BitMapping<Self, $dst>])
66 { }
67 }
68 }
69 };
70}
71
72verus! {
73
74pub trait MapInvertForwardTrait<Dst>: Sized {
75 spec fn map_invert_forward_spec(self, bm: &[BitMapping<Self, Dst>]) -> Dst;
76
77 #[verifier::when_used_as_spec(map_invert_forward_spec)]
78 fn map_invert_forward(self, bm: &[BitMapping<Self, Dst>]) -> Dst
79 returns
80 self.map_invert_forward_spec(bm),
81 ;
82
83 broadcast proof fn lemma_equal_map_invert_froward(
84 x: Self,
85 y: Self,
86 bm1: &[BitMapping<Self, Dst>],
87 bm2: &[BitMapping<Self, Dst>],
88 )
89 requires
90 x == y,
91 bm1 == bm2,
92 ensures
93 #[trigger] x.map_invert_forward(bm1) == #[trigger] y.map_invert_forward(bm2),
94 ;
95}
96
97} macro_rules! impl_map_invert_forward {
99 ($src:ty, $dst:ty) => {
100 verus! {
101 impl MapInvertForwardTrait<$dst> for $src {
102 open spec fn map_invert_forward_spec(self, bm: &[BitMapping<Self, $dst>]) -> $dst {
103 let inv_src = !self;
104 bm@.fold_left(0 as $dst, |acc: $dst, m: BitMapping<Self, $dst>| {
105 if inv_src & m.src == 0 {
106 acc | m.dst
107 } else {
108 acc
109 }
110 })
111 }
112
113 #[verifier::external_body]
114 fn map_invert_forward(self, bm: &[BitMapping<Self, $dst>]) -> $dst
115 {
116 let inv_src = !self;
117 bm.iter().fold(0 as $dst, |acc, m| {
118 if inv_src & m.src == 0 {
119 acc | m.dst
120 } else {
121 acc
122 }
123 })
124 }
125
126 proof fn lemma_equal_map_invert_froward(x: Self, y: Self,
127 bm1: &[BitMapping<Self, $dst>], bm2: &[BitMapping<Self, $dst>])
128 { }
129 }
130 }
131 };
132}
133
134verus! {
135
136pub trait MapBackward<Src>: Sized {
137 spec fn map_backward_spec(self, bm: &[BitMapping<Src, Self>]) -> Src;
138
139 #[verifier::when_used_as_spec(map_backward_spec)]
140 fn map_backward(self, bm: &[BitMapping<Src, Self>]) -> Src
141 returns
142 self.map_backward_spec(bm),
143 ;
144
145 broadcast proof fn lemma_equal_map_backward(
146 x: Self,
147 y: Self,
148 bm1: &[BitMapping<Src, Self>],
149 bm2: &[BitMapping<Src, Self>],
150 )
151 requires
152 x == y,
153 bm1 == bm2,
154 ensures
155 #[trigger] x.map_backward(bm1) == #[trigger] y.map_backward(bm2),
156 ;
157}
158
159} macro_rules! impl_map_backward {
161 ($src:ty, $dst:ty) => {
162 verus! {
163 impl MapBackward<$src> for $dst {
164
165 open spec fn map_backward_spec(self, bm: &[BitMapping<$src, Self>]) -> $src {
166 bm@.fold_left(0 as $src, |acc: $src, m: BitMapping<$src, Self>| {
167 if self & m.dst == m.dst {
168 acc | m.src
169 } else {
170 acc
171 }
172 })
173 }
174
175 #[verifier::external_body]
176 fn map_backward(self, bm: &[BitMapping<$src, Self>]) -> $src
177 {
178 bm.iter().fold(0 as $src, |acc, m| {
179 if self & m.dst == m.dst {
180 acc | m.src
181 } else {
182 acc
183 }
184 })
185 }
186
187 proof fn lemma_equal_map_backward(x: Self, y: Self,
188 bm1: &[BitMapping<$src, Self>], bm2: &[BitMapping<$src, Self>])
189 { }
190 }
191 }
192 };
193}
194
195verus! {
196
197pub trait MapInvertBackward<Src>: Sized {
198 spec fn map_invert_backward_spec(self, bm: &[BitMapping<Src, Self>]) -> Src;
199
200 #[verifier::when_used_as_spec(map_invert_backward_spec)]
201 fn map_invert_backward(self, bm: &[BitMapping<Src, Self>]) -> Src
202 returns
203 self.map_invert_backward_spec(bm),
204 ;
205
206 broadcast proof fn lemma_equal_map_invert_backward(
207 x: Self,
208 y: Self,
209 bm1: &[BitMapping<Src, Self>],
210 bm2: &[BitMapping<Src, Self>],
211 )
212 requires
213 x == y,
214 bm1 == bm2,
215 ensures
216 #[trigger] x.map_invert_backward(bm1) == #[trigger] y.map_invert_backward(bm2),
217 ;
218}
219
220} macro_rules! impl_map_invert_backward {
222 ($src:ty, $dst:ty) => {
223 verus! {
224 impl MapInvertBackward<$src> for $dst {
225
226 open spec fn map_invert_backward_spec(self, bm: &[BitMapping<$src, Self>]) -> $src {
227 let inv_src = !self;
228 bm@.fold_left(0 as $src, |acc: $src, m: BitMapping<$src, Self>| {
229 if inv_src & m.dst == 0 {
230 acc | m.src
231 } else {
232 acc
233 }
234 })
235 }
236
237 #[verifier::external_body]
238 fn map_invert_backward(self, bm: &[BitMapping<$src, Self>]) -> $src
239 {
240 let inv_src = !self;
241 bm.iter().fold(0 as $src, |acc, m| {
242 if inv_src & m.dst == 0 {
243 acc | m.src
244 } else {
245 acc
246 }
247 })
248 }
249
250 proof fn lemma_equal_map_invert_backward(x: Self, y: Self,
251 bm1: &[BitMapping<$src, Self>], bm2: &[BitMapping<$src, Self>])
252 { }
253 }
254 }
255 };
256}
257
258macro_rules! impl_map_operations {
259 ($src:ty, $dst:ty) => {
260 impl_map_forward!($src, $dst);
261 impl_map_invert_forward!($src, $dst);
262 impl_map_backward!($src, $dst);
263 impl_map_invert_backward!($src, $dst);
264 };
265}
266
267impl_map_operations!(u8, u8);
268impl_map_operations!(u8, u16);
269impl_map_operations!(u8, u32);
270impl_map_operations!(u8, u64);
271impl_map_operations!(u8, usize);
272
273impl_map_operations!(u32, u32);
274impl_map_operations!(u32, u64);
275impl_map_operations!(u32, usize);
276
277impl_map_operations!(u64, u64);
278impl_map_operations!(u64, usize);
279
280verus! {
281
282
283} #[macro_export]
285macro_rules! bm {
286 ($src: expr, $dst: expr) => {
287 BitMapping {
288 src: $src,
289 dst: $dst,
290 }
291 };
292}
293
294pub use bm;
295
296#[macro_export]
297macro_rules! bms {
298 ($(($src:expr, $dst:expr)), * $(,)?) => {
299 [
300 $(BitMapping { src: $src, dst: $dst }, )*
301 ]
302 };
303}
304
305pub use bms;
306
307#[macro_export]
308macro_rules! bms_as {
309 ($src_ty:ty, $dst_ty:ty, [ $( ($src:expr, $dst:expr) ),* $(,)? ]) => {
310 [
311 $(BitMapping { src: $src as $src_ty, dst: $dst as $dst_ty }, )*
312 ]
313 };
314}
315
316pub use bms_as;
317
318#[macro_export]
319macro_rules! decl_bms_const {
320 ($name:ident, $spec_name:ident, $type1:ty, $type2:ty, $len:expr, [$($flags:expr),* $(,)?]) => {
321 verus! {
322 pub spec const $spec_name: [BitMapping<$type1, $type2>; $len] = bms![
323 $($flags),*
324 ];
325
326 #[verifier::when_used_as_spec($spec_name)]
327 pub exec const $name: [BitMapping<$type1, $type2>; $len] = bms![
328 $($flags),*
329 ];
330 }
331 };
332}
333
334pub use decl_bms_const;