Skip to content

Instantly share code, notes, and snippets.

@pythonesque
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pythonesque/e4e1bea3c147e97dddec to your computer and use it in GitHub Desktop.
Save pythonesque/e4e1bea3c147e97dddec to your computer and use it in GitHub Desktop.
#![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();
}
#![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();
}
#![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();
}
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