1use super::super::modes::*;
2use super::super::pcm::*;
3use super::super::prelude::*;
4use super::super::storage_protocol::*;
5use super::*;
6
7verus! {
8
9broadcast use {super::super::map::group_map_axioms, super::super::set::group_set_axioms};
10enum FractionalCarrier<T, const TOTAL: u64> {
13 Value { v: T, n: int },
14 Empty,
15 Invalid,
16}
17
18impl<T, const TOTAL: u64> FractionalCarrier<T, TOTAL> {
19 spec fn new(v: T) -> Self {
20 FractionalCarrier::Value { v: v, n: TOTAL as int }
21 }
22}
23
24impl<T, const TOTAL: u64> PCM for FractionalCarrier<T, TOTAL> {
25 closed spec fn valid(self) -> bool {
26 match self {
27 FractionalCarrier::Invalid => false,
28 FractionalCarrier::Empty => true,
29 FractionalCarrier::Value { v: v, n: n } => 0 < n <= TOTAL,
30 }
31 }
32
33 closed spec fn op(self, other: Self) -> Self {
34 match self {
35 FractionalCarrier::Invalid => FractionalCarrier::Invalid,
36 FractionalCarrier::Empty => other,
37 FractionalCarrier::Value { v: sv, n: sn } => match other {
38 FractionalCarrier::Invalid => FractionalCarrier::Invalid,
39 FractionalCarrier::Empty => self,
40 FractionalCarrier::Value { v: ov, n: on } => {
41 if sv != ov {
42 FractionalCarrier::Invalid
43 } else if sn <= 0 || on <= 0 {
44 FractionalCarrier::Invalid
45 } else {
46 FractionalCarrier::Value { v: sv, n: sn + on }
47 }
48 },
49 },
50 }
51 }
52
53 closed spec fn unit() -> Self {
54 FractionalCarrier::Empty
55 }
56
57 proof fn closed_under_incl(a: Self, b: Self) {
58 }
59
60 proof fn commutative(a: Self, b: Self) {
61 }
62
63 proof fn associative(a: Self, b: Self, c: Self) {
64 }
65
66 proof fn op_unit(a: Self) {
67 }
68
69 proof fn unit_valid() {
70 }
71}
72
73pub struct FracGhost<T, const TOTAL: u64 = 2> {
124 r: Resource<FractionalCarrier<T, TOTAL>>,
125}
126
127impl<T, const TOTAL: u64> FracGhost<T, TOTAL> {
128 #[verifier::type_invariant]
129 spec fn inv(self) -> bool {
130 self.r.value() is Value
131 }
132
133 pub closed spec fn id(self) -> Loc {
134 self.r.loc()
135 }
136
137 pub closed spec fn view(self) -> T {
138 self.r.value()->v
139 }
140
141 pub closed spec fn frac(self) -> int {
144 self.r.value()->n
145 }
146
147 pub open spec fn valid(self, id: Loc, frac: int) -> bool {
148 &&& self.id() == id
149 &&& self.frac() == frac
150 }
151
152 pub proof fn new(v: T) -> (tracked result: Self)
155 requires
156 TOTAL > 0,
157 ensures
158 result.frac() == TOTAL as int,
159 result@ == v,
160 {
161 let f = FractionalCarrier::<T, TOTAL>::new(v);
162 let tracked r = Resource::alloc(f);
163 Self { r }
164 }
165
166 pub proof fn agree(tracked self: &Self, tracked other: &Self)
168 requires
169 self.id() == other.id(),
170 ensures
171 self@ == other@,
172 {
173 use_type_invariant(self);
174 use_type_invariant(other);
175 let tracked joined = self.r.join_shared(&other.r);
176 joined.validate()
177 }
178
179 pub proof fn take(tracked &mut self) -> (tracked result: Self)
181 ensures
182 result == *old(self),
183 {
184 self.bounded();
185 let tracked mut mself = Self::dummy();
186 tracked_swap(self, &mut mself);
187 mself
188 }
189
190 pub proof fn split(tracked &mut self, n: int) -> (tracked result: Self)
194 requires
195 0 < n < old(self).frac(),
196 ensures
197 result.id() == self.id() == old(self).id(),
198 self@ == old(self)@,
199 result@ == old(self)@,
200 self.frac() + result.frac() == old(self).frac(),
201 result.frac() == n,
202 {
203 self.bounded();
204 let tracked mut mself = Self::dummy();
205 tracked_swap(self, &mut mself);
206 use_type_invariant(&mself);
207 let tracked (r1, r2) = mself.r.split(
208 FractionalCarrier::Value { v: mself.r.value()->v, n: mself.r.value()->n - n },
209 FractionalCarrier::Value { v: mself.r.value()->v, n: n },
210 );
211 self.r = r1;
212 Self { r: r2 }
213 }
214
215 pub proof fn combine(tracked &mut self, tracked other: Self)
217 requires
218 old(self).id() == other.id(),
219 ensures
220 self.id() == old(self).id(),
221 self@ == old(self)@,
222 self@ == other@,
223 self.frac() == old(self).frac() + other.frac(),
224 {
225 self.bounded();
226 let tracked mut mself = Self::dummy();
227 tracked_swap(self, &mut mself);
228 use_type_invariant(&mself);
229 use_type_invariant(&other);
230 let tracked mut r = mself.r;
231 r.validate_2(&other.r);
232 *self = Self { r: r.join(other.r) };
233 }
234
235 pub proof fn update(tracked &mut self, v: T)
238 requires
239 old(self).frac() == TOTAL,
240 ensures
241 self.id() == old(self).id(),
242 self@ == v,
243 self.frac() == old(self).frac(),
244 {
245 self.bounded();
246 let tracked mut mself = Self::dummy();
247 tracked_swap(self, &mut mself);
248 use_type_invariant(&mself);
249 let tracked mut r = mself.r;
250 let f = FractionalCarrier::<T, TOTAL>::Value { v: v, n: TOTAL as int };
251 *self = Self { r: r.update(f) };
252 }
253
254 pub proof fn update_with(tracked &mut self, tracked other: &mut Self, v: T)
257 requires
258 old(self).id() == old(other).id(),
259 old(self).frac() + old(other).frac() == TOTAL,
260 ensures
261 self.id() == old(self).id(),
262 other.id() == old(other).id(),
263 self.frac() == old(self).frac(),
264 other.frac() == old(other).frac(),
265 old(self)@ == old(other)@,
266 self@ == v,
267 other@ == v,
268 {
269 let ghost other_frac = other.frac();
270 other.bounded();
271
272 let tracked mut xother = Self::dummy();
273 tracked_swap(other, &mut xother);
274 self.bounded();
275 self.combine(xother);
276 self.update(v);
277
278 let tracked mut xother = self.split(other_frac);
279 tracked_swap(other, &mut xother);
280 }
281
282 pub proof fn bounded(tracked &self)
284 ensures
285 0 < self.frac() <= TOTAL,
286 {
287 use_type_invariant(self);
288 self.r.validate()
289 }
290
291 pub proof fn dummy() -> (tracked result: Self)
294 requires
295 TOTAL > 0,
296 {
297 Self::new(arbitrary())
298 }
299}
300
301pub struct GhostVar<T> {
303 frac: FracGhost<T>,
304}
305
306impl<T> GhostVar<T> {
307 #[verifier::type_invariant]
308 spec fn inv(self) -> bool {
309 self.frac.frac() == 1
310 }
311
312 pub closed spec fn id(self) -> int {
313 self.frac.id()
314 }
315
316 pub closed spec fn view(self) -> T {
317 self.frac.view()
318 }
319}
320
321pub struct GhostVarAuth<T> {
350 frac: FracGhost<T>,
351}
352
353impl<T> GhostVarAuth<T> {
354 #[verifier::type_invariant]
355 spec fn inv(self) -> bool {
356 self.frac.frac() == 1
357 }
358
359 pub closed spec fn id(self) -> int {
360 self.frac.id()
361 }
362
363 pub closed spec fn view(self) -> T {
364 self.frac.view()
365 }
366
367 pub proof fn new(v: T) -> (tracked result: (GhostVarAuth<T>, GhostVar<T>))
369 ensures
370 result.0.id() == result.1.id(),
371 result.0@ == v,
372 result.1@ == v,
373 {
374 let tracked mut f = FracGhost::<T>::new(v);
375 let tracked v = GhostVar::<T> { frac: f.split(1) };
376 let tracked a = GhostVarAuth::<T> { frac: f };
377 (a, v)
378 }
379
380 pub proof fn agree(tracked &self, tracked v: &GhostVar<T>)
382 requires
383 self.id() == v.id(),
384 ensures
385 self@ == v@,
386 {
387 self.frac.agree(&v.frac)
388 }
389
390 pub proof fn update(tracked &mut self, tracked v: &mut GhostVar<T>, new_val: T)
392 requires
393 old(self).id() == old(v).id(),
394 ensures
395 self.id() == old(self).id(),
396 v.id() == old(v).id(),
397 old(self)@ == old(v)@,
398 self@ == new_val,
399 v@ == new_val,
400 {
401 let tracked (mut ms, mut mv) = Self::new(new_val);
402 tracked_swap(self, &mut ms);
403 tracked_swap(v, &mut mv);
404 use_type_invariant(&ms);
405 use_type_invariant(&mv);
406 let tracked mut msfrac = ms.frac;
407 msfrac.combine(mv.frac);
408 msfrac.update(new_val);
409 let tracked mut nv = GhostVar::<T> { frac: msfrac.split(1) };
410 let tracked mut ns = Self { frac: msfrac };
411 tracked_swap(self, &mut ns);
412 tracked_swap(v, &mut nv);
413 }
414}
415
416enum FractionalCarrierOpt<T, const TOTAL: u64> {
418 Value { v: Option<T>, n: int },
419 Empty,
420 Invalid,
421}
422
423impl<T, const TOTAL: u64> Protocol<(), T> for FractionalCarrierOpt<T, TOTAL> {
424 closed spec fn op(self, other: Self) -> Self {
425 match self {
426 FractionalCarrierOpt::Invalid => FractionalCarrierOpt::Invalid,
427 FractionalCarrierOpt::Empty => other,
428 FractionalCarrierOpt::Value { v: sv, n: sn } => match other {
429 FractionalCarrierOpt::Invalid => FractionalCarrierOpt::Invalid,
430 FractionalCarrierOpt::Empty => self,
431 FractionalCarrierOpt::Value { v: ov, n: on } => {
432 if sv != ov {
433 FractionalCarrierOpt::Invalid
434 } else if sn <= 0 || on <= 0 {
435 FractionalCarrierOpt::Invalid
436 } else {
437 FractionalCarrierOpt::Value { v: sv, n: sn + on }
438 }
439 },
440 },
441 }
442 }
443
444 closed spec fn rel(self, s: Map<(), T>) -> bool {
445 match self {
446 FractionalCarrierOpt::Value { v, n } => {
447 (match v {
448 Some(v0) => s.dom().contains(()) && s[()] == v0,
449 None => s =~= map![],
450 }) && n == TOTAL && n != 0
451 },
452 FractionalCarrierOpt::Empty => false,
453 FractionalCarrierOpt::Invalid => false,
454 }
455 }
456
457 closed spec fn unit() -> Self {
458 FractionalCarrierOpt::Empty
459 }
460
461 proof fn commutative(a: Self, b: Self) {
462 }
463
464 proof fn associative(a: Self, b: Self, c: Self) {
465 }
466
467 proof fn op_unit(a: Self) {
468 }
469}
470
471pub struct Frac<T, const TOTAL: u64 = 2> {
475 r: StorageResource<(), T, FractionalCarrierOpt<T, TOTAL>>,
476}
477
478pub struct Empty<T, const TOTAL: u64 = 2> {
481 r: StorageResource<(), T, FractionalCarrierOpt<T, TOTAL>>,
482}
483
484impl<T, const TOTAL: u64> Frac<T, TOTAL> {
485 #[verifier::type_invariant]
486 spec fn inv(self) -> bool {
487 self.r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. }
488 }
489
490 pub closed spec fn id(self) -> Loc {
491 self.r.loc()
492 }
493
494 pub closed spec fn resource(self) -> T {
495 self.r.value()->v.unwrap()
496 }
497
498 pub closed spec fn frac(self) -> int {
499 self.r.value()->n
500 }
501
502 pub open spec fn valid(self, id: Loc, frac: int) -> bool {
503 &&& self.id() == id
504 &&& self.frac() == frac
505 }
506
507 pub proof fn new(tracked v: T) -> (tracked result: Self)
509 requires
510 TOTAL > 0,
511 ensures
512 result.frac() == TOTAL as int,
513 result.resource() == v,
514 {
515 let f = FractionalCarrierOpt::<T, TOTAL>::Value { v: Some(v), n: TOTAL as int };
516 let tracked mut m = Map::<(), T>::tracked_empty();
517 m.tracked_insert((), v);
518 let tracked r = StorageResource::alloc(f, m);
519 Self { r }
520 }
521
522 pub proof fn agree(tracked self: &Self, tracked other: &Self)
524 requires
525 self.id() == other.id(),
526 ensures
527 self.resource() == other.resource(),
528 {
529 use_type_invariant(self);
530 use_type_invariant(other);
531 let tracked joined = self.r.join_shared(&other.r);
532 joined.validate();
533 }
534
535 pub proof fn split(tracked &mut self, n: int) -> (tracked result: Self)
539 requires
540 0 < n < old(self).frac(),
541 ensures
542 result.id() == self.id() == old(self).id(),
543 self.resource() == old(self).resource(),
544 result.resource() == old(self).resource(),
545 self.frac() + result.frac() == old(self).frac(),
546 result.frac() == n,
547 {
548 use_type_invariant(&*self);
549 Self::split_helper(&mut self.r, n)
550 }
551
552 proof fn split_helper(
553 tracked r: &mut StorageResource<(), T, FractionalCarrierOpt<T, TOTAL>>,
554 n: int,
555 ) -> (tracked result: Self)
556 requires
557 0 < n < old(r).value()->n,
558 old(r).value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
559 ensures
560 result.id() == r.loc() == old(r).loc(),
561 r.value()->v.unwrap() == old(r).value()->v.unwrap(),
562 result.resource() == old(r).value()->v.unwrap(),
563 r.value()->n + result.frac() == old(r).value()->n,
564 result.frac() == n,
565 r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
566 {
567 r.validate();
568 let tracked mut r1 = StorageResource::alloc(
569 FractionalCarrierOpt::Value { v: None, n: TOTAL as int },
570 Map::tracked_empty(),
571 );
572 tracked_swap(r, &mut r1);
573 let tracked (r1, r2) = r1.split(
574 FractionalCarrierOpt::Value { v: r1.value()->v, n: r1.value()->n - n },
575 FractionalCarrierOpt::Value { v: r1.value()->v, n: n },
576 );
577 *r = r1;
578 Self { r: r2 }
579 }
580
581 pub proof fn combine(tracked &mut self, tracked other: Self)
583 requires
584 old(self).id() == other.id(),
585 ensures
586 self.id() == old(self).id(),
587 self.resource() == old(self).resource(),
588 self.resource() == other.resource(),
589 self.frac() == old(self).frac() + other.frac(),
590 {
591 use_type_invariant(&*self);
592 Self::combine_helper(&mut self.r, other)
593 }
594
595 proof fn combine_helper(
596 tracked r: &mut StorageResource<(), T, FractionalCarrierOpt<T, TOTAL>>,
597 tracked other: Self,
598 )
599 requires
600 old(r).loc() == other.id(),
601 old(r).value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
602 ensures
603 r.loc() == old(r).loc(),
604 r.value()->v.unwrap() == old(r).value()->v.unwrap(),
605 r.value()->v.unwrap() == other.resource(),
606 r.value()->n == old(r).value()->n + other.frac(),
607 r.value() matches FractionalCarrierOpt::Value { v: Some(_), .. },
608 {
609 r.validate();
610 use_type_invariant(&other);
611 let tracked mut r1 = StorageResource::alloc(
612 FractionalCarrierOpt::Value { v: None, n: TOTAL as int },
613 Map::tracked_empty(),
614 );
615 tracked_swap(r, &mut r1);
616 r1.validate_with_shared(&other.r);
617 *r = StorageResource::join(r1, other.r);
618 }
619
620 pub proof fn bounded(tracked &self)
622 ensures
623 0 < self.frac() <= TOTAL,
624 {
625 use_type_invariant(self);
626 let (x, _) = self.r.validate();
627 }
628
629 pub proof fn borrow(tracked &self) -> (tracked ret: &T)
631 ensures
632 ret == self.resource(),
633 {
634 use_type_invariant(self);
635 StorageResource::guard(&self.r, map![() => self.resource()]).tracked_borrow(())
636 }
637
638 pub proof fn take_resource(tracked self) -> (tracked pair: (T, Empty<T, TOTAL>))
640 requires
641 self.frac() == TOTAL,
642 ensures
643 pair.0 == self.resource(),
644 pair.1.id() == self.id(),
645 {
646 use_type_invariant(&self);
647 self.r.validate();
648
649 let p1 = self.r.value();
650 let p2 = FractionalCarrierOpt::Value { v: None, n: TOTAL as int };
651 let b2 = map![() => self.resource()];
652 assert forall|q: FractionalCarrierOpt<T, TOTAL>, t1: Map<(), T>|
653 #![all_triggers]
654 FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p1, q), t1) implies exists|
655 t2: Map<(), T>,
656 |
657 #![all_triggers]
658 FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2) && t2.dom().disjoint(
659 b2.dom(),
660 ) && t1 =~= t2.union_prefer_right(b2) by {
661 let t2 = map![];
662 assert(FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2));
663 assert(t2.dom().disjoint(b2.dom()));
664 assert(t1 =~= t2.union_prefer_right(b2));
665 }
666
667 let tracked Self { r } = self;
668 let tracked (new_r, mut m) = r.withdraw(p2, b2);
669 let tracked emp = Empty { r: new_r };
670 let tracked resource = m.tracked_remove(());
671 (resource, emp)
672 }
673}
674
675impl<T, const TOTAL: u64> Empty<T, TOTAL> {
676 #[verifier::type_invariant]
677 spec fn inv(self) -> bool {
678 &&& self.r.value() matches FractionalCarrierOpt::Value { v: None, n }
679 &&& n == TOTAL
680 }
681
682 pub closed spec fn id(self) -> Loc {
683 self.r.loc()
684 }
685
686 pub proof fn new(tracked v: T) -> (tracked result: Self)
687 requires
688 TOTAL > 0,
689 {
690 let f = FractionalCarrierOpt::<T, TOTAL>::Value { v: None, n: TOTAL as int };
691 let tracked mut m = Map::<(), T>::tracked_empty();
692 let tracked r = StorageResource::alloc(f, m);
693 Self { r }
694 }
695
696 pub proof fn put_resource(tracked self, tracked resource: T) -> (tracked frac: Frac<T, TOTAL>)
698 ensures
699 frac.id() == self.id(),
700 frac.resource() == resource,
701 frac.frac() == TOTAL,
702 {
703 use_type_invariant(&self);
704 self.r.validate();
705
706 let p1 = self.r.value();
707 let b1 = map![() => resource];
708 let p2 = FractionalCarrierOpt::Value { v: Some(resource), n: TOTAL as int };
709
710 assert forall|q: FractionalCarrierOpt<T, TOTAL>, t1: Map<(), T>|
711 #![all_triggers]
712 FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p1, q), t1) implies exists|
713 t2: Map<(), T>,
714 |
715 #![all_triggers]
716 FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2) && t1.dom().disjoint(
717 b1.dom(),
718 ) && t1.union_prefer_right(b1) =~= t2 by {
719 let t2 = map![() => resource];
720 assert(FractionalCarrierOpt::rel(FractionalCarrierOpt::op(p2, q), t2)
721 && t1.dom().disjoint(b1.dom()) && t1.union_prefer_right(b1) =~= t2);
722 }
723
724 let tracked mut m = Map::tracked_empty();
725 m.tracked_insert((), resource);
726 let tracked Self { r } = self;
727 let tracked new_r = r.deposit(m, p2);
728 let tracked f = Frac { r: new_r };
729 f
730 }
731}
732
733}