Crate dependent_view[][src]

dependent_view is a rust library providing simple wrappers around the Rc and Arc types, imbuing them with the capability to provide "views" of non-owned structs to separate components of a system.


Add this to your Cargo.toml

This example is not tested

and this to your crate root:

This example is not tested
extern crate dependent_view;

The library provides two main structs DependentRc and DependentArc for normal and thread-safe views.

These change the result of the view type (between std::rc::Weak or std::sync::Weak).

To obtain a Weak<Trait> from a dependent struct, use the macros to_view!() or to_view_sync() respectively.

The compiler will check at compile time that the type T within DependentRc<T> impl's the trait you want to obtain a view for.

These dependent types provide a different kind of ownership delegation as compared to standard Rc's or Box's.

A DependentRc should be viewed as the single owner of it's contained type, however unlike a Box, it allows users to generate multiple runtime managed Weak<Trait> references to the object (for each Trait impl'd by the contained entity) - these Weak references cease to be upgradable once the source DependantRc is dropped.


Assume we have the following traits:

trait Dance {
    fn dance(&self);
trait Prance {
    fn prance(&self);

and some structs which impl the traits:

struct Dancer {id: usize}
impl Dance for Dancer {fn dance(&self) {println!("D{:?}",;}}
impl Prance for Dancer {fn prance(&self)  {println!("P{:?}",;}}
struct Prancer {id: usize}
impl Dance for Prancer {fn dance(&self) {println!("D{:?}",;}}
impl Prance for Prancer {fn prance(&self)  {println!("P{:?}",;}}

We can create DependentRc using the new function:

use dependent_view::rc::*;
let mut dancer = DependentRc::new(Dancer { id: 0 });
let mut prancer = DependentRc::new(Prancer { id: 0 });

We can use these DependentRc's to create non-owned views of our structs:

let dancer_dance_view : Weak<Dance> = to_view!(dancer);
let dancer_prance_view : Weak<Prance> = to_view!(dancer);
let prancer_dance_view : Weak<Dance> = to_view!(prancer);
let prancer_prance_view : Weak<Prance> = to_view!(prancer);

We can then share these views to other components, and not have to worry about managing their deletion:

let mut dancers : Vec<Weak<Dance>> = Vec::new();
let mut prancers : Vec<Weak<Prance>> = Vec::new();
    let mut dancer = DependentRc::new(Dancer { id: 0 });
    let mut prancer = DependentRc::new(Prancer { id: 0 });
    for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {
    // at this point, dancer and prancer are dropped, invalidating the views
for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {

Also, it is a compile time error to attempt to produce a trait view of a struct when the underlying struct doesn't implement the trait:

This example is not tested
struct Bad { id: usize }
let bad = DependentRc::new(Bad { id: 0 });
let bad_view : Weak<Dance> = to_view!(bad); // compile time error

See for the full source.

Due to the way the internals work, if the compiler can not infer the type of the result of to_view!, it complains about std::mem::transmute being called on types of different sizes. This usually only happens if you don't actually use the view - and can often be avoided by simply adding type annotations.



Module defining DependentArc, a wrapper around the Arc type.


Module defining DependentRc, a wrapper around the Rc type.



Macro for obtaining views from DependentRc


Macro for obtaining thread safe views from DependentArc