1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
3 #![crate_name = "anymap"]
5 #![feature(default_type_params)]
6 #![warn(unused_qualifications, non_upper_case_globals,
7 variant_size_differences
, unused_typecasts
,
8 missing_docs
, unused_results
)]
14 use std
::intrinsics
::{forget
, TypeId
};
15 use std
::collections
::HashMap
;
16 use std
::hash
::{Hash
, Hasher
, Writer
};
17 use std
::mem
::{transmute
, transmute_copy
};
18 use std
::raw
::TraitObject
;
26 impl Writer
for TypeIdState
{
28 fn write(&mut self, bytes
: &[u8]) {
29 // This expects to receive one and exactly one 64-bit value
30 debug_assert!(bytes
.len() == 8);
32 std
::ptr
::copy_nonoverlapping_memory(&mut self.value
,
39 impl Hasher
<TypeIdState
> for TypeIdHasher
{
40 fn hash
<Sized? T
: Hash
<TypeIdState
>>(&self, value
: &T
) -> u64 {
41 let mut state
= TypeIdState
{
44 value
.hash(&mut state
);
49 /// An extension of `AnyRefExt` allowing unchecked downcasting of trait objects to `&T`.
50 trait UncheckedAnyRefExt
<'a
> {
51 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
52 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
53 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
;
56 impl<'a
> UncheckedAnyRefExt
<'a
> for &'a Any
+ 'a
{
58 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
{
59 // Get the raw representation of the trait object
60 let to
: TraitObject
= transmute_copy(&self);
62 // Extract the data pointer
67 /// An extension of `AnyMutRefExt` allowing unchecked downcasting of trait objects to `&mut T`.
68 trait UncheckedAnyMutRefExt
<'a
> {
69 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
70 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
71 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
;
74 impl<'a
> UncheckedAnyMutRefExt
<'a
> for &'a
mut Any
+ 'a
{
76 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
{
77 // Get the raw representation of the trait object
78 let to
: TraitObject
= transmute_copy(&self);
80 // Extract the data pointer
85 /// An extension of `BoxAny` allowing unchecked downcasting of trait objects to `Box<T>`.
86 trait UncheckedBoxAny
{
87 /// Returns the boxed value, assuming that it is of type `T`. This should only be called if you
88 /// are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
89 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
>;
92 impl UncheckedBoxAny
for Box
<Any
+ '
static> {
94 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
> {
95 // Get the raw representation of the trait object
96 let to
: TraitObject
= *transmute
::<&Box
<Any
>, &TraitObject
>(&self);
98 // Prevent destructor on self being run
101 // Extract the data pointer
106 /// A map containing zero or one values for any given type and allowing convenient,
107 /// type-safe access to those values.
110 /// # use anymap::AnyMap;
111 /// let mut data = AnyMap::new();
112 /// assert_eq!(data.get(), None::<&int>);
113 /// data.insert(42i);
114 /// assert_eq!(data.get(), Some(&42i));
115 /// data.remove::<int>();
116 /// assert_eq!(data.get::<int>(), None);
118 /// #[deriving(PartialEq, Show)]
123 /// assert_eq!(data.get::<Foo>(), None);
124 /// data.insert(Foo { str: "foo".to_string() });
125 /// assert_eq!(data.get(), Some(&Foo { str: "foo".to_string() }));
126 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
127 /// assert_eq!(data.get::<Foo>().unwrap().str.as_slice(), "foot");
130 /// Values containing non-static references are not permitted.
132 data
: HashMap
<TypeId
, Box
<Any
+ '
static>, TypeIdHasher
>,
136 /// Construct a new `AnyMap`.
137 pub fn new() -> AnyMap
{
139 data
: HashMap
::with_hasher(TypeIdHasher
),
145 /// Deprecated: Renamed to `get`.
146 #[deprecated = "Renamed to `get`"]
147 pub fn find
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
151 /// Deprecated: Renamed to `get_mut`.
152 #[deprecated = "Renamed to `get_mut`"]
153 pub fn find_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
157 /// Retrieve the value stored in the map for the type `T`, if it exists.
158 pub fn get
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
159 self.data
.get(&TypeId
::of
::<T
>())
160 .map(|any
| unsafe { any
.downcast_ref_unchecked
::<T
>() })
163 /// Retrieve a mutable reference to the value stored in the map for the type `T`, if it exists.
164 pub fn get_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
165 self.data
.get_mut(&TypeId
::of
::<T
>())
166 .map(|any
| unsafe { any
.downcast_mut_unchecked
::<T
>() })
169 /// Set the value contained in the map for the type `T`.
170 /// If there is a previous value stored, it will be returned.
171 pub fn insert
<T
: Any
+ '
static>(&mut self, value
: T
) -> Option
<T
> {
172 self.data
.insert(TypeId
::of
::<T
>(), box value
as Box
<Any
>)
173 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
176 /// Remove and return the value for the type `T` if it existed.
177 pub fn remove
<T
: Any
+ '
static>(&mut self) -> Option
<T
> {
178 self.data
.remove(&TypeId
::of
::<T
>())
179 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
182 /// Does a value of type `T` exist?
183 pub fn contains
<T
: Any
+ '
static>(&self) -> bool
{
184 self.data
.contains_key(&TypeId
::of
::<T
>())
187 /// Returns the number of items in the collection.
188 pub fn len(&self) -> uint
{
192 /// Returns true if there are no items in the collection.
193 pub fn is_empty(&self) -> bool
{
197 /// Removes all items from the collection.
198 pub fn clear(&mut self) {
204 fn bench_insertion(b
: &mut ::test
::Bencher
) {
206 let mut data
= AnyMap
::new();
207 for _
in range(0u, 100) {
208 let _
= data
.insert(42i);
214 fn bench_get_missing(b
: &mut ::test
::Bencher
) {
216 let data
= AnyMap
::new();
217 for _
in range(0u, 100) {
218 assert_eq!(data
.get(), None
::<&int
>);
224 fn bench_get_present(b
: &mut ::test
::Bencher
) {
226 let mut data
= AnyMap
::new();
227 let _
= data
.insert(42i);
228 // These inner loops are a feeble attempt to drown the other factors.
229 for _
in range(0u, 100) {
230 assert_eq!(data
.get(), Some(&42i));