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