Crate owning_ref [] [src]

An owning reference.

This crate provides the owning reference type OwningRef 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.

It works by requiring owner types to dereference to stable memory locations and preventing mutable access, which in practice requires an heap allocation as provided by Box<T>, Rc<T>, etc.

Also provided are typedefs for common owner type combinations, which allows for less verbose type signatures. For example, BoxRef<T> instead of OwningRef<Box<T>, T>.

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!
}Run

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);
}Run

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);
}Run

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");
}Run

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);
}Run

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);
}Run

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));
}Run

Structs

OwningRef

An owning reference.

Traits

CloneStableAddress

Marker trait for expressing that the memory address of the value reachable via a dereference remains identical even if self is a clone.

Erased

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.

IntoErased

Helper trait for erasing the concrete type of what an owner derferences to, for example Box<T> -> Box<Erased>. This would be unneeded with higher kinded types support in the language.

StableAddress

Marker trait for expressing that the memory address of the value reachable via a dereference remains identical even if self gets moved.

Type Definitions

ArcRef

Typedef of a owning reference that uses a Arc as the owner.

BoxRef

Typedef of a owning reference that uses a Box as the owner.

ErasedArcRef

Typedef of a owning reference that uses an erased Arc as the owner.

ErasedBoxRef

Typedef of a owning reference that uses an erased Box as the owner.

ErasedRcRef

Typedef of a owning reference that uses an erased Rc as the owner.

MutexGuardRef

Typedef of a owning reference that uses a MutexGuard as the owner.

RcRef

Typedef of a owning reference that uses a Rc as the owner.

RefMutRef

Typedef of a owning reference that uses a RefMut as the owner.

RefRef

Typedef of a owning reference that uses a Ref as the owner.

RwLockReadGuardRef

Typedef of a owning reference that uses a RwLockReadGuard as the owner.

RwLockWriteGuardRef

Typedef of a owning reference that uses a RwLockWriteGuard as the owner.

StringRef

Typedef of a owning reference that uses a String as the owner.

VecRef

Typedef of a owning reference that uses a Vec as the owner.