#![warn(missing_docs)] /*! # An owning reference. This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` that enables it to bundle a reference together with the owner of the data it points to. This allows moving and dropping of a `OwningRef` without needing to recreate the reference. This can sometimes be useful because Rust borrowing rules normally prevent moving a type that has been moved from. For example, this kind of code gets rejected: ```rust,ignore fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { let v = vec![1, 2, 3, 4]; let s = &v[1..3]; (v, s) } ``` Even though, from a memory-layout point of view, this can be entirely safe if the new location of the vector still lives longer than the lifetime `'a` of the reference because the backing allocation of the vector does not change. This library enables this safe usage by keeping the owner and the reference bundled together in a wrapper type that ensure that lifetime constraint: ```rust # extern crate owning_ref; # use owning_ref::OwningRef; # fn main() { fn return_owned_and_referenced() -> OwningRef, [u8]> { let v = vec![1, 2, 3, 4]; let or = OwningRef::new(v); let or = or.map(|v| &v[1..3]); or } # } ``` It works by requiring owner types to dereference to stable memory locations and preventing mutable access to root containers, which in practice requires heap allocation as provided by `Box`, `Rc`, etc. Also provided are typedefs for common owner type combinations, which allow for less verbose type signatures. For example, `BoxRef` instead of `OwningRef, T>`. The crate also provides the more advanced `OwningHandle` type, which allows more freedom in bundling a dependent handle object along with the data it depends on, at the cost of some unsafe needed in the API. See the documentation around `OwningHandle` for more details. # Examples ## Basics ``` extern crate owning_ref; use owning_ref::BoxRef; fn main() { // Create an array owned by a Box. let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; // Transfer into a BoxRef. let arr: BoxRef<[i32]> = BoxRef::new(arr); assert_eq!(&*arr, &[1, 2, 3, 4]); // We can slice the array without losing ownership or changing type. let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); assert_eq!(&*arr, &[2, 3]); // Also works for Arc, Rc, String and Vec! } ``` ## Caching a reference to a struct field ``` extern crate owning_ref; use owning_ref::BoxRef; fn main() { struct Foo { tag: u32, x: u16, y: u16, z: u16, } let foo = Foo { tag: 1, x: 100, y: 200, z: 300 }; let or = BoxRef::new(Box::new(foo)).map(|foo| { match foo.tag { 0 => &foo.x, 1 => &foo.y, 2 => &foo.z, _ => panic!(), } }); assert_eq!(*or, 200); } ``` ## Caching a reference to an entry in a vector ``` extern crate owning_ref; use owning_ref::VecRef; fn main() { let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]); assert_eq!(*v, 4); } ``` ## Caching a subslice of a String ``` extern crate owning_ref; use owning_ref::StringRef; fn main() { let s = StringRef::new("hello world".to_owned()) .map(|s| s.split(' ').nth(1).unwrap()); assert_eq!(&*s, "world"); } ``` ## Reference counted slices that share ownership of the backing storage ``` extern crate owning_ref; use owning_ref::RcRef; use std::rc::Rc; fn main() { let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>); assert_eq!(&*rc, &[1, 2, 3, 4]); let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]); let rc_b = rc.clone().map(|s| &s[1..3]); let rc_c = rc.clone().map(|s| &s[2..4]); assert_eq!(&*rc_a, &[1, 2]); assert_eq!(&*rc_b, &[2, 3]); assert_eq!(&*rc_c, &[3, 4]); let rc_c_a = rc_c.clone().map(|s| &s[1]); assert_eq!(&*rc_c_a, &4); } ``` ## Atomic reference counted slices that share ownership of the backing storage ``` extern crate owning_ref; use owning_ref::ArcRef; use std::sync::Arc; fn main() { use std::thread; fn par_sum(rc: ArcRef<[i32]>) -> i32 { if rc.len() == 0 { return 0; } else if rc.len() == 1 { return rc[0]; } let mid = rc.len() / 2; let left = rc.clone().map(|s| &s[..mid]); let right = rc.map(|s| &s[mid..]); let left = thread::spawn(move || par_sum(left)); let right = thread::spawn(move || par_sum(right)); left.join().unwrap() + right.join().unwrap() } let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]); let rc: ArcRef<[i32]> = rc.into(); assert_eq!(par_sum(rc), 10); } ``` ## References into RAII locks ``` extern crate owning_ref; use owning_ref::RefRef; use std::cell::{RefCell, Ref}; fn main() { let refcell = RefCell::new((1, 2, 3, 4)); // Also works with Mutex and RwLock let refref = { let refref = RefRef::new(refcell.borrow()).map(|x| &x.3); assert_eq!(*refref, 4); // We move the RAII lock and the reference to one of // the subfields in the data it guards here: refref }; assert_eq!(*refref, 4); drop(refref); assert_eq!(*refcell.borrow(), (1, 2, 3, 4)); } ``` ## Mutable reference When the owned container implements `DerefMut`, it is also possible to make a _mutable owning reference_. (E.g. with `Box`, `RefMut`, `MutexGuard`) ``` extern crate owning_ref; use owning_ref::RefMutRefMut; use std::cell::{RefCell, RefMut}; fn main() { let refcell = RefCell::new((1, 2, 3, 4)); let mut refmut_refmut = { let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3); assert_eq!(*refmut_refmut, 4); *refmut_refmut *= 2; refmut_refmut }; assert_eq!(*refmut_refmut, 8); *refmut_refmut *= 2; drop(refmut_refmut); assert_eq!(*refcell.borrow(), (1, 2, 3, 16)); } ``` */ extern crate stable_deref_trait; pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress}; /// An owning reference. /// /// This wraps an owner `O` and a reference `&T` pointing /// at something reachable from `O::Target` while keeping /// the ability to move `self` around. /// /// The owner is usually a pointer that points at some base type. /// /// For more details and examples, see the module and method docs. pub struct OwningRef { owner: O, reference: *const T, } /// An mutable owning reference. /// /// This wraps an owner `O` and a reference `&mut T` pointing /// at something reachable from `O::Target` while keeping /// the ability to move `self` around. /// /// The owner is usually a pointer that points at some base type. /// /// For more details and examples, see the module and method docs. pub struct OwningRefMut { owner: O, reference: *mut T, } /// Helper trait for an erased concrete type an owner dereferences to. /// This is used in form of a trait object for keeping /// something around to (virtually) call the destructor. pub trait Erased {} impl Erased for T {} /// Helper trait for erasing the concrete type of what an owner derferences to, /// for example `Box -> Box`. This would be unneeded with /// higher kinded types support in the language. pub unsafe trait IntoErased<'a> { /// Owner with the dereference type substituted to `Erased`. type Erased; /// Perform the type erasure. fn into_erased(self) -> Self::Erased; } ///////////////////////////////////////////////////////////////////////////// // OwningRef ///////////////////////////////////////////////////////////////////////////// impl OwningRef { /// Creates a new owning reference from a owner /// initialized to the direct dereference of it. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRef; /// /// fn main() { /// let owning_ref = OwningRef::new(Box::new(42)); /// assert_eq!(*owning_ref, 42); /// } /// ``` pub fn new(o: O) -> Self where O: StableAddress, O: Deref, { OwningRef { reference: &*o, owner: o, } } /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. /// Instead, the caller is responsible to make the same promises as implementing the trait. /// /// This is useful for cases where coherence rules prevents implementing the trait /// without adding a dependency to this crate in a third-party library. pub unsafe fn new_assert_stable_address(o: O) -> Self where O: Deref, { OwningRef { reference: &*o, owner: o, } } /// Converts `self` into a new owning reference that points at something reachable /// from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRef; /// /// fn main() { /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref = owning_ref.map(|array| &array[2]); /// assert_eq!(*owning_ref, 3); /// } /// ``` pub fn map(self, f: F) -> OwningRef where O: StableAddress, F: FnOnce(&T) -> &U { OwningRef { reference: f(&self), owner: self.owner, } } /// Converts `self` into a new owning reference that points at something reachable /// from the previous one or from the owner itself. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U` or from the owner `O`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRef; /// /// fn main() { /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); /// let owning_ref = owning_ref.map(|array| &array[2]); /// assert_eq!(*owning_ref, 3); /// /// // create a owning reference that points at the /// // second element of the array from the owning ref that was pointing to the third /// let owning_ref = owning_ref.map_with_owner(|array, _prev| &array[1]); /// assert_eq!(*owning_ref, 2); /// } /// ``` pub fn map_with_owner(self, f: F) -> OwningRef where O: StableAddress, F: for<'a> FnOnce(&'a O, &'a T) -> &'a U { OwningRef { reference: f(&self.owner, &self), owner: self.owner, } } /// Tries to convert `self` into a new owning reference that points /// at something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRef; /// /// fn main() { /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref = owning_ref.try_map(|array| { /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } /// }); /// assert_eq!(*owning_ref.unwrap(), 3); /// } /// ``` pub fn try_map(self, f: F) -> Result, E> where O: StableAddress, F: FnOnce(&T) -> Result<&U, E> { Ok(OwningRef { reference: f(&self)?, owner: self.owner, }) } /// Tries to convert `self` into a new owning reference that points /// at something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRef; /// /// fn main() { /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); /// let owning_ref = owning_ref.map(|array| &array[2]); /// /// // create a owning reference that points at the /// // second element of the array from the owning ref that was pointing to the third /// let owning_ref = owning_ref.try_map_with_owner(|array, _prev| { /// if array[1] == 2 { Ok(&array[1]) } else { Err(()) } /// }); /// assert_eq!(*owning_ref.unwrap(), 2); /// } /// ``` pub fn try_map_with_owner(self, f: F) -> Result, E> where O: StableAddress, F: for<'a> FnOnce(&'a O, &'a T) -> Result<&'a U, E> { Ok(OwningRef { reference: f(&self.owner, &self)?, owner: self.owner, }) } /// Converts `self` into a new owning reference with a different owner type. /// /// The new owner type needs to still contain the original owner in some way /// so that the reference into it remains valid. This function is marked unsafe /// because the user needs to manually uphold this guarantee. pub unsafe fn map_owner(self, f: F) -> OwningRef where O: StableAddress, P: StableAddress, F: FnOnce(O) -> P { OwningRef { reference: self.reference, owner: f(self.owner), } } /// Converts `self` into a new owning reference where the owner is wrapped /// in an additional `Box`. /// /// This can be used to safely erase the owner of any `OwningRef` /// to a `OwningRef, T>`. pub fn map_owner_box(self) -> OwningRef, T> { OwningRef { reference: self.reference, owner: Box::new(self.owner), } } /// Erases the concrete base type of the owner with a trait object. /// /// This allows mixing of owned references with different owner base types. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::{OwningRef, Erased}; /// /// fn main() { /// // NB: Using the concrete types here for explicitnes. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_a: OwningRef, [i32; 4]> /// = OwningRef::new(Box::new([1, 2, 3, 4])); /// /// let owning_ref_b: OwningRef>, Vec<(i32, bool)>> /// = OwningRef::new(Box::new(vec![(0, false), (1, true)])); /// /// let owning_ref_a: OwningRef, i32> /// = owning_ref_a.map(|a| &a[0]); /// /// let owning_ref_b: OwningRef>, i32> /// = owning_ref_b.map(|a| &a[1].0); /// /// let owning_refs: [OwningRef, i32>; 2] /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()]; /// /// assert_eq!(*owning_refs[0], 1); /// assert_eq!(*owning_refs[1], 1); /// } /// ``` pub fn erase_owner<'a>(self) -> OwningRef where O: IntoErased<'a>, { OwningRef { reference: self.reference, owner: self.owner.into_erased(), } } // TODO: wrap_owner /// A reference to the underlying owner. pub fn as_owner(&self) -> &O { &self.owner } /// Discards the reference and retrieves the owner. pub fn into_owner(self) -> O { self.owner } } impl OwningRefMut { /// Creates a new owning reference from a owner /// initialized to the direct dereference of it. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRefMut; /// /// fn main() { /// let owning_ref_mut = OwningRefMut::new(Box::new(42)); /// assert_eq!(*owning_ref_mut, 42); /// } /// ``` pub fn new(mut o: O) -> Self where O: StableAddress, O: DerefMut, { OwningRefMut { reference: &mut *o, owner: o, } } /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. /// Instead, the caller is responsible to make the same promises as implementing the trait. /// /// This is useful for cases where coherence rules prevents implementing the trait /// without adding a dependency to this crate in a third-party library. pub unsafe fn new_assert_stable_address(mut o: O) -> Self where O: DerefMut, { OwningRefMut { reference: &mut *o, owner: o, } } /// Converts `self` into a new _shared_ owning reference that points at /// something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRefMut; /// /// fn main() { /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref = owning_ref_mut.map(|array| &array[2]); /// assert_eq!(*owning_ref, 3); /// } /// ``` pub fn map(mut self, f: F) -> OwningRef where O: StableAddress, F: FnOnce(&mut T) -> &U { OwningRef { reference: f(&mut self), owner: self.owner, } } /// Converts `self` into a new _mutable_ owning reference that points at /// something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRefMut; /// /// fn main() { /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]); /// assert_eq!(*owning_ref_mut, 3); /// } /// ``` pub fn map_mut(mut self, f: F) -> OwningRefMut where O: StableAddress, F: FnOnce(&mut T) -> &mut U { OwningRefMut { reference: f(&mut self), owner: self.owner, } } /// Tries to convert `self` into a new _shared_ owning reference that points /// at something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRefMut; /// /// fn main() { /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref = owning_ref_mut.try_map(|array| { /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } /// }); /// assert_eq!(*owning_ref.unwrap(), 3); /// } /// ``` pub fn try_map(mut self, f: F) -> Result, E> where O: StableAddress, F: FnOnce(&mut T) -> Result<&U, E> { Ok(OwningRef { reference: f(&mut self)?, owner: self.owner, }) } /// Tries to convert `self` into a new _mutable_ owning reference that points /// at something reachable from the previous one. /// /// This can be a reference to a field of `U`, something reachable from a field of /// `U`, or even something unrelated with a `'static` lifetime. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::OwningRefMut; /// /// fn main() { /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); /// /// // create a owning reference that points at the /// // third element of the array. /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| { /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) } /// }); /// assert_eq!(*owning_ref_mut.unwrap(), 3); /// } /// ``` pub fn try_map_mut(mut self, f: F) -> Result, E> where O: StableAddress, F: FnOnce(&mut T) -> Result<&mut U, E> { Ok(OwningRefMut { reference: f(&mut self)?, owner: self.owner, }) } /// Converts `self` into a new owning reference with a different owner type. /// /// The new owner type needs to still contain the original owner in some way /// so that the reference into it remains valid. This function is marked unsafe /// because the user needs to manually uphold this guarantee. pub unsafe fn map_owner(self, f: F) -> OwningRefMut where O: StableAddress, P: StableAddress, F: FnOnce(O) -> P { OwningRefMut { reference: self.reference, owner: f(self.owner), } } /// Converts `self` into a new owning reference where the owner is wrapped /// in an additional `Box`. /// /// This can be used to safely erase the owner of any `OwningRefMut` /// to a `OwningRefMut, T>`. pub fn map_owner_box(self) -> OwningRefMut, T> { OwningRefMut { reference: self.reference, owner: Box::new(self.owner), } } /// Erases the concrete base type of the owner with a trait object. /// /// This allows mixing of owned references with different owner base types. /// /// # Example /// ``` /// extern crate owning_ref; /// use owning_ref::{OwningRefMut, Erased}; /// /// fn main() { /// // NB: Using the concrete types here for explicitnes. /// // For less verbose code type aliases like `BoxRef` are provided. /// /// let owning_ref_mut_a: OwningRefMut, [i32; 4]> /// = OwningRefMut::new(Box::new([1, 2, 3, 4])); /// /// let owning_ref_mut_b: OwningRefMut>, Vec<(i32, bool)>> /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)])); /// /// let owning_ref_mut_a: OwningRefMut, i32> /// = owning_ref_mut_a.map_mut(|a| &mut a[0]); /// /// let owning_ref_mut_b: OwningRefMut>, i32> /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0); /// /// let owning_refs_mut: [OwningRefMut, i32>; 2] /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()]; /// /// assert_eq!(*owning_refs_mut[0], 1); /// assert_eq!(*owning_refs_mut[1], 1); /// } /// ``` pub fn erase_owner<'a>(self) -> OwningRefMut where O: IntoErased<'a>, { OwningRefMut { reference: self.reference, owner: self.owner.into_erased(), } } // TODO: wrap_owner /// A reference to the underlying owner. pub fn as_owner(&self) -> &O { &self.owner } /// A mutable reference to the underlying owner. pub fn as_owner_mut(&mut self) -> &mut O { &mut self.owner } /// Discards the reference and retrieves the owner. pub fn into_owner(self) -> O { self.owner } } ///////////////////////////////////////////////////////////////////////////// // OwningHandle ///////////////////////////////////////////////////////////////////////////// use std::ops::{Deref, DerefMut}; /// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows /// consumers to pass around an owned object and a dependent reference, /// `OwningHandle` contains an owned object and a dependent _object_. /// /// `OwningHandle` can encapsulate a `RefMut` along with its associated /// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. /// However, the API is completely generic and there are no restrictions on /// what types of owning and dependent objects may be used. /// /// `OwningHandle` is created by passing an owner object (which dereferences /// to a stable address) along with a callback which receives a pointer to /// that stable location. The callback may then dereference the pointer and /// mint a dependent object, with the guarantee that the returned object will /// not outlive the referent of the pointer. /// /// Since the callback needs to dereference a raw pointer, it requires `unsafe` /// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is /// implemented for common data structures. Types that implement `ToHandle` can /// be wrapped into an `OwningHandle` without passing a callback. pub struct OwningHandle where O: StableAddress, H: Deref, { handle: H, _owner: O, } impl Deref for OwningHandle where O: StableAddress, H: Deref, { type Target = H::Target; fn deref(&self) -> &H::Target { self.handle.deref() } } unsafe impl StableAddress for OwningHandle where O: StableAddress, H: StableAddress, {} impl DerefMut for OwningHandle where O: StableAddress, H: DerefMut, { fn deref_mut(&mut self) -> &mut H::Target { self.handle.deref_mut() } } /// Trait to implement the conversion of owner to handle for common types. pub trait ToHandle { /// The type of handle to be encapsulated by the OwningHandle. type Handle: Deref; /// Given an appropriately-long-lived pointer to ourselves, create a /// handle to be encapsulated by the `OwningHandle`. unsafe fn to_handle(x: *const Self) -> Self::Handle; } /// Trait to implement the conversion of owner to mutable handle for common types. pub trait ToHandleMut { /// The type of handle to be encapsulated by the OwningHandle. type HandleMut: DerefMut; /// Given an appropriately-long-lived pointer to ourselves, create a /// mutable handle to be encapsulated by the `OwningHandle`. unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut; } impl OwningHandle where O: StableAddress, O::Target: ToHandle, H: Deref, { /// Create a new `OwningHandle` for a type that implements `ToHandle`. For types /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts /// a callback to perform the conversion. pub fn new(o: O) -> Self { OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) }) } } impl OwningHandle where O: StableAddress, O::Target: ToHandleMut, H: DerefMut, { /// Create a new mutable `OwningHandle` for a type that implements `ToHandleMut`. pub fn new_mut(o: O) -> Self { OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) }) } } impl OwningHandle where O: StableAddress, H: Deref, { /// Create a new OwningHandle. The provided callback will be invoked with /// a pointer to the object owned by `o`, and the returned value is stored /// as the object to which this `OwningHandle` will forward `Deref` and /// `DerefMut`. pub fn new_with_fn(o: O, f: F) -> Self where F: FnOnce(*const O::Target) -> H { let h: H; { h = f(o.deref() as *const O::Target); } OwningHandle { handle: h, _owner: o, } } /// Create a new OwningHandle. The provided callback will be invoked with /// a pointer to the object owned by `o`, and the returned value is stored /// as the object to which this `OwningHandle` will forward `Deref` and /// `DerefMut`. pub fn try_new(o: O, f: F) -> Result where F: FnOnce(*const O::Target) -> Result { let h: H; { h = f(o.deref() as *const O::Target)?; } Ok(OwningHandle { handle: h, _owner: o, }) } /// A getter for the underlying owner. pub fn as_owner(&self) -> &O { &self._owner } /// Discards the dependent object and returns the owner. pub fn into_owner(self) -> O { self._owner } } ///////////////////////////////////////////////////////////////////////////// // std traits ///////////////////////////////////////////////////////////////////////////// use std::convert::From; use std::fmt::{self, Debug}; use std::marker::{Send, Sync}; use std::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering}; use std::hash::{Hash, Hasher}; use std::borrow::Borrow; impl Deref for OwningRef { type Target = T; fn deref(&self) -> &T { unsafe { &*self.reference } } } impl Deref for OwningRefMut { type Target = T; fn deref(&self) -> &T { unsafe { &*self.reference } } } impl DerefMut for OwningRefMut { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.reference } } } unsafe impl StableAddress for OwningRef {} unsafe impl StableAddress for OwningRefMut {} impl AsRef for OwningRef { fn as_ref(&self) -> &T { &*self } } impl AsRef for OwningRefMut { fn as_ref(&self) -> &T { &*self } } impl AsMut for OwningRefMut { fn as_mut(&mut self) -> &mut T { &mut *self } } impl Borrow for OwningRef { fn borrow(&self) -> &T { &*self } } impl From for OwningRef where O: StableAddress, O: Deref, { fn from(owner: O) -> Self { OwningRef::new(owner) } } impl From for OwningRefMut where O: StableAddress, O: DerefMut { fn from(owner: O) -> Self { OwningRefMut::new(owner) } } impl From> for OwningRef where O: StableAddress, O: DerefMut { fn from(other: OwningRefMut) -> Self { OwningRef { owner: other.owner, reference: other.reference, } } } // ^ FIXME: Is a Into impl for calling into_owner() possible as well? impl Debug for OwningRef where O: Debug, T: Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.as_owner(), &**self) } } impl Debug for OwningRefMut where O: Debug, T: Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.as_owner(), &**self) } } impl Clone for OwningRef where O: CloneStableAddress, { fn clone(&self) -> Self { OwningRef { owner: self.owner.clone(), reference: self.reference, } } } unsafe impl CloneStableAddress for OwningRef where O: CloneStableAddress {} unsafe impl Send for OwningRef where O: Send, for<'a> (&'a T): Send {} unsafe impl Sync for OwningRef where O: Sync, for<'a> (&'a T): Sync {} unsafe impl Send for OwningRefMut where O: Send, for<'a> (&'a mut T): Send {} unsafe impl Sync for OwningRefMut where O: Sync, for<'a> (&'a mut T): Sync {} impl Debug for dyn Erased { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "",) } } impl PartialEq for OwningRef where T: PartialEq { fn eq(&self, other: &Self) -> bool { (&*self as &T).eq(&*other as &T) } } impl Eq for OwningRef where T: Eq {} impl PartialOrd for OwningRef where T: PartialOrd { fn partial_cmp(&self, other: &Self) -> Option { (&*self as &T).partial_cmp(&*other as &T) } } impl Ord for OwningRef where T: Ord { fn cmp(&self, other: &Self) -> Ordering { (&*self as &T).cmp(&*other as &T) } } impl Hash for OwningRef where T: Hash { fn hash(&self, state: &mut H) { (&*self as &T).hash(state); } } impl PartialEq for OwningRefMut where T: PartialEq { fn eq(&self, other: &Self) -> bool { (&*self as &T).eq(&*other as &T) } } impl Eq for OwningRefMut where T: Eq {} impl PartialOrd for OwningRefMut where T: PartialOrd { fn partial_cmp(&self, other: &Self) -> Option { (&*self as &T).partial_cmp(&*other as &T) } } impl Ord for OwningRefMut where T: Ord { fn cmp(&self, other: &Self) -> Ordering { (&*self as &T).cmp(&*other as &T) } } impl Hash for OwningRefMut where T: Hash { fn hash(&self, state: &mut H) { (&*self as &T).hash(state); } } ///////////////////////////////////////////////////////////////////////////// // std types integration and convenience type defs ///////////////////////////////////////////////////////////////////////////// use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; use std::cell::{Ref, RefCell, RefMut}; impl ToHandle for RefCell { type Handle = Ref<'static, T>; unsafe fn to_handle(x: *const Self) -> Self::Handle { (*x).borrow() } } impl ToHandleMut for RefCell { type HandleMut = RefMut<'static, T>; unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { (*x).borrow_mut() } } // NB: Implementing ToHandle{,Mut} for Mutex and RwLock requires a decision // about which handle creation to use (i.e. read() vs try_read()) as well as // what to do with error results. /// Typedef of a owning reference that uses a `Box` as the owner. pub type BoxRef = OwningRef, U>; /// Typedef of a owning reference that uses a `Vec` as the owner. pub type VecRef = OwningRef, U>; /// Typedef of a owning reference that uses a `String` as the owner. pub type StringRef = OwningRef; /// Typedef of a owning reference that uses a `Rc` as the owner. pub type RcRef = OwningRef, U>; /// Typedef of a owning reference that uses a `Arc` as the owner. pub type ArcRef = OwningRef, U>; /// Typedef of a owning reference that uses a `Ref` as the owner. pub type RefRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a owning reference that uses a `RefMut` as the owner. pub type RefMutRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a owning reference that uses a `MutexGuard` as the owner. pub type MutexGuardRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a owning reference that uses a `RwLockReadGuard` as the owner. pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a owning reference that uses a `RwLockWriteGuard` as the owner. pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a mutable owning reference that uses a `Box` as the owner. pub type BoxRefMut = OwningRefMut, U>; /// Typedef of a mutable owning reference that uses a `Vec` as the owner. pub type VecRefMut = OwningRefMut, U>; /// Typedef of a mutable owning reference that uses a `String` as the owner. pub type StringRefMut = OwningRefMut; /// Typedef of a mutable owning reference that uses a `RefMut` as the owner. pub type RefMutRefMut<'a, T, U = T> = OwningRefMut, U>; /// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut, U>; /// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner. pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRefMut, U>; unsafe impl<'a, T: 'a> IntoErased<'a> for Box { type Erased = Box; fn into_erased(self) -> Self::Erased { self } } unsafe impl<'a, T: 'a> IntoErased<'a> for Rc { type Erased = Rc; fn into_erased(self) -> Self::Erased { self } } unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { type Erased = Arc; fn into_erased(self) -> Self::Erased { self } } /// Typedef of a owning reference that uses an erased `Box` as the owner. pub type ErasedBoxRef = OwningRef, U>; /// Typedef of a owning reference that uses an erased `Rc` as the owner. pub type ErasedRcRef = OwningRef, U>; /// Typedef of a owning reference that uses an erased `Arc` as the owner. pub type ErasedArcRef = OwningRef, U>; /// Typedef of a mutable owning reference that uses an erased `Box` as the owner. pub type ErasedBoxRefMut = OwningRefMut, U>; #[cfg(test)] mod tests { mod owning_ref { use super::super::OwningRef; use super::super::{RcRef, BoxRef, Erased, ErasedBoxRef}; use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; use std::collections::HashMap; use std::rc::Rc; #[derive(Debug, PartialEq)] struct Example(u32, String, [u8; 3]); fn example() -> Example { Example(42, "hello world".to_string(), [1, 2, 3]) } #[test] fn new_deref() { let or: OwningRef, ()> = OwningRef::new(Box::new(())); assert_eq!(&*or, &()); } #[test] fn into() { let or: OwningRef, ()> = Box::new(()).into(); assert_eq!(&*or, &()); } #[test] fn map_offset_ref() { let or: BoxRef = Box::new(example()).into(); let or: BoxRef<_, u32> = or.map(|x| &x.0); assert_eq!(&*or, &42); let or: BoxRef = Box::new(example()).into(); let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); assert_eq!(&*or, &2); } #[test] fn map_heap_ref() { let or: BoxRef = Box::new(example()).into(); let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); assert_eq!(&*or, "hello"); } #[test] fn map_static_ref() { let or: BoxRef<()> = Box::new(()).into(); let or: BoxRef<_, str> = or.map(|_| "hello"); assert_eq!(&*or, "hello"); } #[test] fn map_chained() { let or: BoxRef = Box::new(example().1).into(); let or: BoxRef<_, str> = or.map(|x| &x[1..5]); let or: BoxRef<_, str> = or.map(|x| &x[..2]); assert_eq!(&*or, "el"); } #[test] fn map_chained_inference() { let or = BoxRef::new(Box::new(example().1)) .map(|x| &x[..5]) .map(|x| &x[1..3]); assert_eq!(&*or, "el"); } #[test] fn as_owner() { let or: BoxRef = Box::new(example().1).into(); let or = or.map(|x| &x[..5]); assert_eq!(&*or, "hello"); assert_eq!(&**or.as_owner(), "hello world"); } #[test] fn into_owner() { let or: BoxRef = Box::new(example().1).into(); let or = or.map(|x| &x[..5]); assert_eq!(&*or, "hello"); let s = *or.into_owner(); assert_eq!(&s, "hello world"); } #[test] fn fmt_debug() { let or: BoxRef = Box::new(example().1).into(); let or = or.map(|x| &x[..5]); let s = format!("{:?}", or); assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); } #[test] fn erased_owner() { let o1: BoxRef = BoxRef::new(Box::new(example())) .map(|x| &x.1[..]); let o2: BoxRef = BoxRef::new(Box::new(example().1)) .map(|x| &x[..]); let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; assert!(os.iter().all(|e| &e[..] == "hello world")); } #[test] fn non_static_erased_owner() { let foo = [413, 612]; let bar = &foo; // FIXME: lifetime inference fails us, and we can't easily define a lifetime for a closure // (see https://github.com/rust-lang/rust/issues/22340) // So we use a function to identify the lifetimes instead. fn borrow<'a>(a: &'a &[i32; 2]) -> &'a i32 { &a[0] } let o: BoxRef<&[i32; 2]> = Box::new(bar).into(); let o: BoxRef<&[i32; 2], i32> = o.map(borrow); let o: BoxRef = o.erase_owner(); assert_eq!(*o, 413); } #[test] fn raii_locks() { use super::super::{RefRef, RefMutRef}; use std::cell::RefCell; use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; use std::sync::{Mutex, RwLock}; { let a = RefCell::new(1); let a = { let a = RefRef::new(a.borrow()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = RefCell::new(1); let a = { let a = RefMutRef::new(a.borrow_mut()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = Mutex::new(1); let a = { let a = MutexGuardRef::new(a.lock().unwrap()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = RwLock::new(1); let a = { let a = RwLockReadGuardRef::new(a.read().unwrap()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = RwLock::new(1); let a = { let a = RwLockWriteGuardRef::new(a.write().unwrap()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } } #[test] fn eq() { let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); assert_eq!(or1.eq(&or2), true); } #[test] fn cmp() { let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); assert_eq!(or1.cmp(&or2), Ordering::Less); } #[test] fn partial_cmp() { let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); } #[test] fn hash() { let mut h1 = DefaultHasher::new(); let mut h2 = DefaultHasher::new(); let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); or1.hash(&mut h1); or2.hash(&mut h2); assert_eq!(h1.finish(), h2.finish()); } #[test] fn borrow() { let mut hash = HashMap::new(); let key = RcRef::::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); hash.insert(key.clone().map(|s| &s[..3]), 42); hash.insert(key.clone().map(|s| &s[4..]), 23); assert_eq!(hash.get("foo"), Some(&42)); assert_eq!(hash.get("bar"), Some(&23)); } #[test] fn total_erase() { let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); let b: OwningRef, [u8]> = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); let c: OwningRef>, [u8]> = unsafe {a.map_owner(Rc::new)}; let d: OwningRef>, [u8]> = unsafe {b.map_owner(Rc::new)}; let e: OwningRef, [u8]> = c.erase_owner(); let f: OwningRef, [u8]> = d.erase_owner(); let _g = e.clone(); let _h = f.clone(); } #[test] fn total_erase_box() { let a: OwningRef, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); let b: OwningRef, [u8]> = OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); let c: OwningRef>, [u8]> = a.map_owner_box(); let d: OwningRef>, [u8]> = b.map_owner_box(); let _e: OwningRef, [u8]> = c.erase_owner(); let _f: OwningRef, [u8]> = d.erase_owner(); } #[test] fn try_map1() { use std::any::Any; let x = Box::new(123_i32); let y: Box = x; OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).unwrap(); } #[test] fn try_map2() { use std::any::Any; let x = Box::new(123_u32); let y: Box = x; OwningRef::new(y).try_map(|x| x.downcast_ref::().ok_or(())).unwrap_err(); } #[test] fn map_with_owner() { let owning_ref: BoxRef = Box::new(example()).into(); let owning_ref = owning_ref.map(|owner| &owner.1); owning_ref.map_with_owner(|owner, ref_field| { assert_eq!(owner.1, *ref_field); ref_field }); } #[test] fn try_map_with_owner_ok() { let owning_ref: BoxRef = Box::new(example()).into(); let owning_ref = owning_ref.map(|owner| &owner.1); owning_ref.try_map_with_owner(|owner, ref_field| { assert_eq!(owner.1, *ref_field); Ok(ref_field) as Result<_, ()> }).unwrap(); } #[test] fn try_map_with_owner_err() { let owning_ref: BoxRef = Box::new(example()).into(); let owning_ref = owning_ref.map(|owner| &owner.1); owning_ref.try_map_with_owner(|owner, ref_field| { assert_eq!(owner.1, *ref_field); Err(()) as Result<&(), _> }).unwrap_err(); } } mod owning_handle { use super::super::OwningHandle; use super::super::RcRef; use std::rc::Rc; use std::cell::RefCell; use std::sync::Arc; use std::sync::RwLock; #[test] fn owning_handle() { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); assert_eq!(*handle, 2); *handle = 3; assert_eq!(*handle, 3); } #[test] fn try_owning_handle_ok() { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()) }).unwrap(); assert_eq!(*handle, 2); *handle = 3; assert_eq!(*handle, 3); } #[test] fn try_owning_handle_err() { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { if false { return Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()) } Err(()) }); assert!(handle.is_err()); } #[test] fn nested() { use std::cell::RefCell; use std::sync::{Arc, RwLock}; let result = { let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); let curr = RcRef::new(complex); let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); assert_eq!(*curr, "someString"); *curr = "someOtherString"; curr }; assert_eq!(*result, "someOtherString"); } #[test] fn owning_handle_safe() { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); let handle = OwningHandle::new(cell_ref); assert_eq!(*handle, 2); } #[test] fn owning_handle_mut_safe() { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); let mut handle = OwningHandle::new_mut(cell_ref); assert_eq!(*handle, 2); *handle = 3; assert_eq!(*handle, 3); } #[test] fn owning_handle_safe_2() { let result = { let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); let curr = RcRef::new(complex); let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); assert_eq!(*curr, "someString"); *curr = "someOtherString"; curr }; assert_eq!(*result, "someOtherString"); } } mod owning_ref_mut { use super::super::{OwningRefMut, BoxRefMut, Erased, ErasedBoxRefMut}; use super::super::BoxRef; use std::cmp::{PartialEq, Ord, PartialOrd, Ordering}; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; use std::collections::HashMap; #[derive(Debug, PartialEq)] struct Example(u32, String, [u8; 3]); fn example() -> Example { Example(42, "hello world".to_string(), [1, 2, 3]) } #[test] fn new_deref() { let or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); assert_eq!(&*or, &()); } #[test] fn new_deref_mut() { let mut or: OwningRefMut, ()> = OwningRefMut::new(Box::new(())); assert_eq!(&mut *or, &mut ()); } #[test] fn mutate() { let mut or: OwningRefMut, usize> = OwningRefMut::new(Box::new(0)); assert_eq!(&*or, &0); *or = 1; assert_eq!(&*or, &1); } #[test] fn into() { let or: OwningRefMut, ()> = Box::new(()).into(); assert_eq!(&*or, &()); } #[test] fn map_offset_ref() { let or: BoxRefMut = Box::new(example()).into(); let or: BoxRef<_, u32> = or.map(|x| &mut x.0); assert_eq!(&*or, &42); let or: BoxRefMut = Box::new(example()).into(); let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); assert_eq!(&*or, &2); } #[test] fn map_heap_ref() { let or: BoxRefMut = Box::new(example()).into(); let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); assert_eq!(&*or, "hello"); } #[test] fn map_static_ref() { let or: BoxRefMut<()> = Box::new(()).into(); let or: BoxRef<_, str> = or.map(|_| "hello"); assert_eq!(&*or, "hello"); } #[test] fn map_mut_offset_ref() { let or: BoxRefMut = Box::new(example()).into(); let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); assert_eq!(&*or, &42); let or: BoxRefMut = Box::new(example()).into(); let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); assert_eq!(&*or, &2); } #[test] fn map_mut_heap_ref() { let or: BoxRefMut = Box::new(example()).into(); let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); assert_eq!(&*or, "hello"); } #[test] fn map_mut_static_ref() { static mut MUT_S: [u8; 5] = *b"hello"; let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; let or: BoxRefMut<()> = Box::new(()).into(); let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); assert_eq!(&*or, b"hello"); } #[test] fn map_mut_chained() { let or: BoxRefMut = Box::new(example().1).into(); let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); assert_eq!(&*or, "el"); } #[test] fn map_chained_inference() { let or = BoxRefMut::new(Box::new(example().1)) .map_mut(|x| &mut x[..5]) .map_mut(|x| &mut x[1..3]); assert_eq!(&*or, "el"); } #[test] fn try_map_mut() { let or: BoxRefMut = Box::new(example().1).into(); let or: Result, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); assert_eq!(&*or.unwrap(), "ello"); let or: BoxRefMut = Box::new(example().1).into(); let or: Result, ()> = or.try_map_mut(|_| Err(())); assert!(or.is_err()); } #[test] fn as_owner() { let or: BoxRefMut = Box::new(example().1).into(); let or = or.map_mut(|x| &mut x[..5]); assert_eq!(&*or, "hello"); assert_eq!(&**or.as_owner(), "hello world"); } #[test] fn into_owner() { let or: BoxRefMut = Box::new(example().1).into(); let or = or.map_mut(|x| &mut x[..5]); assert_eq!(&*or, "hello"); let s = *or.into_owner(); assert_eq!(&s, "hello world"); } #[test] fn fmt_debug() { let or: BoxRefMut = Box::new(example().1).into(); let or = or.map_mut(|x| &mut x[..5]); let s = format!("{:?}", or); assert_eq!(&s, "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); } #[test] fn erased_owner() { let o1: BoxRefMut = BoxRefMut::new(Box::new(example())) .map_mut(|x| &mut x.1[..]); let o2: BoxRefMut = BoxRefMut::new(Box::new(example().1)) .map_mut(|x| &mut x[..]); let os: Vec> = vec![o1.erase_owner(), o2.erase_owner()]; assert!(os.iter().all(|e| &e[..] == "hello world")); } #[test] fn non_static_erased_owner() { let mut foo = [413, 612]; let bar = &mut foo; // FIXME: lifetime inference fails us, and we can't easily define a lifetime for a closure // (see https://github.com/rust-lang/rust/issues/22340) // So we use a function to identify the lifetimes instead. fn borrow<'a>(a: &'a mut &mut [i32; 2]) -> &'a mut i32 { &mut a[0] } let o: BoxRefMut<&mut [i32; 2]> = Box::new(bar).into(); let o: BoxRefMut<&mut [i32; 2], i32> = o.map_mut(borrow); let o: BoxRefMut = o.erase_owner(); assert_eq!(*o, 413); } #[test] fn raii_locks() { use super::super::RefMutRefMut; use std::cell::RefCell; use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; use std::sync::{Mutex, RwLock}; { let a = RefCell::new(1); let a = { let a = RefMutRefMut::new(a.borrow_mut()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = Mutex::new(1); let a = { let a = MutexGuardRefMut::new(a.lock().unwrap()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } { let a = RwLock::new(1); let a = { let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); assert_eq!(*a, 1); a }; assert_eq!(*a, 1); drop(a); } } #[test] fn eq() { let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); assert_eq!(or1.eq(&or2), true); } #[test] fn cmp() { let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); assert_eq!(or1.cmp(&or2), Ordering::Less); } #[test] fn partial_cmp() { let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); } #[test] fn hash() { let mut h1 = DefaultHasher::new(); let mut h2 = DefaultHasher::new(); let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); or1.hash(&mut h1); or2.hash(&mut h2); assert_eq!(h1.finish(), h2.finish()); } #[test] fn borrow() { let mut hash = HashMap::new(); let key1 = BoxRefMut::::new(Box::new("foo".to_string())).map(|s| &s[..]); let key2 = BoxRefMut::::new(Box::new("bar".to_string())).map(|s| &s[..]); hash.insert(key1, 42); hash.insert(key2, 23); assert_eq!(hash.get("foo"), Some(&42)); assert_eq!(hash.get("bar"), Some(&23)); } #[test] fn total_erase() { let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); let b: OwningRefMut, [u8]> = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); let c: OwningRefMut>, [u8]> = unsafe {a.map_owner(Box::new)}; let d: OwningRefMut>, [u8]> = unsafe {b.map_owner(Box::new)}; let _e: OwningRefMut, [u8]> = c.erase_owner(); let _f: OwningRefMut, [u8]> = d.erase_owner(); } #[test] fn total_erase_box() { let a: OwningRefMut, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); let b: OwningRefMut, [u8]> = OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); let c: OwningRefMut>, [u8]> = a.map_owner_box(); let d: OwningRefMut>, [u8]> = b.map_owner_box(); let _e: OwningRefMut, [u8]> = c.erase_owner(); let _f: OwningRefMut, [u8]> = d.erase_owner(); } #[test] fn try_map1() { use std::any::Any; let x = Box::new(123_i32); let y: Box = x; OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).unwrap(); } #[test] fn try_map2() { use std::any::Any; let x = Box::new(123_u32); let y: Box = x; OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::().ok_or(())).unwrap_err(); } #[test] fn try_map3() { use std::any::Any; let x = Box::new(123_i32); let y: Box = x; OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).unwrap(); } #[test] fn try_map4() { use std::any::Any; let x = Box::new(123_u32); let y: Box = x; OwningRefMut::new(y).try_map(|x| x.downcast_ref::().ok_or(())).unwrap_err(); } #[test] fn into_owning_ref() { use super::super::BoxRef; let or: BoxRefMut<()> = Box::new(()).into(); let or: BoxRef<()> = or.into(); assert_eq!(&*or, &()); } struct Foo { u: u32, } struct Bar { f: Foo, } #[test] fn ref_mut() { use std::cell::RefCell; let a = RefCell::new(Bar { f: Foo { u: 42 } }); let mut b = OwningRefMut::new(a.borrow_mut()); assert_eq!(b.f.u, 42); b.f.u = 43; let mut c = b.map_mut(|x| &mut x.f); assert_eq!(c.u, 43); c.u = 44; let mut d = c.map_mut(|x| &mut x.u); assert_eq!(*d, 44); *d = 45; assert_eq!(*d, 45); } } }