daa60449bda2f4271ea5b1b2b0bcc0fb1258de4a
1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
3 #![feature(default_type_params, tuple_indexing)]
4 #![warn(unused_qualifications, non_upper_case_globals,
5 variant_size_differences
, unused_typecasts
,
6 missing_docs
, unused_results
)]
12 use std
::intrinsics
::{forget
, TypeId
};
13 use std
::collections
::HashMap
;
14 use std
::collections
::hash_map
;
15 use std
::hash
::{Hash
, Hasher
, Writer
};
16 use std
::mem
::{transmute
, transmute_copy
};
17 use std
::raw
::TraitObject
;
19 pub use Entry
::{Vacant
, Occupied
};
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
<Sized? 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 downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
;
57 impl<'a
> UncheckedAnyRefExt
<'a
> for &'
a (Any
+ 'a
) {
59 unsafe fn downcast_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 downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
;
75 impl<'a
> UncheckedAnyMutRefExt
<'a
> for &'a
mut (Any
+ 'a
) {
77 unsafe fn downcast_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 /// An extension of `BoxAny` allowing unchecked downcasting of trait objects to `Box<T>`.
87 trait UncheckedBoxAny
{
88 /// Returns the boxed value, assuming that it is of type `T`. This should only be called if you
89 /// are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
90 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
>;
93 impl UncheckedBoxAny
for Box
<Any
+ '
static> {
95 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
> {
96 // Get the raw representation of the trait object
97 let to
: TraitObject
= *transmute
::<&Box
<Any
>, &TraitObject
>(&self);
99 // Prevent destructor on self being run
102 // Extract the data pointer
107 /// A map containing zero or one values for any given type and allowing convenient,
108 /// type-safe access to those values.
111 /// # use anymap::AnyMap;
112 /// let mut data = AnyMap::new();
113 /// assert_eq!(data.get(), None::<&int>);
114 /// data.insert(42i);
115 /// assert_eq!(data.get(), Some(&42i));
116 /// data.remove::<int>();
117 /// assert_eq!(data.get::<int>(), None);
119 /// #[deriving(PartialEq, Show)]
124 /// assert_eq!(data.get::<Foo>(), None);
125 /// data.insert(Foo { str: "foo".to_string() });
126 /// assert_eq!(data.get(), Some(&Foo { str: "foo".to_string() }));
127 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
128 /// assert_eq!(data.get::<Foo>().unwrap().str.as_slice(), "foot");
131 /// Values containing non-static references are not permitted.
133 data
: HashMap
<TypeId
, Box
<Any
+ '
static>, TypeIdHasher
>,
137 /// Construct a new `AnyMap`.
138 pub fn new() -> AnyMap
{
140 data
: HashMap
::with_hasher(TypeIdHasher
),
146 /// Deprecated: Renamed to `get`.
147 #[deprecated = "Renamed to `get`"]
148 pub fn find
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
152 /// Deprecated: Renamed to `get_mut`.
153 #[deprecated = "Renamed to `get_mut`"]
154 pub fn find_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
158 /// Retrieve the value stored in the map for the type `T`, if it exists.
159 pub fn get
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
160 self.data
.get(&TypeId
::of
::<T
>())
161 .map(|any
| unsafe { any
.downcast_ref_unchecked
::<T
>() })
164 /// Retrieve a mutable reference to the value stored in the map for the type `T`, if it exists.
165 pub fn get_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
166 self.data
.get_mut(&TypeId
::of
::<T
>())
167 .map(|any
| unsafe { any
.downcast_mut_unchecked
::<T
>() })
170 /// Set the value contained in the map for the type `T`.
171 /// If there is a previous value stored, it will be returned.
172 pub fn insert
<T
: Any
+ '
static>(&mut self, value
: T
) -> Option
<T
> {
173 self.data
.insert(TypeId
::of
::<T
>(), box value
as Box
<Any
>)
174 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
177 /// Remove and return the value for the type `T` if it existed.
178 pub fn remove
<T
: Any
+ '
static>(&mut self) -> Option
<T
> {
179 self.data
.remove(&TypeId
::of
::<T
>())
180 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
183 /// Does a value of type `T` exist?
184 pub fn contains
<T
: Any
+ '
static>(&self) -> bool
{
185 self.data
.contains_key(&TypeId
::of
::<T
>())
188 /// Gets the given key's corresponding entry in the map for in-place manipulation
189 pub fn entry
<T
: Any
+ '
static>(&mut self) -> Entry
<T
> {
190 match self.data
.entry(TypeId
::of
::<T
>()) {
191 hash_map
::Occupied(e
) => Occupied(OccupiedEntry
{ entry
: e
}),
192 hash_map
::Vacant(e
) => Vacant(VacantEntry
{ entry
: e
}),
196 /// Returns the number of items in the collection.
197 pub fn len(&self) -> uint
{
201 /// Returns true if there are no items in the collection.
202 pub fn is_empty(&self) -> bool
{
206 /// Removes all items from the collection.
207 pub fn clear(&mut self) {
212 /// A view into a single occupied location in a HashMap
213 pub struct OccupiedEntry
<'a
, V
: 'a
> {
214 entry
: hash_map
::OccupiedEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
217 /// A view into a single empty location in a HashMap
218 pub struct VacantEntry
<'a
, V
: 'a
> {
219 entry
: hash_map
::VacantEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
222 /// A view into a single location in a map, which may be vacant or occupied
223 pub enum Entry
<'a
, V
: 'a
> {
224 /// An occupied Entry
225 Occupied(OccupiedEntry
<'a
, V
>),
227 Vacant(VacantEntry
<'a
, V
>),
230 impl<'a
, V
: '
static> OccupiedEntry
<'a
, V
> {
231 /// Gets a reference to the value in the entry
232 pub fn get(&self) -> &V
{
233 unsafe { self.entry
.get().downcast_ref_unchecked() }
236 /// Gets a mutable reference to the value in the entry
237 pub fn get_mut(&mut self) -> &mut V
{
238 unsafe { self.entry
.get_mut().downcast_mut_unchecked() }
241 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
242 /// with a lifetime bound to the map itself
243 pub fn into_mut(self) -> &'a
mut V
{
244 unsafe { self.entry
.into_mut().downcast_mut_unchecked() }
247 /// Sets the value of the entry, and returns the entry's old value
248 pub fn set(&mut self, value
: V
) -> V
{
249 unsafe { *self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_unchecked() }
252 /// Takes the value out of the entry, and returns it
253 pub fn take(self) -> V
{
254 unsafe { *self.entry
.take().downcast_unchecked() }
258 impl<'a
, V
: '
static> VacantEntry
<'a
, V
> {
259 /// Sets the value of the entry with the VacantEntry's key,
260 /// and returns a mutable reference to it
261 pub fn set(self, value
: V
) -> &'a
mut V
{
262 unsafe { self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_mut_unchecked() }
267 fn bench_insertion(b
: &mut ::test
::Bencher
) {
269 let mut data
= AnyMap
::new();
270 for _
in range(0u, 100) {
271 let _
= data
.insert(42i);
277 fn bench_get_missing(b
: &mut ::test
::Bencher
) {
279 let data
= AnyMap
::new();
280 for _
in range(0u, 100) {
281 assert_eq!(data
.get(), None
::<&int
>);
287 fn bench_get_present(b
: &mut ::test
::Bencher
) {
289 let mut data
= AnyMap
::new();
290 let _
= data
.insert(42i);
291 // These inner loops are a feeble attempt to drown the other factors.
292 for _
in range(0u, 100) {
293 assert_eq!(data
.get(), Some(&42i));
300 #[deriving(Show, PartialEq)] struct A(int);
301 #[deriving(Show, PartialEq)] struct B(int);
302 #[deriving(Show, PartialEq)] struct C(int);
303 #[deriving(Show, PartialEq)] struct D(int);
304 #[deriving(Show, PartialEq)] struct E(int);
305 #[deriving(Show, PartialEq)] struct F(int);
306 #[deriving(Show, PartialEq)] struct J(int);
308 let mut map
: AnyMap
= AnyMap
::new();
309 assert_eq!(map
.insert(A(10)), None
);
310 assert_eq!(map
.insert(B(20)), None
);
311 assert_eq!(map
.insert(C(30)), None
);
312 assert_eq!(map
.insert(D(40)), None
);
313 assert_eq!(map
.insert(E(50)), None
);
314 assert_eq!(map
.insert(F(60)), None
);
316 // Existing key (insert)
317 match map
.entry
::<A
>() {
318 Vacant(_
) => unreachable!(),
319 Occupied(mut view
) => {
320 assert_eq!(view
.get(), &A(10));
321 assert_eq!(view
.set(A(100)), A(10));
324 assert_eq!(map
.get
::<A
>().unwrap(), &A(100));
325 assert_eq!(map
.len(), 6);
328 // Existing key (update)
329 match map
.entry
::<B
>() {
330 Vacant(_
) => unreachable!(),
331 Occupied(mut view
) => {
332 let v
= view
.get_mut();
333 let new_v
= B(v
.0 * 10);
337 assert_eq!(map
.get().unwrap(), &B(200));
338 assert_eq!(map
.len(), 6);
341 // Existing key (take)
342 match map
.entry
::<C
>() {
343 Vacant(_
) => unreachable!(),
345 assert_eq!(view
.take(), C(30));
348 assert_eq!(map
.get
::<C
>(), None
);
349 assert_eq!(map
.len(), 5);
352 // Inexistent key (insert)
353 match map
.entry
::<J
>() {
354 Occupied(_
) => unreachable!(),
356 assert_eq!(*view
.set(J(1000)), J(1000));
359 assert_eq!(map
.get
::<J
>().unwrap(), &J(1000));
360 assert_eq!(map
.len(), 6);