]> git.lizzy.rs Git - rust.git/blob - src/libstd/any.rs
auto merge of #10977 : brson/rust/androidtest, r=brson
[rust.git] / src / libstd / any.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! This module implements the `Any` trait, which enables dynamic typing
12 //! of any type, through runtime reflection.
13 //!
14 //! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object.
15 //! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
16 //! contained value is of a given type, and to get a reference to the inner value as a type. As
17 //! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
18 //! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object.  See the
19 //! extension traits (`*Ext`) for the full details.
20
21 use cast::transmute;
22 use option::{Option, Some, None};
23 use to_str::ToStr;
24 use unstable::intrinsics;
25 use util::Void;
26 use unstable::intrinsics::TypeId;
27
28 ///////////////////////////////////////////////////////////////////////////////
29 // Any trait
30 ///////////////////////////////////////////////////////////////////////////////
31
32 /// The `Any` trait is implemented by all types, and can be used as a trait object
33 /// for dynamic typing
34 pub trait Any {
35     /// Get the `TypeId` of `self`
36     fn get_type_id(&self) -> TypeId;
37
38     /// Get a void pointer to `self`
39     fn as_void_ptr(&self) -> *Void;
40
41     /// Get a mutable void pointer to `self`
42     fn as_mut_void_ptr(&mut self) -> *mut Void;
43 }
44
45 impl<T: 'static> Any for T {
46     /// Get the `TypeId` of `self`
47     fn get_type_id(&self) -> TypeId {
48         TypeId::of::<T>()
49     }
50
51     /// Get a void pointer to `self`
52     fn as_void_ptr(&self) -> *Void {
53         self as *T as *Void
54     }
55
56     /// Get a mutable void pointer to `self`
57     fn as_mut_void_ptr(&mut self) -> *mut Void {
58         self as *mut T as *mut Void
59     }
60 }
61
62 ///////////////////////////////////////////////////////////////////////////////
63 // Extension methods for Any trait objects.
64 // Implemented as three extension traits so that generics work.
65 ///////////////////////////////////////////////////////////////////////////////
66
67 /// Extension methods for a referenced `Any` trait object
68 pub trait AnyRefExt<'a> {
69     /// Returns true if the boxed type is the same as `T`
70     fn is<T: 'static>(self) -> bool;
71
72     /// Returns some reference to the boxed value if it is of type `T`, or
73     /// `None` if it isn't.
74     fn as_ref<T: 'static>(self) -> Option<&'a T>;
75 }
76
77 impl<'a> AnyRefExt<'a> for &'a Any {
78     #[inline]
79     fn is<T: 'static>(self) -> bool {
80         // Get TypeId of the type this function is instantiated with
81         let t = TypeId::of::<T>();
82
83         // Get TypeId of the type in the trait object
84         let boxed = self.get_type_id();
85
86         // Compare both TypeIds on equality
87         t == boxed
88     }
89
90     #[inline]
91     fn as_ref<T: 'static>(self) -> Option<&'a T> {
92         if self.is::<T>() {
93             Some(unsafe { transmute(self.as_void_ptr()) })
94         } else {
95             None
96         }
97     }
98 }
99
100 /// Extension methods for a mutable referenced `Any` trait object
101 pub trait AnyMutRefExt<'a> {
102     /// Returns some mutable reference to the boxed value if it is of type `T`, or
103     /// `None` if it isn't.
104     fn as_mut<T: 'static>(self) -> Option<&'a mut T>;
105 }
106
107 impl<'a> AnyMutRefExt<'a> for &'a mut Any {
108     #[inline]
109     fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
110         if self.is::<T>() {
111             Some(unsafe { transmute(self.as_mut_void_ptr()) })
112         } else {
113             None
114         }
115     }
116 }
117
118 /// Extension methods for a owning `Any` trait object
119 pub trait AnyOwnExt {
120     /// Returns the boxed value if it is of type `T`, or
121     /// `None` if it isn't.
122     fn move<T: 'static>(self) -> Option<~T>;
123 }
124
125 impl AnyOwnExt for ~Any {
126     #[inline]
127     fn move<T: 'static>(self) -> Option<~T> {
128         if self.is::<T>() {
129             unsafe {
130                 // Extract the pointer to the boxed value, temporary alias with self
131                 let ptr: ~T = transmute(self.as_void_ptr());
132
133                 // Prevent destructor on self being run
134                 intrinsics::forget(self);
135
136                 Some(ptr)
137             }
138         } else {
139             None
140         }
141     }
142 }
143
144 ///////////////////////////////////////////////////////////////////////////////
145 // Trait implementations
146 ///////////////////////////////////////////////////////////////////////////////
147
148 impl ToStr for ~Any {
149     fn to_str(&self) -> ~str { ~"~Any" }
150 }
151
152 impl<'a> ToStr for &'a Any {
153     fn to_str(&self) -> ~str { ~"&Any" }
154 }
155
156 #[cfg(test)]
157 mod tests {
158     use super::*;
159     use super::AnyRefExt;
160     use option::{Some, None};
161
162     #[deriving(Eq)]
163     struct Test;
164
165     static TEST: &'static str = "Test";
166
167     #[test]
168     fn any_as_void_ptr() {
169         let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
170         let a_r: &Any = a;
171         let b_r: &Any = b;
172         let c_r: &Any = c;
173
174         assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
175         assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
176         assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
177
178         let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
179         let a_r: &Any = a;
180         let b_r: &Any = b;
181         let c_r: &Any = c;
182
183         assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
184         assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
185         assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
186
187         let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
188         let a_r: &Any = a;
189         let b_r: &Any = b;
190         let c_r: &Any = c;
191
192         assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
193         assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
194         assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
195
196         let mut x = Test;
197         let mut y: &'static str = "Test";
198         let (a, b, c) = (&mut 5u as &mut Any,
199                          &mut y as &mut Any,
200                          &mut x as &mut Any);
201         let a_r: &Any = a;
202         let b_r: &Any = b;
203         let c_r: &Any = c;
204
205         assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
206         assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
207         assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
208
209         let (a, b, c) = (5u, "hello", Test);
210         let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);
211
212         assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
213         assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
214         assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
215     }
216
217     #[test]
218     fn any_as_mut_void_ptr() {
219         let y: &'static str = "Test";
220         let mut a = ~5u as ~Any;
221         let mut b = ~y as ~Any;
222         let mut c = ~Test as ~Any;
223
224         let a_ptr = a.as_mut_void_ptr();
225         let b_ptr = b.as_mut_void_ptr();
226         let c_ptr = c.as_mut_void_ptr();
227
228         let a_r: &mut Any = a;
229         let b_r: &mut Any = b;
230         let c_r: &mut Any = c;
231
232         assert_eq!(a_ptr, a_r.as_mut_void_ptr());
233         assert_eq!(b_ptr, b_r.as_mut_void_ptr());
234         assert_eq!(c_ptr, c_r.as_mut_void_ptr());
235
236         let mut x = Test;
237         let mut y: &'static str = "Test";
238         let a = &mut 5u as &mut Any;
239         let b = &mut y as &mut Any;
240         let c = &mut x as &mut Any;
241
242         let a_ptr = a.as_mut_void_ptr();
243         let b_ptr = b.as_mut_void_ptr();
244         let c_ptr = c.as_mut_void_ptr();
245
246         let a_r: &mut Any = a;
247         let b_r: &mut Any = b;
248         let c_r: &mut Any = c;
249
250         assert_eq!(a_ptr, a_r.as_mut_void_ptr());
251         assert_eq!(b_ptr, b_r.as_mut_void_ptr());
252         assert_eq!(c_ptr, c_r.as_mut_void_ptr());
253
254         let y: &'static str = "Test";
255         let mut a = 5u;
256         let mut b = y;
257         let mut c = Test;
258
259         let a_ptr = a.as_mut_void_ptr();
260         let b_ptr = b.as_mut_void_ptr();
261         let c_ptr = c.as_mut_void_ptr();
262
263         let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);
264
265         assert_eq!(a_ptr, a_r.as_mut_void_ptr());
266         assert_eq!(b_ptr, b_r.as_mut_void_ptr());
267         assert_eq!(c_ptr, c_r.as_mut_void_ptr());
268     }
269
270     #[test]
271     fn any_referenced() {
272         let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
273
274         assert!(a.is::<uint>());
275         assert!(!b.is::<uint>());
276         assert!(!c.is::<uint>());
277
278         assert!(!a.is::<&'static str>());
279         assert!(b.is::<&'static str>());
280         assert!(!c.is::<&'static str>());
281
282         assert!(!a.is::<Test>());
283         assert!(!b.is::<Test>());
284         assert!(c.is::<Test>());
285     }
286
287     #[test]
288     fn any_owning() {
289         let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
290
291         assert!(a.is::<uint>());
292         assert!(!b.is::<uint>());
293         assert!(!c.is::<uint>());
294
295         assert!(!a.is::<&'static str>());
296         assert!(b.is::<&'static str>());
297         assert!(!c.is::<&'static str>());
298
299         assert!(!a.is::<Test>());
300         assert!(!b.is::<Test>());
301         assert!(c.is::<Test>());
302     }
303
304     #[test]
305     fn any_managed() {
306         let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
307
308         assert!(a.is::<uint>());
309         assert!(!b.is::<uint>());
310         assert!(!c.is::<uint>());
311
312         assert!(!a.is::<&'static str>());
313         assert!(b.is::<&'static str>());
314         assert!(!c.is::<&'static str>());
315
316         assert!(!a.is::<Test>());
317         assert!(!b.is::<Test>());
318         assert!(c.is::<Test>());
319     }
320
321     #[test]
322     fn any_as_ref() {
323         let a = &5u as &Any;
324
325         match a.as_ref::<uint>() {
326             Some(&5) => {}
327             x => fail!("Unexpected value {:?}", x)
328         }
329
330         match a.as_ref::<Test>() {
331             None => {}
332             x => fail!("Unexpected value {:?}", x)
333         }
334     }
335
336     #[test]
337     fn any_as_mut() {
338         let mut a = 5u;
339         let mut b = ~7u;
340
341         let a_r = &mut a as &mut Any;
342         let tmp: &mut uint = b;
343         let b_r = tmp as &mut Any;
344
345         match a_r.as_mut::<uint>() {
346             Some(x) => {
347                 assert_eq!(*x, 5u);
348                 *x = 612;
349             }
350             x => fail!("Unexpected value {:?}", x)
351         }
352
353         match b_r.as_mut::<uint>() {
354             Some(x) => {
355                 assert_eq!(*x, 7u);
356                 *x = 413;
357             }
358             x => fail!("Unexpected value {:?}", x)
359         }
360
361         match a_r.as_mut::<Test>() {
362             None => (),
363             x => fail!("Unexpected value {:?}", x)
364         }
365
366         match b_r.as_mut::<Test>() {
367             None => (),
368             x => fail!("Unexpected value {:?}", x)
369         }
370
371         match a_r.as_mut::<uint>() {
372             Some(&612) => {}
373             x => fail!("Unexpected value {:?}", x)
374         }
375
376         match b_r.as_mut::<uint>() {
377             Some(&413) => {}
378             x => fail!("Unexpected value {:?}", x)
379         }
380     }
381
382     #[test]
383     fn any_move() {
384         let a = ~8u as ~Any;
385         let b = ~Test as ~Any;
386
387         assert_eq!(a.move(), Some(~8u));
388         assert_eq!(b.move(), Some(~Test));
389
390         let a = ~8u as ~Any;
391         let b = ~Test as ~Any;
392
393         assert_eq!(a.move(), None::<~Test>);
394         assert_eq!(b.move(), None::<~uint>);
395     }
396 }