#![warn(missing_docs)]
use std::mem;
pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress};
pub struct OwningRef<O, T: ?Sized> {
owner: O,
reference: *const T,
}
pub struct OwningRefMut<O, T: ?Sized> {
owner: O,
reference: *mut T,
}
pub trait Erased {}
impl<T> Erased for T {}
pub unsafe trait IntoErased<'a> {
type Erased;
fn into_erased(self) -> Self::Erased;
}
pub unsafe trait IntoErasedSend<'a> {
type Erased: Send;
fn into_erased_send(self) -> Self::Erased;
}
pub unsafe trait IntoErasedSendSync<'a> {
type Erased: Send + Sync;
fn into_erased_send_sync(self) -> Self::Erased;
}
impl<O, T: ?Sized> OwningRef<O, T> {
pub fn new(o: O) -> Self
where O: StableAddress,
O: Deref<Target = T>,
{
OwningRef {
reference: &*o,
owner: o,
}
}
pub unsafe fn new_assert_stable_address(o: O) -> Self
where O: Deref<Target = T>,
{
OwningRef {
reference: &*o,
owner: o,
}
}
pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
where O: StableAddress,
F: FnOnce(&T) -> &U
{
OwningRef {
reference: f(&self),
owner: self.owner,
}
}
pub fn try_map<F, U: ?Sized, E>(self, f: F) -> Result<OwningRef<O, U>, E>
where O: StableAddress,
F: FnOnce(&T) -> Result<&U, E>
{
Ok(OwningRef {
reference: f(&self)?,
owner: self.owner,
})
}
pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRef<P, T>
where O: StableAddress,
P: StableAddress,
F: FnOnce(O) -> P
{
OwningRef {
reference: self.reference,
owner: f(self.owner),
}
}
pub fn map_owner_box(self) -> OwningRef<Box<O>, T> {
OwningRef {
reference: self.reference,
owner: Box::new(self.owner),
}
}
pub fn erase_owner<'a>(self) -> OwningRef<O::Erased, T>
where O: IntoErased<'a>,
{
OwningRef {
reference: self.reference,
owner: self.owner.into_erased(),
}
}
pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T>
where O: IntoErasedSend<'a>,
{
OwningRef {
reference: self.reference,
owner: self.owner.into_erased_send(),
}
}
pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T>
where O: IntoErasedSendSync<'a>,
{
OwningRef {
reference: self.reference,
owner: self.owner.into_erased_send_sync(),
}
}
pub fn owner(&self) -> &O {
&self.owner
}
pub fn into_inner(self) -> O {
self.owner
}
}
impl<O, T: ?Sized> OwningRefMut<O, T> {
pub fn new(mut o: O) -> Self
where O: StableAddress,
O: DerefMut<Target = T>,
{
OwningRefMut {
reference: &mut *o,
owner: o,
}
}
pub unsafe fn new_assert_stable_address(mut o: O) -> Self
where O: DerefMut<Target = T>,
{
OwningRefMut {
reference: &mut *o,
owner: o,
}
}
pub fn map<F, U: ?Sized>(mut self, f: F) -> OwningRef<O, U>
where O: StableAddress,
F: FnOnce(&mut T) -> &U
{
OwningRef {
reference: f(&mut self),
owner: self.owner,
}
}
pub fn map_mut<F, U: ?Sized>(mut self, f: F) -> OwningRefMut<O, U>
where O: StableAddress,
F: FnOnce(&mut T) -> &mut U
{
OwningRefMut {
reference: f(&mut self),
owner: self.owner,
}
}
pub fn try_map<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRef<O, U>, E>
where O: StableAddress,
F: FnOnce(&mut T) -> Result<&U, E>
{
Ok(OwningRef {
reference: f(&mut self)?,
owner: self.owner,
})
}
pub fn try_map_mut<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRefMut<O, U>, E>
where O: StableAddress,
F: FnOnce(&mut T) -> Result<&mut U, E>
{
Ok(OwningRefMut {
reference: f(&mut self)?,
owner: self.owner,
})
}
pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRefMut<P, T>
where O: StableAddress,
P: StableAddress,
F: FnOnce(O) -> P
{
OwningRefMut {
reference: self.reference,
owner: f(self.owner),
}
}
pub fn map_owner_box(self) -> OwningRefMut<Box<O>, T> {
OwningRefMut {
reference: self.reference,
owner: Box::new(self.owner),
}
}
pub fn erase_owner<'a>(self) -> OwningRefMut<O::Erased, T>
where O: IntoErased<'a>,
{
OwningRefMut {
reference: self.reference,
owner: self.owner.into_erased(),
}
}
pub fn owner(&self) -> &O {
&self.owner
}
pub fn into_inner(self) -> O {
self.owner
}
}
use std::ops::{Deref, DerefMut};
pub struct OwningHandle<O, H>
where O: StableAddress, H: Deref,
{
handle: H,
_owner: O,
}
impl<O, H> Deref for OwningHandle<O, H>
where O: StableAddress, H: Deref,
{
type Target = H::Target;
fn deref(&self) -> &H::Target {
self.handle.deref()
}
}
unsafe impl<O, H> StableAddress for OwningHandle<O, H>
where O: StableAddress, H: StableAddress,
{}
impl<O, H> DerefMut for OwningHandle<O, H>
where O: StableAddress, H: DerefMut,
{
fn deref_mut(&mut self) -> &mut H::Target {
self.handle.deref_mut()
}
}
pub trait ToHandle {
type Handle: Deref;
unsafe fn to_handle(x: *const Self) -> Self::Handle;
}
pub trait ToHandleMut {
type HandleMut: DerefMut;
unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut;
}
impl<O, H> OwningHandle<O, H>
where O: StableAddress, O::Target: ToHandle<Handle = H>, H: Deref,
{
pub fn new(o: O) -> Self {
OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) })
}
}
impl<O, H> OwningHandle<O, H>
where O: StableAddress, O::Target: ToHandleMut<HandleMut = H>, H: DerefMut,
{
pub fn new_mut(o: O) -> Self {
OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) })
}
}
impl<O, H> OwningHandle<O, H>
where O: StableAddress, H: Deref,
{
pub fn new_with_fn<F>(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,
}
}
pub fn try_new<F, E>(o: O, f: F) -> Result<Self, E>
where F: FnOnce(*const O::Target) -> Result<H, E>
{
let h: H;
{
h = f(o.deref() as *const O::Target)?;
}
Ok(OwningHandle {
handle: h,
_owner: o,
})
}
}
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<O, T: ?Sized> Deref for OwningRef<O, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.reference
}
}
}
impl<O, T: ?Sized> Deref for OwningRefMut<O, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*self.reference
}
}
}
impl<O, T: ?Sized> DerefMut for OwningRefMut<O, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.reference
}
}
}
unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {}
impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> {
fn as_ref(&self) -> &T {
&*self
}
}
impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> {
fn as_ref(&self) -> &T {
&*self
}
}
impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
}
}
impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> {
fn borrow(&self) -> &T {
&*self
}
}
impl<O, T: ?Sized> From<O> for OwningRef<O, T>
where O: StableAddress,
O: Deref<Target = T>,
{
fn from(owner: O) -> Self {
OwningRef::new(owner)
}
}
impl<O, T: ?Sized> From<O> for OwningRefMut<O, T>
where O: StableAddress,
O: DerefMut<Target = T>
{
fn from(owner: O) -> Self {
OwningRefMut::new(owner)
}
}
impl<O, T: ?Sized> From<OwningRefMut<O, T>> for OwningRef<O, T>
where O: StableAddress,
O: DerefMut<Target = T>
{
fn from(other: OwningRefMut<O, T>) -> Self {
OwningRef {
owner: other.owner,
reference: other.reference,
}
}
}
impl<O, T: ?Sized> Debug for OwningRef<O, T>
where O: Debug,
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,
"OwningRef {{ owner: {:?}, reference: {:?} }}",
self.owner(),
&**self)
}
}
impl<O, T: ?Sized> Debug for OwningRefMut<O, T>
where O: Debug,
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,
"OwningRefMut {{ owner: {:?}, reference: {:?} }}",
self.owner(),
&**self)
}
}
impl<O, T: ?Sized> Clone for OwningRef<O, T>
where O: CloneStableAddress,
{
fn clone(&self) -> Self {
OwningRef {
owner: self.owner.clone(),
reference: self.reference,
}
}
}
unsafe impl<O, T: ?Sized> CloneStableAddress for OwningRef<O, T>
where O: CloneStableAddress {}
unsafe impl<O, T: ?Sized> Send for OwningRef<O, T>
where O: Send, for<'a> (&'a T): Send {}
unsafe impl<O, T: ?Sized> Sync for OwningRef<O, T>
where O: Sync, for<'a> (&'a T): Sync {}
unsafe impl<O, T: ?Sized> Send for OwningRefMut<O, T>
where O: Send, for<'a> (&'a mut T): Send {}
unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T>
where O: Sync, for<'a> (&'a mut T): Sync {}
impl Debug for dyn Erased {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<Erased>",)
}
}
impl<O, T: ?Sized> PartialEq for OwningRef<O, T> where T: PartialEq {
fn eq(&self, other: &Self) -> bool {
(&*self as &T).eq(&*other as &T)
}
}
impl<O, T: ?Sized> Eq for OwningRef<O, T> where T: Eq {}
impl<O, T: ?Sized> PartialOrd for OwningRef<O, T> where T: PartialOrd {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(&*self as &T).partial_cmp(&*other as &T)
}
}
impl<O, T: ?Sized> Ord for OwningRef<O, T> where T: Ord {
fn cmp(&self, other: &Self) -> Ordering {
(&*self as &T).cmp(&*other as &T)
}
}
impl<O, T: ?Sized> Hash for OwningRef<O, T> where T: Hash {
fn hash<H: Hasher>(&self, state: &mut H) {
(&*self as &T).hash(state);
}
}
impl<O, T: ?Sized> PartialEq for OwningRefMut<O, T> where T: PartialEq {
fn eq(&self, other: &Self) -> bool {
(&*self as &T).eq(&*other as &T)
}
}
impl<O, T: ?Sized> Eq for OwningRefMut<O, T> where T: Eq {}
impl<O, T: ?Sized> PartialOrd for OwningRefMut<O, T> where T: PartialOrd {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(&*self as &T).partial_cmp(&*other as &T)
}
}
impl<O, T: ?Sized> Ord for OwningRefMut<O, T> where T: Ord {
fn cmp(&self, other: &Self) -> Ordering {
(&*self as &T).cmp(&*other as &T)
}
}
impl<O, T: ?Sized> Hash for OwningRefMut<O, T> where T: Hash {
fn hash<H: Hasher>(&self, state: &mut H) {
(&*self as &T).hash(state);
}
}
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<T: 'static> ToHandle for RefCell<T> {
type Handle = Ref<'static, T>;
unsafe fn to_handle(x: *const Self) -> Self::Handle { (*x).borrow() }
}
impl<T: 'static> ToHandleMut for RefCell<T> {
type HandleMut = RefMut<'static, T>;
unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { (*x).borrow_mut() }
}
pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
pub type StringRef = OwningRef<String, str>;
pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
pub type BoxRefMut<T, U = T> = OwningRefMut<Box<T>, U>;
pub type VecRefMut<T, U = T> = OwningRefMut<Vec<T>, U>;
pub type StringRefMut = OwningRefMut<String, str>;
pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
type Erased = Box<dyn Erased + 'a>;
fn into_erased(self) -> Self::Erased {
self
}
}
unsafe impl<'a, T: 'a> IntoErased<'a> for Rc<T> {
type Erased = Rc<dyn Erased + 'a>;
fn into_erased(self) -> Self::Erased {
self
}
}
unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> {
type Erased = Arc<dyn Erased + 'a>;
fn into_erased(self) -> Self::Erased {
self
}
}
unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> {
type Erased = Box<dyn Erased + Send + 'a>;
fn into_erased_send(self) -> Self::Erased {
self
}
}
unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> {
type Erased = Box<dyn Erased + Sync + Send + 'a>;
fn into_erased_send_sync(self) -> Self::Erased {
let result: Box<dyn Erased + Send + 'a> = self;
unsafe {
mem::transmute(result)
}
}
}
unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> {
type Erased = Arc<dyn Erased + Send + Sync + 'a>;
fn into_erased_send_sync(self) -> Self::Erased {
self
}
}
pub type ErasedBoxRef<U> = OwningRef<Box<dyn Erased>, U>;
pub type ErasedRcRef<U> = OwningRef<Rc<dyn Erased>, U>;
pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>;
pub type ErasedBoxRefMut<U> = OwningRefMut<Box<dyn Erased>, 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<Box<()>, ()> = OwningRef::new(Box::new(()));
assert_eq!(&*or, &());
}
#[test]
fn into() {
let or: OwningRef<Box<()>, ()> = Box::new(()).into();
assert_eq!(&*or, &());
}
#[test]
fn map_offset_ref() {
let or: BoxRef<Example> = Box::new(example()).into();
let or: BoxRef<_, u32> = or.map(|x| &x.0);
assert_eq!(&*or, &42);
let or: BoxRef<Example> = 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<Example> = 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<String> = 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 owner() {
let or: BoxRef<String> = Box::new(example().1).into();
let or = or.map(|x| &x[..5]);
assert_eq!(&*or, "hello");
assert_eq!(&**or.owner(), "hello world");
}
#[test]
fn into_inner() {
let or: BoxRef<String> = Box::new(example().1).into();
let or = or.map(|x| &x[..5]);
assert_eq!(&*or, "hello");
let s = *or.into_inner();
assert_eq!(&s, "hello world");
}
#[test]
fn fmt_debug() {
let or: BoxRef<String> = 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<Example, str> = BoxRef::new(Box::new(example()))
.map(|x| &x.1[..]);
let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1))
.map(|x| &x[..]);
let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()];
assert!(os.iter().all(|e| &e[..] == "hello world"));
}
#[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::<String>::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<Vec<u8>, [u8]>
= OwningRef::new(vec![]).map(|x| &x[..]);
let b: OwningRef<Box<[u8]>, [u8]>
= OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe {a.map_owner(Rc::new)};
let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Rc::new)};
let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner();
let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner();
let _g = e.clone();
let _h = f.clone();
}
#[test]
fn total_erase_box() {
let a: OwningRef<Vec<u8>, [u8]>
= OwningRef::new(vec![]).map(|x| &x[..]);
let b: OwningRef<Box<[u8]>, [u8]>
= OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box();
let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner();
let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner();
}
#[test]
fn try_map1() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok());
}
#[test]
fn try_map2() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_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<Box<()>, ()> = OwningRefMut::new(Box::new(()));
assert_eq!(&*or, &());
}
#[test]
fn new_deref_mut() {
let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(()));
assert_eq!(&mut *or, &mut ());
}
#[test]
fn mutate() {
let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0));
assert_eq!(&*or, &0);
*or = 1;
assert_eq!(&*or, &1);
}
#[test]
fn into() {
let or: OwningRefMut<Box<()>, ()> = Box::new(()).into();
assert_eq!(&*or, &());
}
#[test]
fn map_offset_ref() {
let or: BoxRefMut<Example> = Box::new(example()).into();
let or: BoxRef<_, u32> = or.map(|x| &mut x.0);
assert_eq!(&*or, &42);
let or: BoxRefMut<Example> = 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<Example> = 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<Example> = Box::new(example()).into();
let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0);
assert_eq!(&*or, &42);
let or: BoxRefMut<Example> = 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<Example> = 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<String> = 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<String> = Box::new(example().1).into();
let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5]));
assert_eq!(&*or.unwrap(), "ello");
let or: BoxRefMut<String> = Box::new(example().1).into();
let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(()));
assert!(or.is_err());
}
#[test]
fn owner() {
let or: BoxRefMut<String> = Box::new(example().1).into();
let or = or.map_mut(|x| &mut x[..5]);
assert_eq!(&*or, "hello");
assert_eq!(&**or.owner(), "hello world");
}
#[test]
fn into_inner() {
let or: BoxRefMut<String> = Box::new(example().1).into();
let or = or.map_mut(|x| &mut x[..5]);
assert_eq!(&*or, "hello");
let s = *or.into_inner();
assert_eq!(&s, "hello world");
}
#[test]
fn fmt_debug() {
let or: BoxRefMut<String> = 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<Example, str> = BoxRefMut::new(Box::new(example()))
.map_mut(|x| &mut x.1[..]);
let o2: BoxRefMut<String, str> = BoxRefMut::new(Box::new(example().1))
.map_mut(|x| &mut x[..]);
let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()];
assert!(os.iter().all(|e| &e[..] == "hello world"));
}
#[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::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]);
let key2 = BoxRefMut::<String>::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<Vec<u8>, [u8]>
= OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
let b: OwningRefMut<Box<[u8]>, [u8]>
= OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe {a.map_owner(Box::new)};
let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe {b.map_owner(Box::new)};
let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
}
#[test]
fn total_erase_box() {
let a: OwningRefMut<Vec<u8>, [u8]>
= OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
let b: OwningRefMut<Box<[u8]>, [u8]>
= OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box();
let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
}
#[test]
fn try_map1() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_ok());
}
#[test]
fn try_map2() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_err());
}
#[test]
fn try_map3() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok());
}
#[test]
fn try_map4() {
use std::any::Any;
let x = Box::new(123_i32);
let y: Box<dyn Any> = x;
assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_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);
}
}
}