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