1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
3 #![crate_id = "anymap#0.9"]
4 #![crate_type = "rlib"]
5 #![crate_type = "dylib"]
6 #![feature(default_type_params)]
7 #![warn(unnecessary_qualification, non_uppercase_statics,
8 variant_size_difference
, managed_heap_memory
, unnecessary_typecast
,
9 missing_doc
, unused_result
, deprecated_owned_vector
)]
15 use std
::intrinsics
::TypeId
;
16 use std
::collections
::HashMap
;
17 use std
::hash
::{Hash
, Hasher
, Writer
};
18 use std
::mem
::{transmute
, transmute_copy
};
19 use std
::raw
::TraitObject
;
27 impl Writer
for TypeIdState
{
29 fn write(&mut self, bytes
: &[u8]) {
30 // This expects to receive one and exactly one 64-bit value
31 debug_assert!(bytes
.len() == 8);
33 std
::ptr
::copy_nonoverlapping_memory(&mut self.value
,
40 impl Hasher
<TypeIdState
> for TypeIdHasher
{
41 fn hash
<T
: Hash
<TypeIdState
>>(&self, value
: &T
) -> u64 {
42 let mut state
= TypeIdState
{
45 value
.hash(&mut state
);
50 /// An extension of `AnyRefExt` allowing unchecked downcasting of trait objects to `&T`.
51 trait UncheckedAnyRefExt
<'a
> {
52 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
53 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
54 unsafe fn as_ref_unchecked
<T
: '
static>(self) -> &'a T
;
57 impl<'a
> UncheckedAnyRefExt
<'a
> for &'a Any
{
59 unsafe fn as_ref_unchecked
<T
: '
static>(self) -> &'a T
{
60 // Get the raw representation of the trait object
61 let to
: TraitObject
= transmute_copy(&self);
63 // Extract the data pointer
68 /// An extension of `AnyMutRefExt` allowing unchecked downcasting of trait objects to `&mut T`.
69 trait UncheckedAnyMutRefExt
<'a
> {
70 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
71 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
72 unsafe fn as_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
;
75 impl<'a
> UncheckedAnyMutRefExt
<'a
> for &'a
mut Any
{
77 unsafe fn as_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
{
78 // Get the raw representation of the trait object
79 let to
: TraitObject
= transmute_copy(&self);
81 // Extract the data pointer
86 /// A map containing zero or one values for any given type and allowing convenient,
87 /// type-safe access to those values.
90 /// # use anymap::AnyMap;
91 /// let mut data = AnyMap::new();
92 /// assert_eq!(data.find(), None::<&int>);
94 /// assert_eq!(data.find(), Some(&42i));
95 /// data.remove::<int>();
96 /// assert_eq!(data.find::<int>(), None);
98 /// #[deriving(PartialEq, Show)]
103 /// assert_eq!(data.find::<Foo>(), None);
104 /// data.insert(Foo { str: "foo".to_string() });
105 /// assert_eq!(data.find(), Some(&Foo { str: "foo".to_string() }));
106 /// data.find_mut::<Foo>().map(|foo| foo.str.push_char('t'));
107 /// assert_eq!(data.find::<Foo>().unwrap().str.as_slice(), "foot");
110 /// Values containing non-static references are not permitted.
112 data
: HashMap
<TypeId
, Box
<Any
>:'
static, TypeIdHasher
>,
116 /// Construct a new `AnyMap`.
117 pub fn new() -> AnyMap
{
119 data
: HashMap
::with_hasher(TypeIdHasher
),
125 /// Retrieve the value stored in the map for the type `T`, if it exists.
126 pub fn find
<'a
, T
: '
static>(&'a
self) -> Option
<&'a T
> {
127 self.data
.find(&TypeId
::of
::<T
>()).map(|any
| unsafe { any
.as_ref_unchecked
::<T
>() })
130 /// Retrieve a mutable reference to the value stored in the map for the type `T`, if it exists.
131 pub fn find_mut
<'a
, T
: '
static>(&'a
mut self) -> Option
<&'a
mut T
> {
132 self.data
.find_mut(&TypeId
::of
::<T
>()).map(|any
| unsafe { any
.as_mut_unchecked
::<T
>() })
135 /// Set the value contained in the map for the type `T`.
136 /// This will override any previous value stored.
137 pub fn insert
<T
: '
static>(&mut self, value
: T
) {
138 self.data
.insert(TypeId
::of
::<T
>(), box value
as Box
<Any
>);
141 /// Remove the value for the type `T` if it existed.
142 pub fn remove
<T
: '
static>(&mut self) {
143 self.data
.remove(&TypeId
::of
::<T
>());
148 fn bench_insertion(b
: &mut ::test
::Bencher
) {
150 let mut data
= AnyMap
::new();
151 for _
in range(0, 100) {
158 fn bench_find_missing(b
: &mut ::test
::Bencher
) {
160 let data
= AnyMap
::new();
161 for _
in range(0, 100) {
162 assert_eq!(data
.find(), None
::<&int
>);
168 fn bench_find_present(b
: &mut ::test
::Bencher
) {
170 let mut data
= AnyMap
::new();
172 // These inner loops are a feeble attempt to drown the other factors.
173 for _
in range(0, 100) {
174 assert_eq!(data
.find(), Some(&42i));