https://github.com/kiranandcode/dependent-view
A rust library for weak dependent views.
https://github.com/kiranandcode/dependent-view
rust trait-object weak-references
Last synced: 8 months ago
JSON representation
A rust library for weak dependent views.
- Host: GitHub
- URL: https://github.com/kiranandcode/dependent-view
- Owner: kiranandcode
- License: mit
- Created: 2018-08-01T06:37:15.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-08-06T14:36:21.000Z (over 7 years ago)
- Last Synced: 2025-03-28T07:42:03.032Z (9 months ago)
- Topics: rust, trait-object, weak-references
- Language: Rust
- Size: 27.3 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dependent_view [](https://ci.appveyor.com/project/Gopiandcode/dependent-view) [](https://travis-ci.org/Gopiandcode/dependent-view)
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.
## Usage
Add this to your `Cargo.toml`
```
[dependencies]
dependent_view="1"
```
and this to your crate root:
```
#[macro_use]
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` from these objects, use the macros `to_view!()` or `to_view_sync()` respectively.
It is checked at compile time that the type `T` wihtin `DependentRc` impl's the trait you want to obtain a view for (see example).
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` 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.
## Example
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{:?}", self.id);}}
impl Prance for Dancer {fn prance(&self) {println!("P{:?}", self.id);}}
struct Prancer {id: usize}
impl Dance for Prancer {fn dance(&self) {println!("D{:?}", self.id);}}
impl Prance for Prancer {fn prance(&self) {println!("P{:?}", self.id);}}
```
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 = to_view!(dancer);
let dancer_prance_view : Weak = to_view!(dancer);
let prancer_dance_view : Weak = to_view!(prancer);
let prancer_prance_view : Weak = 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> = Vec::new();
let mut prancers : Vec> = Vec::new();
{
let mut dancer = DependentRc::new(Dancer { id: 0 });
let mut prancer = DependentRc::new(Prancer { id: 0 });
dancers.push(to_view!(dancer));
prancers.push(to_view!(dancer));
dancers.push(to_view!(prancer));
prancers.push(to_view!(prancer));
for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {
dancer_ref.upgrade().unwrap().dance();
prancer_ref.upgrade().unwrap().prance();
}
// at this point, dancer and prancer are dropped, invalidating the views
}
for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {
assert!(dancer_ref.upgrade().is_none());
assert!(prancer_ref.upgrade().is_none());
}
```
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:
```
struct Bad { id: usize }
let bad = DependentRc::new(Bad { id: 0 });
let bad_view : Weak = to_view!(bad); // compile time error
```
See `example.rs` 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.