Last active
August 29, 2015 14:07
-
-
Save pythonesque/e4e1bea3c147e97dddec to your computer and use it in GitHub Desktop.
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
#![feature(if_let)] | |
extern crate arena; | |
extern crate rustc; | |
use arena::Arena; | |
use rustc::util::nodemap::FnvHashMap; | |
use std::any::{Any, AnyRefExt}; | |
use std::cell::RefCell; | |
use std::collections::hashmap; | |
use std::intrinsics::TypeId; | |
pub trait Component: Send {} | |
pub struct ComponentVec<T> where T: Component { | |
dummy: u8, | |
} | |
impl<T: Component> ComponentVec<T> { | |
pub fn new() -> ComponentVec<T> { | |
ComponentVec { | |
dummy: 42, | |
} | |
} | |
} | |
/// A simple wrapper for a `Arena` that holds `ComponentVecs`s to make the borrow checker happy. | |
pub struct ComponentVecArena<'a> { | |
/// The wrapped arena. | |
arena: Arena, | |
} | |
impl<'a> ComponentVecArena<'a> { | |
/// Creates a new, empty `ComponentVecArena`. | |
pub fn new() -> ComponentVecArena<'a> { | |
ComponentVecArena { | |
arena: Arena::new(), | |
} | |
} | |
/// Allocates a new `ComponentVec<T>` as a `RefCell<ComponentVec<T>>` in the wrapped arena and | |
/// returns a reference to it. | |
pub fn alloc_vec<'b: 'a, T>(&'b self) -> &'a RefCell<ComponentVec<T>> where T: Component | |
{ | |
self.arena.alloc( || RefCell::new(ComponentVec::<T>::new()) ) | |
} | |
} | |
pub struct ComponentCollection<'a> { | |
/// The (type id -> component vec pointer) pairs storage. | |
comp_vecs: FnvHashMap<TypeId, &'a Any>, | |
} | |
impl<'a> ComponentCollection<'a> { | |
/// Creates a new, empty `ComponentCollection`. | |
pub fn new() -> ComponentCollection<'a> { | |
ComponentCollection { | |
comp_vecs: FnvHashMap::new(), | |
} | |
} | |
/// Registers the component type `T` into this collection. | |
pub fn register<'b, 'c, T>(&'c mut self, arena: &'a ComponentVecArena<'b>) where T: Component { | |
if let hashmap::Vacant(entry) = self.comp_vecs.entry(TypeId::of::<T>()) { | |
entry.set(arena.alloc_vec::<T>()); | |
}; | |
} | |
/// Gets a mutable reference to the vector that stores `T`s in this collection. | |
pub fn vec_of<T>(&self) -> Option<&'a RefCell<ComponentVec<T>>> where T: Component { | |
self.comp_vecs.find(&TypeId::of::<T>()) | |
.map( |t| t.downcast_ref::<RefCell<ComponentVec<T>>>() | |
.expect("ComponentVec had the wrong type!") ) | |
} | |
} | |
struct MyComp; | |
impl Component for MyComp {} | |
struct MyComp2; | |
impl Component for MyComp2 {} | |
fn componentcollection_simple() { | |
let arena = ComponentVecArena::new(); | |
let mut collection = ComponentCollection::new(); | |
collection.register::<MyComp>(&arena); | |
let vec_ref = collection.vec_of::<MyComp>().unwrap(); | |
collection.register::<MyComp2>(&arena); | |
let vec_ref2 = collection.vec_of::<MyComp2>().unwrap(); | |
{ | |
println!("Borrow both"); | |
let v1 = vec_ref.borrow(); | |
println!("borrow vec: {}", v1.dummy); | |
let v2 = vec_ref.borrow(); | |
println!("borrow vec: {}", v2.dummy); | |
let v3 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v3.dummy); | |
let v4 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v4.dummy); | |
} | |
{ | |
println!("\nBorrow and mutate"); | |
let mut v1 = vec_ref.borrow_mut(); | |
v1.dummy = 1; | |
println!("mutate vec: {}", v1.dummy); | |
let v2 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v2.dummy); | |
let v3 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v3.dummy); | |
} | |
{ | |
println!("\nMutate both"); | |
let mut v1 = vec_ref.borrow_mut(); | |
v1.dummy = 2; | |
println!("mutate vec: {}", v1.dummy); | |
let mut v2 = vec_ref2.borrow_mut(); | |
v2.dummy = 3; | |
println!("mutate vec2: {}", v2.dummy); | |
} | |
} | |
fn main() { | |
componentcollection_simple(); | |
} |
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
#![feature(if_let)] | |
extern crate rustc; | |
use rustc::util::nodemap::FnvHashMap; | |
use std::any::{Any, AnyRefExt}; | |
use std::cell::RefCell; | |
use std::collections::hashmap; | |
use std::intrinsics::TypeId; | |
pub trait Component: Send {} | |
pub struct ComponentVec<T> where T: Component { | |
dummy: u8, | |
} | |
impl<T: Component> ComponentVec<T> { | |
pub fn new() -> ComponentVec<T> { | |
ComponentVec { | |
dummy: 42, | |
} | |
} | |
} | |
pub struct ComponentCollection { | |
/// The (type id -> component vec pointer) pairs storage. | |
comp_vecs: FnvHashMap<TypeId, Box<Any>>, | |
} | |
impl ComponentCollection { | |
/// Creates a new, empty `ComponentCollection`. | |
pub fn new() -> ComponentCollection { | |
ComponentCollection { | |
comp_vecs: FnvHashMap::new(), | |
} | |
} | |
/// Registers the component type `T` into this collection. | |
pub fn register<T>(&mut self) where T: Component { | |
if let hashmap::Vacant(entry) = self.comp_vecs.entry(TypeId::of::<T>()) { | |
let vec = ComponentVec::<T>::new(); | |
entry.set(box RefCell::new(vec)); | |
} | |
} | |
/// Gets a mutable reference to the vector that stores `T`s in this collection. | |
pub fn vec_of<T>(&self) -> Option<&RefCell<ComponentVec<T>>> where T: Component { | |
self.comp_vecs.find(&TypeId::of::<T>()) | |
.map( |t| t.downcast_ref::<RefCell<ComponentVec<T>>>() | |
.expect("ComponentVec had the wrong type!") ) | |
} | |
} | |
struct MyComp; | |
impl Component for MyComp {} | |
struct MyComp2; | |
impl Component for MyComp2 {} | |
fn componentcollection_simple() { | |
let mut collection = ComponentCollection::new(); | |
collection.register::<MyComp>(); | |
// This is the downside to the boxed version--you can't register new types while borrowing. | |
// This may not be a problem for your usecase. | |
// let vec_ref = collection.vec_of::<MyComp>().unwrap(); | |
collection.register::<MyComp2>(); | |
let vec_ref = collection.vec_of::<MyComp>().unwrap(); | |
let vec_ref2 = collection.vec_of::<MyComp2>().unwrap(); | |
{ | |
println!("Borrow both"); | |
let v1 = vec_ref.borrow(); | |
println!("borrow vec: {}", v1.dummy); | |
let v2 = vec_ref.borrow(); | |
println!("borrow vec: {}", v2.dummy); | |
let v3 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v3.dummy); | |
let v4 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v4.dummy); | |
} | |
{ | |
println!("\nBorrow and mutate"); | |
let mut v1 = vec_ref.borrow_mut(); | |
v1.dummy = 1; | |
println!("mutate vec: {}", v1.dummy); | |
let v2 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v2.dummy); | |
let v3 = vec_ref2.borrow(); | |
println!("borrow vec2: {}", v3.dummy); | |
} | |
{ | |
println!("\nMutate both"); | |
let mut v1 = vec_ref.borrow_mut(); | |
v1.dummy = 2; | |
println!("mutate vec: {}", v1.dummy); | |
let mut v2 = vec_ref2.borrow_mut(); | |
v2.dummy = 3; | |
println!("mutate vec2: {}", v2.dummy); | |
} | |
} | |
fn main() { | |
componentcollection_simple(); | |
} |
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
#![feature(if_let)] | |
extern crate rustc; | |
use rustc::util::nodemap::FnvHashMap; | |
use std::any::{Any, AnyMutRefExt, AnyRefExt}; | |
use std::collections::hashmap; | |
use std::intrinsics::TypeId; | |
pub trait Component: Send {} | |
pub struct ComponentVec<T> where T: Component { | |
dummy: u8, | |
} | |
impl<T: Component> ComponentVec<T> { | |
pub fn new() -> ComponentVec<T> { | |
ComponentVec { | |
dummy: 42, | |
} | |
} | |
} | |
pub struct ComponentCollection { | |
/// The (type id -> component vec pointer) pairs storage. | |
comp_vecs: FnvHashMap<TypeId, Box<Any>>, | |
} | |
impl ComponentCollection { | |
/// Creates a new, empty `ComponentCollection`. | |
pub fn new() -> ComponentCollection { | |
ComponentCollection { | |
comp_vecs: FnvHashMap::new(), | |
} | |
} | |
/// Registers the component type `T` into this collection. | |
pub fn register<T>(&mut self) where T: Component { | |
if let hashmap::Vacant(entry) = self.comp_vecs.entry(TypeId::of::<T>()) { | |
let vec = box ComponentVec::<T>::new(); | |
entry.set(vec); | |
}; | |
} | |
/// Gets an immutable reference to the vector that stores `T`s in this collection. | |
pub fn vec_of<T>(&self) -> Option<&ComponentVec<T>> where T: Component { | |
self.comp_vecs.find(&TypeId::of::<T>()) | |
.map( |t| t.downcast_ref::<ComponentVec<T>>() | |
.expect("ComponentVec had the wrong type!") ) | |
} | |
/// Gets a mutable reference to the vector that stores `T`s in this collection. | |
pub fn vec_of_mut<T>(&mut self) -> Option<&mut ComponentVec<T>> where T: Component { | |
self.comp_vecs.find_mut(&TypeId::of::<T>()) | |
.map( |t| t.downcast_mut::<ComponentVec<T>>() | |
.expect("ComponentVec had the wrong type!") ) | |
} | |
} | |
struct MyComp; | |
impl Component for MyComp {} | |
struct MyComp2; | |
impl Component for MyComp2 {} | |
fn componentcollection_simple() { | |
let mut collection = ComponentCollection::new(); | |
collection.register::<MyComp>(); | |
{ | |
// The disadvantage here is that you cannot have two vectors from the | |
// collection mutably borrowed at the same time, and cannot register | |
// new types while borrowed (this may not matter for your use case). | |
// On the other hand, it's statically safe, while RefCells can fail | |
// at runtime. | |
let vec = collection.vec_of_mut::<MyComp>().unwrap(); | |
println!("Mutate one"); | |
vec.dummy = 1; | |
println!("mutate vec: {}", vec.dummy); | |
} | |
collection.register::<MyComp2>(); | |
{ | |
let vec = collection.vec_of_mut::<MyComp2>().unwrap(); | |
println!("\nMutate one"); | |
vec.dummy = 2; | |
println!("mutate vec2: {}", vec.dummy); | |
} | |
{ | |
let vec = collection.vec_of::<MyComp>().unwrap(); | |
let vec2 = collection.vec_of::<MyComp2>().unwrap(); | |
println!("\nBorrow both"); | |
println!("borrow vec: {}", vec.dummy); | |
println!("borrow vec2: {}", vec2.dummy); | |
} | |
} | |
fn main() { | |
componentcollection_simple(); | |
} |
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::collections::{Map}; | |
struct Table<T> { | |
table: T, | |
} | |
struct Row<A, G> { | |
action: A, | |
goto: G, | |
} | |
enum Action<S, R> { | |
Shift(S), | |
Reduce(R), | |
Done, | |
} | |
trait Rule<E, N> {} | |
impl<T, R, Actions, Gotos, State, Terminal, NonTerminal> Table<T> | |
where T: Map<State, Row<Actions, Gotos>>, | |
Actions: Map<Terminal, Action<State, R>>, | |
Gotos: Map<NonTerminal, State>, | |
R: Rule<Terminal, NonTerminal>, | |
{ | |
} | |
fn main() | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment