]> git.lizzy.rs Git - rust.git/blob - src/liballoc/owned.rs
addec396bbef8715d14e88ea237671424b1621b2
[rust.git] / src / liballoc / owned.rs
1 // Copyright 2012 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::kinds::Send;
20 use core::mem;
21 use core::option::Option;
22 use core::raw::TraitObject;
23 use core::result::{Ok, Err, Result};
24
25 /// A value that represents the global exchange heap. This is the default
26 /// place that the `box` keyword allocates into when no place is supplied.
27 ///
28 /// The following two examples are equivalent:
29 ///
30 ///     use std::owned::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 #[lang="exchange_heap"]
37 pub static HEAP: () = ();
38
39 /// A type that represents a uniquely-owned value.
40 #[lang="owned_box"]
41 pub struct Box<T>(*mut T);
42
43 impl<T: Default> Default for Box<T> {
44     fn default() -> Box<T> { box Default::default() }
45 }
46
47 #[unstable]
48 impl<T: Clone> Clone for Box<T> {
49     /// Return a copy of the owned box.
50     #[inline]
51     fn clone(&self) -> Box<T> { box {(**self).clone()} }
52
53     /// Perform copy-assignment from `source` by reusing the existing allocation.
54     #[inline]
55     fn clone_from(&mut self, source: &Box<T>) {
56         (**self).clone_from(&(**source));
57     }
58 }
59
60 // box pointers
61 impl<T:PartialEq> PartialEq for Box<T> {
62     #[inline]
63     fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
64     #[inline]
65     fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
66 }
67 impl<T:PartialOrd> PartialOrd for Box<T> {
68     #[inline]
69     fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
70         (**self).partial_cmp(*other)
71     }
72     #[inline]
73     fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
74     #[inline]
75     fn le(&self, other: &Box<T>) -> bool { *(*self) <= *(*other) }
76     #[inline]
77     fn ge(&self, other: &Box<T>) -> bool { *(*self) >= *(*other) }
78     #[inline]
79     fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
80 }
81 impl<T: Ord> Ord for Box<T> {
82     #[inline]
83     fn cmp(&self, other: &Box<T>) -> Ordering { (**self).cmp(*other) }
84 }
85 impl<T: Eq> Eq for Box<T> {}
86
87 /// Extension methods for an owning `Any` trait object
88 pub trait AnyOwnExt {
89     /// Returns the boxed value if it is of type `T`, or
90     /// `Err(Self)` if it isn't.
91     fn move<T: 'static>(self) -> Result<Box<T>, Self>;
92 }
93
94 impl AnyOwnExt for Box<Any> {
95     #[inline]
96     fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
97         if self.is::<T>() {
98             unsafe {
99                 // Get the raw representation of the trait object
100                 let to: TraitObject =
101                     *mem::transmute::<&Box<Any>, &TraitObject>(&self);
102
103                 // Prevent destructor on self being run
104                 intrinsics::forget(self);
105
106                 // Extract the data pointer
107                 Ok(mem::transmute(to.data))
108             }
109         } else {
110             Err(self)
111         }
112     }
113 }
114
115 /// Extension methods for an owning `Any+Send` trait object
116 pub trait AnySendOwnExt {
117     /// Returns the boxed value if it is of type `T`, or
118     /// `Err(Self)` if it isn't.
119     fn move_send<T: 'static>(self) -> Result<Box<T>, Self>;
120 }
121
122 impl AnySendOwnExt for Box<Any+Send> {
123     #[inline]
124     fn move_send<T: 'static>(self) -> Result<Box<T>, Box<Any+Send>> {
125         if self.is::<T>() {
126             unsafe {
127                 // Get the raw representation of the trait object
128                 let to: TraitObject =
129                     *mem::transmute::<&Box<Any+Send>, &TraitObject>(&self);
130
131                 // Prevent destructor on self being run
132                 intrinsics::forget(self);
133
134                 // Extract the data pointer
135                 Ok(mem::transmute(to.data))
136             }
137         } else {
138             Err(self)
139         }
140     }
141 }
142
143 impl<T: fmt::Show> fmt::Show for Box<T> {
144     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145         (**self).fmt(f)
146     }
147 }
148
149 impl fmt::Show for Box<Any> {
150     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151         f.pad("Box<Any>")
152     }
153 }
154
155 #[cfg(test)]
156 mod test {
157     #[test]
158     fn test_owned_clone() {
159         let a = box 5i;
160         let b: Box<int> = a.clone();
161         assert!(a == b);
162     }
163
164     #[test]
165     fn any_move() {
166         let a = box 8u as Box<Any>;
167         let b = box Test as Box<Any>;
168
169         match a.move::<uint>() {
170             Ok(a) => { assert!(a == box 8u); }
171             Err(..) => fail!()
172         }
173         match b.move::<Test>() {
174             Ok(a) => { assert!(a == box Test); }
175             Err(..) => fail!()
176         }
177
178         let a = box 8u as Box<Any>;
179         let b = box Test as Box<Any>;
180
181         assert!(a.move::<Box<Test>>().is_err());
182         assert!(b.move::<Box<uint>>().is_err());
183     }
184
185     #[test]
186     fn test_show() {
187         let a = box 8u as Box<Any>;
188         let b = box Test as Box<Any>;
189         let a_str = a.to_str();
190         let b_str = b.to_str();
191         assert_eq!(a_str.as_slice(), "Box<Any>");
192         assert_eq!(b_str.as_slice(), "Box<Any>");
193
194         let a = &8u as &Any;
195         let b = &Test as &Any;
196         let s = format!("{}", a);
197         assert_eq!(s.as_slice(), "&Any");
198         let s = format!("{}", b);
199         assert_eq!(s.as_slice(), "&Any");
200     }
201 }