]> git.lizzy.rs Git - rust.git/blob - src/liballoc/boxed.rs
rollup merge of #18407 : thestinger/arena
[rust.git] / src / liballoc / boxed.rs
1 // Copyright 2012-2014 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 //! A unique pointer type.
12
13 use core::any::{Any, AnyRefExt};
14 use core::clone::Clone;
15 use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
16 use core::default::Default;
17 use core::fmt;
18 use core::intrinsics;
19 use core::mem;
20 use core::option::Option;
21 use core::raw::TraitObject;
22 use core::result::{Ok, Err, Result};
23
24 /// A value that represents the global exchange heap. This is the default
25 /// place that the `box` keyword allocates into when no place is supplied.
26 ///
27 /// The following two examples are equivalent:
28 ///
29 /// ```rust
30 /// use std::boxed::HEAP;
31 ///
32 /// # struct Bar;
33 /// # impl Bar { fn new(_a: int) { } }
34 /// let foo = box(HEAP) Bar::new(2);
35 /// let foo = box Bar::new(2);
36 /// ```
37 #[lang = "exchange_heap"]
38 #[experimental = "may be renamed; uncertain about custom allocator design"]
39 pub static HEAP: () = ();
40
41 /// A type that represents a uniquely-owned value.
42 #[lang = "owned_box"]
43 #[unstable = "custom allocators will add an additional type parameter (with default)"]
44 pub struct Box<T>(*mut T);
45
46 impl<T: Default> Default for Box<T> {
47     fn default() -> Box<T> { box Default::default() }
48 }
49
50 #[unstable]
51 impl<T: Clone> Clone for Box<T> {
52     /// Returns a copy of the owned box.
53     #[inline]
54     fn clone(&self) -> Box<T> { box {(**self).clone()} }
55
56     /// Performs copy-assignment from `source` by reusing the existing allocation.
57     #[inline]
58     fn clone_from(&mut self, source: &Box<T>) {
59         (**self).clone_from(&(**source));
60     }
61 }
62
63 impl<T:PartialEq> PartialEq for Box<T> {
64     #[inline]
65     fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
66     #[inline]
67     fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
68 }
69 impl<T:PartialOrd> PartialOrd for Box<T> {
70     #[inline]
71     fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
72         (**self).partial_cmp(&**other)
73     }
74     #[inline]
75     fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
76     #[inline]
77     fn le(&self, other: &Box<T>) -> bool { *(*self) <= *(*other) }
78     #[inline]
79     fn ge(&self, other: &Box<T>) -> bool { *(*self) >= *(*other) }
80     #[inline]
81     fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
82 }
83 impl<T: Ord> Ord for Box<T> {
84     #[inline]
85     fn cmp(&self, other: &Box<T>) -> Ordering {
86         (**self).cmp(&**other)
87     }
88 }
89 impl<T: Eq> Eq for Box<T> {}
90
91 /// Extension methods for an owning `Any` trait object.
92 #[unstable = "post-DST and coherence changes, this will not be a trait but \
93               rather a direct `impl` on `Box<Any>`"]
94 pub trait BoxAny {
95     /// Returns the boxed value if it is of type `T`, or
96     /// `Err(Self)` if it isn't.
97     #[unstable = "naming conventions around accessing innards may change"]
98     fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
99 }
100
101 #[stable]
102 impl BoxAny for Box<Any+'static> {
103     #[inline]
104     fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any+'static>> {
105         if self.is::<T>() {
106             unsafe {
107                 // Get the raw representation of the trait object
108                 let to: TraitObject =
109                     *mem::transmute::<&Box<Any>, &TraitObject>(&self);
110
111                 // Prevent destructor on self being run
112                 intrinsics::forget(self);
113
114                 // Extract the data pointer
115                 Ok(mem::transmute(to.data))
116             }
117         } else {
118             Err(self)
119         }
120     }
121 }
122
123 impl<T: fmt::Show> fmt::Show for Box<T> {
124     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125         (**self).fmt(f)
126     }
127 }
128
129 impl fmt::Show for Box<Any+'static> {
130     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131         f.pad("Box<Any>")
132     }
133 }
134
135 #[cfg(test)]
136 mod test {
137     #[test]
138     fn test_owned_clone() {
139         let a = box 5i;
140         let b: Box<int> = a.clone();
141         assert!(a == b);
142     }
143
144     #[test]
145     fn any_move() {
146         let a = box 8u as Box<Any>;
147         let b = box Test as Box<Any>;
148
149         match a.downcast::<uint>() {
150             Ok(a) => { assert!(a == box 8u); }
151             Err(..) => panic!()
152         }
153         match b.downcast::<Test>() {
154             Ok(a) => { assert!(a == box Test); }
155             Err(..) => panic!()
156         }
157
158         let a = box 8u as Box<Any>;
159         let b = box Test as Box<Any>;
160
161         assert!(a.downcast::<Box<Test>>().is_err());
162         assert!(b.downcast::<Box<uint>>().is_err());
163     }
164
165     #[test]
166     fn test_show() {
167         let a = box 8u as Box<Any>;
168         let b = box Test as Box<Any>;
169         let a_str = a.to_str();
170         let b_str = b.to_str();
171         assert_eq!(a_str.as_slice(), "Box<Any>");
172         assert_eq!(b_str.as_slice(), "Box<Any>");
173
174         let a = &8u as &Any;
175         let b = &Test as &Any;
176         let s = format!("{}", a);
177         assert_eq!(s.as_slice(), "&Any");
178         let s = format!("{}", b);
179         assert_eq!(s.as_slice(), "&Any");
180     }
181 }