pub struct CursorMut<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> {
pub list: &'a mut LinkedList<M>,
pub current: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
}Expand description
A cursor that can mutate the linked list links.
The cursor points to either a frame or the “ghost” non-element. It points to the “ghost” non-element when the cursor surpasses the back of the list.
Fields§
§list: &'a mut LinkedList<M>§current: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>Implementations§
Source§impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M>
impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M>
Sourcepub exec fn move_next(&mut self)
pub exec fn move_next(&mut self)
Tracked(owner): Tracked<CursorOwner<M>>,requiresowner.inv(),old(self).wf(owner),ensuresfinal(self).model(owner.move_next_owner_spec())
== old(self).model(owner).move_next_spec(),owner.move_next_owner_spec().inv(),final(self).wf(owner.move_next_owner_spec()),Moves the cursor to the next frame towards the back.
If the cursor is pointing to the “ghost” non-element then this will
move it to the first element of the LinkedList. If it is pointing
to the last element of the LinkedList then this will move it to the
“ghost” non-element.
Sourcepub exec fn move_prev(&mut self)
pub exec fn move_prev(&mut self)
Tracked(owner): Tracked<CursorOwner<M>>,requiresowner.inv(),old(self).wf(owner),ensuresfinal(self).model(owner.move_prev_owner_spec())
== old(self).model(owner).move_prev_spec(),owner.move_prev_owner_spec().inv(),final(self).wf(owner.move_prev_owner_spec()),Moves the cursor to the previous frame towards the front.
If the cursor is pointing to the “ghost” non-element then this will
move it to the last element of the LinkedList. If it is pointing
to the first element of the LinkedList then this will move it to the
“ghost” non-element.
Sourcepub exec fn current_meta(&mut self) -> res : Option<&mut M>
pub exec fn current_meta(&mut self) -> res : Option<&mut M>
Tracked(owner): Tracked<&mut CursorOwner<M>>,requiresold(self).wf(*old(owner)),old(owner).inv(),ensuresfinal(self).wf(*final(owner)),final(owner).inv(),*final(owner) == *old(owner),*final(self) == *old(self),res.is_some() == (0 <= final(owner).index < final(owner).length()),Gets the mutable reference to the current frame’s metadata.
§Verified Properties
§Preconditions
The cursor must be well-formed with respect to the tracked CursorOwner.
§Postconditions
If the cursor is on an element, returns Some(&mut meta) borrowing the
current link’s metadata. The cursor state and owner are otherwise
unchanged.
§Safety
The &mut self guarantees exclusive access to the cursor; the tracked
CursorOwner guarantees the perm for the current link is live. Together
they justify the mutable borrow of link.meta. The body is
external_body because the map-indexed perm extraction needed to call
ReprPtr::borrow_mut runs into a Verus modelling gap — see
vstd_extra::map_extra::tracked_borrow_mut_points_to. The ownership
invariants in the requires/ensures are what we rely on.
Sourcepub exec fn take_current(
&mut self,
) -> res : Option<(UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>)>
pub exec fn take_current( &mut self, ) -> res : Option<(UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>)>
Tracked(regions): Tracked<&mut MetaRegionOwners>,
Tracked(owner): Tracked<&mut CursorOwner<M>>,requiresold(self).wf(*old(owner)),old(owner).inv(),old(regions).inv(),old(owner).length() > 0
==> old(regions)
.slot_owners
.contains_key(frame_to_index(old(self).current.unwrap().addr())),ensuresold(owner).length() == 0 ==> res.is_none(),old(self).current.is_some() ==> res.is_some(),res.is_some()
==> res.unwrap().0.model(res.unwrap().1@).meta
== old(owner).list_own.list[old(owner).index]@,res.is_some()
==> final(self).model(*final(owner)) == old(self).model(*old(owner)).remove(),res.is_some() ==> res.unwrap().1@.frame_link_inv(),res.is_some() ==> final(owner).inv(),res.is_some() ==> final(self).wf(*final(owner)),res.is_none() ==> (*final(owner) =~= *old(owner)),final(regions).inv(),res.is_some() ==> final(owner).index == old(owner).index,res.is_some()
==> final(owner).list_own.list == old(owner).list_own.list.remove(old(owner).index),res.is_some()
==> {
let paddr = old(self).current.unwrap().addr();
let idx = frame_to_index(meta_to_frame(paddr));
&&& final(regions).slot_owners[idx].raw_count
== old(regions).slot_owners[idx].raw_count - 1
&&& final(regions).slots =~= old(regions).slots
},res.is_some()
==> forall |idx: usize| {
idx != frame_to_index(meta_to_frame(old(self).current.unwrap().addr()))
==> final(regions).slot_owners[idx] == old(regions).slot_owners[idx]
},res.is_none() ==> (*final(regions) =~= *old(regions)),res.is_some() ==> res.unwrap().0.wf(res.unwrap().1@),res.is_some() ==> res.unwrap().1@.inv(),Takes the current pointing frame out of the linked list.
If successful, the frame is returned and the cursor is moved to the next frame. If the cursor is pointing to the back of the list then it is moved to the “ghost” non-element.
§Verified Properties
§Preconditions
The cursor must be well-formed, with the pointers to its links’ metadata slots matching the tracked permission objects. The list must be non-empty, so that the current frame is valid.
§Postconditions
The current frame is removed from the list, and the cursor is moved to the next frame. The list invariants are preserved.
§Safety
This function calls from_raw on the frame, but we guarantee that the frame is forgotten
if it is in the list. So, double-free will not occur. All loads and stores are through track
tracked permissions, so there are no illegal memory accesses. No data races are possible.
Sourcepub exec fn insert_before(&mut self, frame: UniqueFrame<Link<M>>)
pub exec fn insert_before(&mut self, frame: UniqueFrame<Link<M>>)
Tracked(regions): Tracked<&mut MetaRegionOwners>,
Tracked(owner): Tracked<&mut CursorOwner<M>>,
Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,requiresold(self).wf(*old(owner)),old(owner).inv(),old(owner).list_own.list_id != 0,old(frame_own).inv(),old(frame_own).global_inv(*old(regions)),frame.wf(*old(frame_own)),old(owner).length() < usize::MAX,old(regions).inv(),old(regions).slots.contains_key(old(frame_own).slot_index),old(regions)
.slot_owners[old(frame_own).slot_index]
.inner_perms
.in_list
.is_for(old(regions).slots[old(frame_own).slot_index].value().in_list),old(frame_own).meta_perm.addr() == frame.ptr.addr(),old(frame_own).frame_link_inv(),ensuresfinal(self).model(*final(owner))
== old(self).model(*old(owner)).insert(final(frame_own).meta_own@),final(self).wf(*final(owner)),final(owner).inv(),final(owner).list_own.list
== old(owner).list_own.list.insert(old(owner).index, final(frame_own).meta_own),final(owner).list_own.list_id == old(owner).list_own.list_id,final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,final(frame_own).meta_own.in_list == old(owner).list_own.list_id,Inserts a frame before the current frame.
If the cursor is pointing at the “ghost” non-element then the new
element is inserted at the back of the LinkedList.
§Verified Properties
§Preconditions
The cursor must be well-formed, with the pointers to its links’ metadata slots matching the tracked permission objects.
- The new frame must be active, so that it is valid to call
into_rawon it.
§Postconditions
- The new frame is inserted into the list, immediately before the current index.
- The list invariants are preserved.
§Safety
- This function calls
into_rawon the frame, so the caller must ensure that the frame is active and has not been forgotten already to avoid a memory leak. If the caller attempts to insert a forgotten frame, the invariant aroundinto_rawandfrom_rawwill be violated. But, it is the safe failure case in that it will not cause a double-free. (Note: we should be able to move this requirement into theUniqueFrameinvariants.)
Sourcepub exec fn as_list(&self) -> &LinkedList<M>
pub exec fn as_list(&self) -> &LinkedList<M>
Provides a reference to the linked list.
Trait Implementations§
Source§impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> ModelOf for CursorMut<'a, M>
impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> ModelOf for CursorMut<'a, M>
Source§impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for CursorMut<'a, M>
impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for CursorMut<'a, M>
Source§open spec fn wf(self, owner: Self::Owner) -> bool
open spec fn wf(self, owner: Self::Owner) -> bool
{
&&& 0 <= owner.index < owner.length()
==> self.current.is_some()
&& self.current.unwrap().addr() == owner.list_own.list[owner.index].paddr
&& owner.list_own.perms[owner.index].pptr().addr()
== self.current.unwrap().addr()
&& self.current.unwrap().ptr
== owner.list_own.perms[owner.index].points_to.pptr()
&&& owner.index == owner.list_own.list.len() ==> self.current.is_none()
&&& (*self.list).wf(owner.list_own)
}Source§type Owner = CursorOwner<M>
type Owner = CursorOwner<M>
Inv, indicating that it must
has a consistent state.