Created
September 27, 2016 12:48
-
-
Save randomPoison/c16e824c318cd580b9d3420784d5f05b to your computer and use it in GitHub Desktop.
A potential implementation for an aliasing sibling to Rc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::rc::Rc; | |
#[macro_use] | |
mod alias { | |
use std::ops::Deref; | |
use std::rc::Rc; | |
#[derive(Debug, Clone)] | |
pub struct RcAlias<T, U> { | |
rc: Rc<T>, | |
data: *const U, | |
} | |
impl<T, U> RcAlias<T, U> { | |
pub unsafe fn new(rc: Rc<T>, data: &U) -> RcAlias<T, U> { | |
RcAlias { | |
rc: rc, | |
data: data, | |
} | |
} | |
} | |
impl<T, U> Deref for RcAlias<T, U> { | |
type Target = U; | |
fn deref(&self) -> &U { | |
unsafe { &*self.data } | |
} | |
} | |
// macro_rules! build_path { | |
// ($root: expr, $part: ident ()) => { $root.$part() }; | |
// ($root: expr, $part: ident) => { &$root.$part } | |
// ($root $( . $part: tt )*) => { | |
// $root. build_path!() | |
// }; | |
// } | |
macro_rules! alias { | |
($rc: ident $( . $path: ident )*) => { | |
unsafe { | |
let data = &$rc $( . $path )*; | |
$crate::alias::RcAlias::new($rc.clone(), data) | |
} | |
}; | |
} | |
} | |
pub mod foo { | |
#[derive(Debug)] | |
pub struct Foo { | |
pub inner: u32, | |
bar: Bar, | |
} | |
impl Foo { | |
pub fn new(inner: u32, bar: Bar) -> Foo { | |
Foo { | |
inner: inner, | |
bar: bar, | |
} | |
} | |
pub fn get_bar(&self) -> &Bar { | |
&self.bar | |
} | |
} | |
#[derive(Debug)] | |
pub struct Bar { | |
pub inner: f32, | |
} | |
} | |
fn main() { | |
let (inner,) = { | |
let rc = Rc::new(foo::Foo::new(7, foo::Bar { inner: 9.876 })); | |
let ref_inner = alias!(rc.inner); | |
// // `alias!` doesn't support getters yet :( | |
// let ref_bar = alias!(rc.get_bar()); | |
(ref_inner,) | |
}; | |
// // We can also alias `RcAlias`. | |
// let bar_inner = alias!(bar.inner); | |
println!("the original rc has been dropped, inner: {:?}", &*inner); | |
// // This junk doesn't compile because the macro (rightly) doesn't allow | |
// // us to alias a nonexistent submember. | |
// let rc = Rc::new(Foo { | |
// inner: 7, | |
// bar: Bar { inner: 9.876 }, | |
// }); | |
// | |
// let bad_alias = alias!(rc.not.a.real.member); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment