16644bf1f8fd56023e54afa5c12741f145fb0b12
1 //! This crate provides the `AnyMap` type, a safe and convenient store for one value of each type.
3 #![feature(default_type_params)]
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
;
17 use std
::raw
::TraitObject
;
25 impl Writer
for TypeIdState
{
27 fn write(&mut self, bytes
: &[u8]) {
28 // This expects to receive one and exactly one 64-bit value
29 debug_assert!(bytes
.len() == 8);
31 std
::ptr
::copy_nonoverlapping_memory(&mut self.value
,
38 impl Hasher
<TypeIdState
> for TypeIdHasher
{
39 fn hash
<Sized? T
: Hash
<TypeIdState
>>(&self, value
: &T
) -> u64 {
40 let mut state
= TypeIdState
{
43 value
.hash(&mut state
);
48 /// An extension of `AnyRefExt` allowing unchecked downcasting of trait objects to `&T`.
49 trait UncheckedAnyRefExt
<'a
> {
50 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
51 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
52 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
;
55 impl<'a
> UncheckedAnyRefExt
<'a
> for &'a Any
{
57 unsafe fn downcast_ref_unchecked
<T
: '
static>(self) -> &'a T
{
58 // Get the raw representation of the trait object
59 let to
: TraitObject
= transmute(self);
61 // Extract the data pointer
66 /// An extension of `AnyMutRefExt` allowing unchecked downcasting of trait objects to `&mut T`.
67 trait UncheckedAnyMutRefExt
<'a
> {
68 /// Returns a reference to the boxed value, assuming that it is of type `T`. This should only be
69 /// called if you are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
70 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
;
73 impl<'a
> UncheckedAnyMutRefExt
<'a
> for &'a
mut Any
{
75 unsafe fn downcast_mut_unchecked
<T
: '
static>(self) -> &'a
mut T
{
76 // Get the raw representation of the trait object
77 let to
: TraitObject
= transmute(self);
79 // Extract the data pointer
84 /// An extension of `BoxAny` allowing unchecked downcasting of trait objects to `Box<T>`.
85 trait UncheckedBoxAny
{
86 /// Returns the boxed value, assuming that it is of type `T`. This should only be called if you
87 /// are ABSOLUTELY CERTAIN of `T` as you will get really wacky output if it’s not.
88 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
>;
91 impl UncheckedBoxAny
for Box
<Any
+ '
static> {
93 unsafe fn downcast_unchecked
<T
: '
static>(self) -> Box
<T
> {
94 // Get the raw representation of the trait object
95 let to
: TraitObject
= *transmute
::<&Box
<Any
>, &TraitObject
>(&self);
97 // Prevent destructor on self being run
100 // Extract the data pointer
105 /// A map containing zero or one values for any given type and allowing convenient,
106 /// type-safe access to those values.
109 /// # use anymap::AnyMap;
110 /// let mut data = AnyMap::new();
111 /// assert_eq!(data.get(), None::<&int>);
112 /// data.insert(42i);
113 /// assert_eq!(data.get(), Some(&42i));
114 /// data.remove::<int>();
115 /// assert_eq!(data.get::<int>(), None);
117 /// #[derive(PartialEq, Show)]
122 /// assert_eq!(data.get::<Foo>(), None);
123 /// data.insert(Foo { str: "foo".to_string() });
124 /// assert_eq!(data.get(), Some(&Foo { str: "foo".to_string() }));
125 /// data.get_mut::<Foo>().map(|foo| foo.str.push('t'));
126 /// assert_eq!(data.get::<Foo>().unwrap().str.as_slice(), "foot");
129 /// Values containing non-static references are not permitted.
131 data
: HashMap
<TypeId
, Box
<Any
+ '
static>, TypeIdHasher
>,
135 /// Construct a new `AnyMap`.
136 pub fn new() -> AnyMap
{
138 data
: HashMap
::with_hasher(TypeIdHasher
),
144 /// Deprecated: Renamed to `get`.
145 #[deprecated = "Renamed to `get`"]
146 pub fn find
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
150 /// Deprecated: Renamed to `get_mut`.
151 #[deprecated = "Renamed to `get_mut`"]
152 pub fn find_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
156 /// Retrieve the value stored in the map for the type `T`, if it exists.
157 pub fn get
<T
: Any
+ '
static>(&self) -> Option
<&T
> {
158 self.data
.get(&TypeId
::of
::<T
>())
159 .map(|any
| unsafe { any
.downcast_ref_unchecked
::<T
>() })
162 /// Retrieve a mutable reference to the value stored in the map for the type `T`, if it exists.
163 pub fn get_mut
<T
: Any
+ '
static>(&mut self) -> Option
<&mut T
> {
164 self.data
.get_mut(&TypeId
::of
::<T
>())
165 .map(|any
| unsafe { any
.downcast_mut_unchecked
::<T
>() })
168 /// Set the value contained in the map for the type `T`.
169 /// If there is a previous value stored, it will be returned.
170 pub fn insert
<T
: Any
+ '
static>(&mut self, value
: T
) -> Option
<T
> {
171 self.data
.insert(TypeId
::of
::<T
>(), box value
as Box
<Any
>)
172 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
175 /// Remove and return the value for the type `T` if it existed.
176 pub fn remove
<T
: Any
+ '
static>(&mut self) -> Option
<T
> {
177 self.data
.remove(&TypeId
::of
::<T
>())
178 .map(|any
| *unsafe { any
.downcast_unchecked
::<T
>() })
181 /// Does a value of type `T` exist?
182 pub fn contains
<T
: Any
+ '
static>(&self) -> bool
{
183 self.data
.contains_key(&TypeId
::of
::<T
>())
186 /// Gets the given key's corresponding entry in the map for in-place manipulation
187 pub fn entry
<T
: Any
+ '
static>(&mut self) -> Entry
<T
> {
188 match self.data
.entry(TypeId
::of
::<T
>()) {
189 hash_map
::Entry
::Occupied(e
) => Entry
::Occupied(OccupiedEntry
{ entry
: e
}),
190 hash_map
::Entry
::Vacant(e
) => Entry
::Vacant(VacantEntry
{ entry
: e
}),
194 /// Returns the number of items in the collection.
195 pub fn len(&self) -> uint
{
199 /// Returns true if there are no items in the collection.
200 pub fn is_empty(&self) -> bool
{
204 /// Removes all items from the collection.
205 pub fn clear(&mut self) {
210 /// A view into a single occupied location in an AnyMap
211 pub struct OccupiedEntry
<'a
, V
: 'a
> {
212 entry
: hash_map
::OccupiedEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
215 /// A view into a single empty location in an AnyMap
216 pub struct VacantEntry
<'a
, V
: 'a
> {
217 entry
: hash_map
::VacantEntry
<'a
, TypeId
, Box
<Any
+ '
static>>,
220 /// A view into a single location in a map, which may be vacant or occupied
221 pub enum Entry
<'a
, V
: 'a
> {
222 /// An occupied Entry
223 Occupied(OccupiedEntry
<'a
, V
>),
225 Vacant(VacantEntry
<'a
, V
>),
228 impl<'a
, V
: '
static> OccupiedEntry
<'a
, V
> {
229 /// Gets a reference to the value in the entry
230 pub fn get(&self) -> &V
{
231 unsafe { self.entry
.get().downcast_ref_unchecked() }
234 /// Gets a mutable reference to the value in the entry
235 pub fn get_mut(&mut self) -> &mut V
{
236 unsafe { self.entry
.get_mut().downcast_mut_unchecked() }
239 /// Converts the OccupiedEntry into a mutable reference to the value in the entry
240 /// with a lifetime bound to the map itself
241 pub fn into_mut(self) -> &'a
mut V
{
242 unsafe { self.entry
.into_mut().downcast_mut_unchecked() }
245 /// Sets the value of the entry, and returns the entry's old value
246 pub fn set(&mut self, value
: V
) -> V
{
247 unsafe { *self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_unchecked() }
250 /// Takes the value out of the entry, and returns it
251 pub fn take(self) -> V
{
252 unsafe { *self.entry
.take().downcast_unchecked() }
256 impl<'a
, V
: '
static> VacantEntry
<'a
, V
> {
257 /// Sets the value of the entry with the VacantEntry's key,
258 /// and returns a mutable reference to it
259 pub fn set(self, value
: V
) -> &'a
mut V
{
260 unsafe { self.entry
.set(box value
as Box
<Any
+ '
static>).downcast_mut_unchecked() }
265 fn bench_insertion(b
: &mut ::test
::Bencher
) {
267 let mut data
= AnyMap
::new();
268 for _
in range(0u, 100) {
269 let _
= data
.insert(42i);
275 fn bench_get_missing(b
: &mut ::test
::Bencher
) {
277 let data
= AnyMap
::new();
278 for _
in range(0u, 100) {
279 assert_eq!(data
.get(), None
::<&int
>);
285 fn bench_get_present(b
: &mut ::test
::Bencher
) {
287 let mut data
= AnyMap
::new();
288 let _
= data
.insert(42i);
289 // These inner loops are a feeble attempt to drown the other factors.
290 for _
in range(0u, 100) {
291 assert_eq!(data
.get(), Some(&42i));
298 #[derive(Show, PartialEq)] struct A(int);
299 #[derive(Show, PartialEq)] struct B(int);
300 #[derive(Show, PartialEq)] struct C(int);
301 #[derive(Show, PartialEq)] struct D(int);
302 #[derive(Show, PartialEq)] struct E(int);
303 #[derive(Show, PartialEq)] struct F(int);
304 #[derive(Show, PartialEq)] struct J(int);
306 let mut map
: AnyMap
= AnyMap
::new();
307 assert_eq!(map
.insert(A(10)), None
);
308 assert_eq!(map
.insert(B(20)), None
);
309 assert_eq!(map
.insert(C(30)), None
);
310 assert_eq!(map
.insert(D(40)), None
);
311 assert_eq!(map
.insert(E(50)), None
);
312 assert_eq!(map
.insert(F(60)), None
);
314 // Existing key (insert)
315 match map
.entry
::<A
>() {
316 Entry
::Vacant(_
) => unreachable!(),
317 Entry
::Occupied(mut view
) => {
318 assert_eq!(view
.get(), &A(10));
319 assert_eq!(view
.set(A(100)), A(10));
322 assert_eq!(map
.get
::<A
>().unwrap(), &A(100));
323 assert_eq!(map
.len(), 6);
326 // Existing key (update)
327 match map
.entry
::<B
>() {
328 Entry
::Vacant(_
) => unreachable!(),
329 Entry
::Occupied(mut view
) => {
330 let v
= view
.get_mut();
331 let new_v
= B(v
.0 * 10);
335 assert_eq!(map
.get().unwrap(), &B(200));
336 assert_eq!(map
.len(), 6);
339 // Existing key (take)
340 match map
.entry
::<C
>() {
341 Entry
::Vacant(_
) => unreachable!(),
342 Entry
::Occupied(view
) => {
343 assert_eq!(view
.take(), C(30));
346 assert_eq!(map
.get
::<C
>(), None
);
347 assert_eq!(map
.len(), 5);
350 // Inexistent key (insert)
351 match map
.entry
::<J
>() {
352 Entry
::Occupied(_
) => unreachable!(),
353 Entry
::Vacant(view
) => {
354 assert_eq!(*view
.set(J(1000)), J(1000));
357 assert_eq!(map
.get
::<J
>().unwrap(), &J(1000));
358 assert_eq!(map
.len(), 6);