Skip to content

Instantly share code, notes, and snippets.

@philopon
Last active May 30, 2019 17:13
Show Gist options
  • Save philopon/6ebbcc84630b9f7d54058dfae2e10929 to your computer and use it in GitHub Desktop.
Save philopon/6ebbcc84630b9f7d54058dfae2e10929 to your computer and use it in GitHub Desktop.
use std::mem::transmute;
use named_type::NamedType;
use named_type_derive::NamedType;
use std::collections::HashMap;
type Stored = Box<()>;
#[derive(Debug)]
pub struct AnyMap(HashMap<&'static str, Stored>);
impl AnyMap {
pub fn new() -> AnyMap {
AnyMap(HashMap::new())
}
pub fn insert<T: NamedType>(&mut self, value: T) -> Option<T> {
let stored = unsafe { transmute::<Box<T>, Stored>(Box::new(value)) };
self.0
.insert(T::type_name(), stored)
.map(|r| *(unsafe { transmute::<Stored, Box<T>>(r) }))
}
pub fn get<T: NamedType>(&self) -> Option<&T> {
self.0
.get(&T::type_name())
.map(|v| (unsafe { transmute::<&Stored, &Box<T>>(v) }).as_ref())
}
pub fn get_mut<T: NamedType>(&mut self) -> Option<&mut T> {
self.0
.get_mut(&T::type_name())
.map(|v| (unsafe { transmute::<&mut Stored, &mut Box<T>>(v) }).as_mut())
}
pub fn remove<T: NamedType>(&mut self) -> Option<T> {
self.0
.remove(&T::type_name())
.map(|v| *(unsafe { transmute::<Stored, Box<T>>(v) }))
}
}
#[derive(Debug, PartialEq, Eq, NamedType)]
pub struct A(String);
#[derive(Debug, PartialEq, Eq, NamedType)]
pub struct B(i64);
#[derive(Debug, PartialEq, NamedType)]
pub struct C(f64);
fn main() {
let mut m = AnyMap::new();
assert_eq!(m.insert(A("foo".to_owned())), None);
assert_eq!(m.insert(A("bar".to_owned())), Some(A("foo".to_owned())));
assert_eq!(m.insert(B(12)), None);
assert_eq!(m.get::<A>(), Some(&A("bar".to_owned())));
assert_eq!(m.get::<C>(), None);
assert_eq!(m.remove::<A>(), Some(A("bar".to_owned())));
assert_eq!(m.remove::<C>(), None);
if let Some(b) = m.get_mut::<B>() {
b.0 += 12;
}
assert_eq!(m.get::<B>(), Some(&B(24)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment