1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use std; use std::os::raw::c_void; use std::collections::HashSet; use borrow::LoanError; pub unsafe trait Pointer { unsafe fn as_ptr(&self) -> *const c_void; unsafe fn as_mut(&mut self) -> *mut c_void; } unsafe impl<T> Pointer for *mut T { unsafe fn as_ptr(&self) -> *const c_void { *self as *const c_void } unsafe fn as_mut(&mut self) -> *mut c_void { *self as *mut c_void } } unsafe impl<'a, T> Pointer for &'a mut T { unsafe fn as_ptr(&self) -> *const c_void { let r: &T = &**self; std::mem::transmute(r) } unsafe fn as_mut(&mut self) -> *mut c_void { let r: &mut T = &mut **self; std::mem::transmute(r) } } pub struct Ledger { immutable_loans: HashSet<*const c_void>, mutable_loans: HashSet<*const c_void> } impl Ledger { pub fn new() -> Self { Ledger { immutable_loans: HashSet::new(), mutable_loans: HashSet::new() } } pub fn try_borrow<T>(&mut self, p: *const T) -> Result<(), LoanError> { let p = p as *const c_void; if self.mutable_loans.contains(&p) { return Err(LoanError::Mutating(p)); } self.immutable_loans.insert(p); Ok(()) } pub fn settle<T>(&mut self, p: *const T) { let p = p as *const c_void; self.immutable_loans.remove(&p); } pub fn try_borrow_mut<T>(&mut self, p: *mut T) -> Result<(), LoanError> { let p = p as *const c_void; if self.mutable_loans.contains(&p) { return Err(LoanError::Mutating(p)); } else if self.immutable_loans.contains(&p) { return Err(LoanError::Frozen(p)); } self.mutable_loans.insert(p); Ok(()) } pub fn settle_mut<T>(&mut self, p: *mut T) { let p = p as *const c_void; self.mutable_loans.remove(&p); } }