1 use std::fmt; 2 3 use crate::borrow_tracker::BorTag; 4 5 /// An item in the per-location borrow stack. 6 #[derive(Copy, Clone, Hash, PartialEq, Eq)] 7 pub struct Item(u64); 8 9 // An Item contains 3 bitfields: 10 // * Bits 0-61 store a BorTag 11 // * Bits 61-63 store a Permission 12 // * Bit 64 stores a flag which indicates if we have a protector 13 const TAG_MASK: u64 = u64::MAX >> 3; 14 const PERM_MASK: u64 = 0x3 << 61; 15 const PROTECTED_MASK: u64 = 0x1 << 63; 16 17 const PERM_SHIFT: u64 = 61; 18 const PROTECTED_SHIFT: u64 = 63; 19 20 impl Item { new(tag: BorTag, perm: Permission, protected: bool) -> Self21 pub fn new(tag: BorTag, perm: Permission, protected: bool) -> Self { 22 assert!(tag.get() <= TAG_MASK); 23 let packed_tag = tag.get(); 24 let packed_perm = perm.to_bits() << PERM_SHIFT; 25 let packed_protected = u64::from(protected) << PROTECTED_SHIFT; 26 27 let new = Self(packed_tag | packed_perm | packed_protected); 28 29 debug_assert!(new.tag() == tag); 30 debug_assert!(new.perm() == perm); 31 debug_assert!(new.protected() == protected); 32 33 new 34 } 35 36 /// The pointers the permission is granted to. tag(self) -> BorTag37 pub fn tag(self) -> BorTag { 38 BorTag::new(self.0 & TAG_MASK).unwrap() 39 } 40 41 /// The permission this item grants. perm(self) -> Permission42 pub fn perm(self) -> Permission { 43 Permission::from_bits((self.0 & PERM_MASK) >> PERM_SHIFT) 44 } 45 46 /// Whether or not there is a protector for this tag protected(self) -> bool47 pub fn protected(self) -> bool { 48 self.0 & PROTECTED_MASK > 0 49 } 50 51 /// Set the Permission stored in this Item set_permission(&mut self, perm: Permission)52 pub fn set_permission(&mut self, perm: Permission) { 53 // Clear the current set permission 54 self.0 &= !PERM_MASK; 55 // Write Permission::Disabled to the Permission bits 56 self.0 |= perm.to_bits() << PERM_SHIFT; 57 } 58 } 59 60 impl fmt::Debug for Item { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 62 write!(f, "[{:?} for {:?}]", self.perm(), self.tag()) 63 } 64 } 65 66 /// Indicates which permission is granted (by this item to some pointers) 67 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] 68 pub enum Permission { 69 /// Grants unique mutable access. 70 Unique, 71 /// Grants shared mutable access. 72 SharedReadWrite, 73 /// Grants shared read-only access. 74 SharedReadOnly, 75 /// Grants no access, but separates two groups of SharedReadWrite so they are not 76 /// all considered mutually compatible. 77 Disabled, 78 } 79 80 impl Permission { 81 const UNIQUE: u64 = 0; 82 const SHARED_READ_WRITE: u64 = 1; 83 const SHARED_READ_ONLY: u64 = 2; 84 const DISABLED: u64 = 3; 85 to_bits(self) -> u6486 fn to_bits(self) -> u64 { 87 match self { 88 Permission::Unique => Self::UNIQUE, 89 Permission::SharedReadWrite => Self::SHARED_READ_WRITE, 90 Permission::SharedReadOnly => Self::SHARED_READ_ONLY, 91 Permission::Disabled => Self::DISABLED, 92 } 93 } 94 from_bits(perm: u64) -> Self95 fn from_bits(perm: u64) -> Self { 96 match perm { 97 Self::UNIQUE => Permission::Unique, 98 Self::SHARED_READ_WRITE => Permission::SharedReadWrite, 99 Self::SHARED_READ_ONLY => Permission::SharedReadOnly, 100 Self::DISABLED => Permission::Disabled, 101 _ => unreachable!(), 102 } 103 } 104 } 105