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