1use vstd::prelude::*;
2
3use vstd::layout;
4use vstd::raw_ptr::MemContents;
5use vstd::set;
6use vstd::set_lib;
7use vstd::simple_pptr::{self, PPtr};
8
9use core::marker::PhantomData;
10
11verus! {
12
13pub trait Repr<R: Sized>: Sized {
14 spec fn wf(r: R) -> bool;
15
16 spec fn to_repr_spec(self) -> R;
17
18 #[verifier::when_used_as_spec(to_repr_spec)]
19 fn to_repr(self) -> (res: R)
20 ensures
21 res == self.to_repr_spec(),
22 ;
23
24 spec fn from_repr_spec(r: R) -> Self;
25
26 #[verifier::when_used_as_spec(from_repr_spec)]
27 fn from_repr(r: R) -> (res: Self)
28 requires
29 Self::wf(r),
30 ensures
31 res == Self::from_repr_spec(r),
32 ;
33
34 fn from_borrowed<'a>(r: &'a R) -> (res: &'a Self)
35 requires
36 Self::wf(*r),
37 ensures
38 *res == Self::from_repr_spec(*r),
39 ;
40
41 proof fn from_to_repr(self)
42 ensures
43 Self::from_repr(self.to_repr()) == self,
44 ;
45
46 proof fn to_from_repr(r: R)
47 requires
48 Self::wf(r),
49 ensures
50 Self::from_repr(r).to_repr() == r,
51 ;
52
53 proof fn to_repr_wf(self)
54 ensures
55 Self::wf(self.to_repr()),
56 ;
57}
58
59pub struct ReprPtr<R, T: Repr<R>> {
62 pub addr: usize,
63 pub ptr: PPtr<R>,
64 pub _T: PhantomData<T>,
65}
66
67impl<R, T: Repr<R>> Clone for ReprPtr<R, T> {
68 fn clone(&self) -> Self {
69 Self { addr: self.addr, ptr: self.ptr, _T: PhantomData }
70 }
71}
72
73impl<R, T: Repr<R>> Copy for ReprPtr<R, T> {
74
75}
76
77impl<R, T: Repr<R>> ReprPtr<R, T> {
78 pub open spec fn addr_spec(self) -> usize {
79 self.addr
80 }
81
82 #[verifier::when_used_as_spec(addr_spec)]
83 pub fn addr(self) -> (u: usize)
84 ensures
85 u == self.addr,
86 {
87 self.addr
88 }
89
90 pub exec fn take(self, Tracked(perm): Tracked<&mut PointsTo<R, T>>) -> (v: T)
91 requires
92 old(perm).pptr() == self,
93 old(perm).is_init(),
94 old(perm).wf(),
95 ensures
96 perm.pptr() == old(perm).pptr(),
97 perm.mem_contents() == MemContents::Uninit::<T>,
98 v == old(perm).value(),
99 {
100 proof {
101 T::from_to_repr(perm.value());
102 }
103 T::from_repr(self.ptr.take(Tracked(&mut perm.points_to)))
104 }
105
106 pub exec fn put(self, Tracked(perm): Tracked<&mut PointsTo<R, T>>, v: T)
107 requires
108 old(perm).pptr() == self,
109 old(perm).mem_contents() == MemContents::Uninit::<T>,
110 ensures
111 perm.pptr() == old(perm).pptr(),
112 perm.mem_contents() == MemContents::Init(v),
113 perm.wf(),
114 {
115 proof {
116 v.from_to_repr();
117 v.to_repr_wf();
118 }
119 self.ptr.put(Tracked(&mut perm.points_to), v.to_repr())
120 }
121
122 pub exec fn borrow<'a>(self, Tracked(perm): Tracked<&'a PointsTo<R, T>>) -> (v: &'a T)
123 requires
124 perm.pptr() == self,
125 perm.is_init(),
126 perm.wf(),
127 ensures
128 *v === perm.value(),
129 {
130 T::from_borrowed(self.ptr.borrow(Tracked(&perm.points_to)))
131 }
132}
133
134#[verifier::accept_recursive_types(T)]
135pub tracked struct PointsTo<R, T: Repr<R>> {
136 pub ghost addr: usize,
137 pub points_to: simple_pptr::PointsTo<R>,
138 pub _T: PhantomData<T>,
139}
140
141impl<R, T: Repr<R>> PointsTo<R, T> {
142 pub proof fn new(
143 addr: Ghost<usize>,
144 tracked points_to: simple_pptr::PointsTo<R>,
145 ) -> tracked Self {
146 Self { addr: addr@, points_to: points_to, _T: PhantomData }
147 }
148
149 pub open spec fn wf(self) -> bool {
150 &&& T::wf(self.points_to.value())
151 }
152
153 pub open spec fn addr(self) -> usize {
154 self.addr
155 }
156
157 pub open spec fn mem_contents(self) -> MemContents<T> {
158 match self.points_to.mem_contents() {
159 MemContents::<R>::Uninit => MemContents::<T>::Uninit,
160 MemContents::<R>::Init(r) => MemContents::<T>::Init(T::from_repr(r)),
161 }
162 }
163
164 pub open spec fn is_init(self) -> bool {
165 self.mem_contents().is_init()
166 }
167
168 pub open spec fn is_uninit(self) -> bool {
169 self.mem_contents().is_uninit()
170 }
171
172 pub open spec fn value(self) -> T
173 recommends
174 self.is_init(),
175 {
176 self.mem_contents().value()
177 }
178
179 pub open spec fn pptr(self) -> ReprPtr<R, T> {
180 ReprPtr { addr: self.addr, ptr: self.points_to.pptr(), _T: PhantomData }
181 }
182
183 pub broadcast proof fn pptr_implies_addr(&self)
184 ensures
185 self.addr() == #[trigger] self.pptr().addr(),
186 {
187 }
188}
189
190}