aec644565434075c6d81be1068dc71e165cd99a9
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, tuple_indexing)]
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
::collections
::hash_map
;
17 use std
::hash
::{Hash
, Hasher
, Writer
};
18 use std
::mem
::{transmute
, transmute_copy
};
19 use std
::raw
::TraitObject
;
21 pub use Entry
::{Vacant
, Occupied
};
29 impl Writer
for TypeIdState
{
31 fn write(&mut self, bytes
: &[u8]) {
32 // This expects to receive one and exactly one 64-bit value
33 debug_assert!(bytes
.len() == 8);
35 std
::ptr
::copy_nonoverlapping_memory(&mut self.value
,
42 impl Hasher
<TypeIdState
> for TypeIdHasher
{
43 fn hash
<Sized? T
: Hash
<TypeIdState
>>(&self, value
: &T
) -> u64 {
44 let mut state
= TypeIdState
{
47 value
.hash(&mut state
);
52 /// An extension of `AnyRefExt` allowing unchecked downcasting of trait objects to `&T`.
53 trait UncheckedAnyRefExt
<'a
> {
54 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
55 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
56 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
;
59 impl<'a
> UncheckedAnyRefExt
<'a
> for &'
a (Any
+ 'a
) {
61 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
{
62 // Get the raw representation of the trait object
63 let to
: TraitObject
= transmute_copy(&self);
65 // Extract the data pointer
70 /// An extension of `AnyMutRefExt` allowing unchecked downcasting of trait objects to `&mut T`.
71 trait UncheckedAnyMutRefExt
<'a
> {
72 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
73 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
74 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
;
77 impl<'a
> UncheckedAnyMutRefExt
<'a
> for &'a
mut (Any
+ 'a
) {
79 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
{
80 // Get the raw representation of the trait object
81 let to
: TraitObject
= transmute_copy(&self);
83 // Extract the data pointer
88 /// An extension of `BoxAny` allowing unchecked downcasting of trait objects to `Box<T>`.
89 trait UncheckedBoxAny
{
90 /// Returns the boxed value, assuming that it is of type `T`. This should only be called if you
91 /// are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
92 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
>;
95 impl UncheckedBoxAny
for Box
<Any
+ '
static> {
97 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
> {
98 // Get the raw representation of the trait object
99 let to
: TraitObject
= *transmute
::<&Box
<Any
>, &TraitObject
>(&self);
101 // Prevent destructor on self being run
104 // Extract the data pointer
109 /// A map containing zero or one values for any given type and allowing convenient,
110 /// type-safe access to those values.
113 /// # use anymap::AnyMap;
114 /// let mut data = AnyMap::new();
115 /// assert_eq!(data.get(), None::<&int>);
116 /// data.insert(42i);
117 /// assert_eq!(data.get(), Some(&42i));
118 /// data.remove::<int>();
119 /// assert_eq!(data.get::<int>(), None);
121 /// #[deriving(PartialEq, Show)]
126 /// assert_eq!(data.get::<Foo>(), None);
127 /// data.insert(Foo { str: "foo".to_string() });
128 /// assert_eq!(data.get(), Some(&Foo { str: "foo".to_string() }));
129 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
130 /// assert_eq!(data.get::<Foo>().unwrap().str.as_slice(), "foot");
133 /// Values containing non-static references are not permitted.
135 data
: HashMap
<TypeId
, Box
<Any
+ '
static>, TypeIdHasher
>,
139 /// Construct a new `AnyMap`.
140 pub fn new() -> AnyMap
{
142 data
: HashMap
::with_hasher(TypeIdHasher
),
148 /// Deprecated: Renamed to `get`.
149 #[deprecated = "Renamed to `get`"]
150 pub fn find
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
154 /// Deprecated: Renamed to `get_mut`.
155 #[deprecated = "Renamed to `get_mut`"]
156 pub fn find_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
160 /// Retrieve the value stored in the map for the type `T`, if it exists.
161 pub fn get
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
162 self.data
.get(&TypeId
::of
::<T
>())
163 .map(|any
| unsafe { any
.downcast_ref_unchecked
::<T
>() })
166 /// Retrieve a mutable reference to the value stored in the map for the type `T`, if it exists.
167 pub fn get_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
168 self.data
.get_mut(&TypeId
::of
::<T
>())
169 .map(|any
| unsafe { any
.downcast_mut_unchecked
::<T
>() })
172 /// Set the value contained in the map for the type `T`.
173 /// If there is a previous value stored, it will be returned.
174 pub fn insert
<T
: Any
+ '
static>(&mut self, value
: T
) -> Option
<T
> {
175 self.data
.insert(TypeId
::of
::<T
>(), box value
as Box
<Any
>)
176 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
179 /// Remove and return the value for the type `T` if it existed.
180 pub fn remove
<T
: Any
+ '
static>(&mut self) -> Option
<T
> {
181 self.data
.remove(&TypeId
::of
::<T
>())
182 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
185 /// Does a value of type `T` exist?
186 pub fn contains
<T
: Any
+ '
static>(&self) -> bool
{
187 self.data
.contains_key(&TypeId
::of
::<T
>())
190 /// Gets the given key's corresponding entry in the map for in-place manipulation
191 pub fn entry
<T
: Any
+ '
static>(&mut self) -> Entry
<T
> {
192 match self.data
.entry(TypeId
::of
::<T
>()) {
193 hash_map
::Occupied(e
) => Occupied(OccupiedEntry
{ entry
: e
}),
194 hash_map
::Vacant(e
) => Vacant(VacantEntry
{ entry
: e
}),
198 /// Returns the number of items in the collection.
199 pub fn len(&self) -> uint
{
203 /// Returns true if there are no items in the collection.
204 pub fn is_empty(&self) -> bool
{
208 /// Removes all items from the collection.
209 pub fn clear(&mut self) {
214 /// A view into a single occupied location in a HashMap
215 pub struct OccupiedEntry
<'a
, V
: 'a
> {
216 entry
: hash_map
::OccupiedEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
219 /// A view into a single empty location in a HashMap
220 pub struct VacantEntry
<'a
, V
: 'a
> {
221 entry
: hash_map
::VacantEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
224 /// A view into a single location in a map, which may be vacant or occupied
225 pub enum Entry
<'a
, V
: 'a
> {
226 /// An occupied Entry
227 Occupied(OccupiedEntry
<'a
, V
>),
229 Vacant(VacantEntry
<'a
, V
>),
232 impl<'a
, V
: '
static> OccupiedEntry
<'a
, V
> {
233 /// Gets a reference to the value in the entry
234 pub fn get(&self) -> &V
{
235 unsafe { self.entry
.get().downcast_ref_unchecked() }
238 /// Gets a mutable reference to the value in the entry
239 pub fn get_mut(&mut self) -> &mut V
{
240 unsafe { self.entry
.get_mut().downcast_mut_unchecked() }
243 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
244 /// with a lifetime bound to the map itself
245 pub fn into_mut(self) -> &'a
mut V
{
246 unsafe { self.entry
.into_mut().downcast_mut_unchecked() }
249 /// Sets the value of the entry, and returns the entry's old value
250 pub fn set(&mut self, value
: V
) -> V
{
251 unsafe { *self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_unchecked() }
254 /// Takes the value out of the entry, and returns it
255 pub fn take(self) -> V
{
256 unsafe { *self.entry
.take().downcast_unchecked() }
260 impl<'a
, V
: '
static> VacantEntry
<'a
, V
> {
261 /// Sets the value of the entry with the VacantEntry's key,
262 /// and returns a mutable reference to it
263 pub fn set(self, value
: V
) -> &'a
mut V
{
264 unsafe { self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_mut_unchecked() }
269 fn bench_insertion(b
: &mut ::test
::Bencher
) {
271 let mut data
= AnyMap
::new();
272 for _
in range(0u, 100) {
273 let _
= data
.insert(42i);
279 fn bench_get_missing(b
: &mut ::test
::Bencher
) {
281 let data
= AnyMap
::new();
282 for _
in range(0u, 100) {
283 assert_eq!(data
.get(), None
::<&int
>);
289 fn bench_get_present(b
: &mut ::test
::Bencher
) {
291 let mut data
= AnyMap
::new();
292 let _
= data
.insert(42i);
293 // These inner loops are a feeble attempt to drown the other factors.
294 for _
in range(0u, 100) {
295 assert_eq!(data
.get(), Some(&42i));
302 #[deriving(Show, PartialEq)] struct A(int);
303 #[deriving(Show, PartialEq)] struct B(int);
304 #[deriving(Show, PartialEq)] struct C(int);
305 #[deriving(Show, PartialEq)] struct D(int);
306 #[deriving(Show, PartialEq)] struct E(int);
307 #[deriving(Show, PartialEq)] struct F(int);
308 #[deriving(Show, PartialEq)] struct J(int);
310 let mut map
: AnyMap
= AnyMap
::new();
311 assert_eq!(map
.insert(A(10)), None
);
312 assert_eq!(map
.insert(B(20)), None
);
313 assert_eq!(map
.insert(C(30)), None
);
314 assert_eq!(map
.insert(D(40)), None
);
315 assert_eq!(map
.insert(E(50)), None
);
316 assert_eq!(map
.insert(F(60)), None
);
318 // Existing key (insert)
319 match map
.entry
::<A
>() {
320 Vacant(_
) => unreachable!(),
321 Occupied(mut view
) => {
322 assert_eq!(view
.get(), &A(10));
323 assert_eq!(view
.set(A(100)), A(10));
326 assert_eq!(map
.get
::<A
>().unwrap(), &A(100));
327 assert_eq!(map
.len(), 6);
330 // Existing key (update)
331 match map
.entry
::<B
>() {
332 Vacant(_
) => unreachable!(),
333 Occupied(mut view
) => {
334 let v
= view
.get_mut();
335 let new_v
= B(v
.0 * 10);
339 assert_eq!(map
.get().unwrap(), &B(200));
340 assert_eq!(map
.len(), 6);
343 // Existing key (take)
344 match map
.entry
::<C
>() {
345 Vacant(_
) => unreachable!(),
347 assert_eq!(view
.take(), C(30));
350 assert_eq!(map
.get
::<C
>(), None
);
351 assert_eq!(map
.len(), 5);
354 // Inexistent key (insert)
355 match map
.entry
::<J
>() {
356 Occupied(_
) => unreachable!(),
358 assert_eq!(*view
.set(J(1000)), J(1000));
361 assert_eq!(map
.get
::<J
>().unwrap(), &J(1000));
362 assert_eq!(map
.len(), 6);