(index<- ) ./libstd/util.rs
1 // Copyright 2012-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 //! Miscellaneous helpers for common patterns.
12
13 use cast;
14 use ptr;
15 use prelude::*;
16 use unstable::intrinsics;
17
18 /// The identity function.
19 #[inline]
20 pub fn id<T>(x: T) -> T { x }
21
22 /// Ignores a value.
23 #[inline]
24 pub fn ignore<T>(_x: T) { }
25
26 /**
27 * Swap the values at two mutable locations of the same type, without
28 * deinitialising or copying either one.
29 */
30 #[inline]
31 pub fn swap<T>(x: &mut T, y: &mut T) {
32 unsafe {
33 // Give ourselves some scratch space to work with
34 let mut tmp: T = intrinsics::uninit();
35 let t: *mut T = &mut tmp;
36
37 // Perform the swap, `&mut` pointers never alias
38 let x_raw: *mut T = x;
39 let y_raw: *mut T = y;
40 ptr::copy_nonoverlapping_memory(t, x_raw, 1);
41 ptr::copy_nonoverlapping_memory(x, y_raw, 1);
42 ptr::copy_nonoverlapping_memory(y, t, 1);
43
44 // y and t now point to the same thing, but we need to completely forget `tmp`
45 // because it's no longer relevant.
46 cast::forget(tmp);
47 }
48 }
49
50 /**
51 * Replace the value at a mutable location with a new one, returning the old
52 * value, without deinitialising or copying either one.
53 */
54 #[inline]
55 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
56 swap(dest, &mut src);
57 src
58 }
59
60 /// A non-copyable dummy type.
61 #[deriving(Eq, TotalEq, Ord, TotalOrd)]
62 #[unsafe_no_drop_flag]
63 pub struct NonCopyable;
64
65 impl NonCopyable {
66 // FIXME(#8233) should not be necessary
67 /// Create a new noncopyable token.
68 pub fn new() -> NonCopyable { NonCopyable }
69 }
70
71 impl Drop for NonCopyable {
72 fn drop(&mut self) { }
73 }
74
75 /// A type with no inhabitants
76 pub enum Void { }
77
78 impl Void {
79 /// A utility function for ignoring this uninhabited type
80 pub fn uninhabited(self) -> ! {
81 match self {
82 // Nothing to match on
83 }
84 }
85 }
86
87
88 #[cfg(test)]
89 mod tests {
90 use super::*;
91
92 use clone::Clone;
93 use ops::Drop;
94 use option::{None, Some};
95 use either::{Either, Left, Right};
96 use sys::size_of;
97
98 #[test]
99 fn identity_crisis() {
100 // Writing a test for the identity function. How did it come to this?
101 let x = ~[(5, false)];
102 //FIXME #3387 assert!(x.eq(id(x.clone())));
103 let y = x.clone();
104 assert!(x.eq(&id(y)));
105 }
106
107 #[test]
108 fn test_swap() {
109 let mut x = 31337;
110 let mut y = 42;
111 swap(&mut x, &mut y);
112 assert_eq!(x, 42);
113 assert_eq!(y, 31337);
114 }
115
116 #[test]
117 fn test_replace() {
118 let mut x = Some(NonCopyable);
119 let y = replace(&mut x, None);
120 assert!(x.is_none());
121 assert!(y.is_some());
122 }
123
124 #[test]
125 fn test_uninhabited() {
126 let could_only_be_coin : Either <Void, ()> = Right (());
127 match could_only_be_coin {
128 Right (coin) => coin,
129 Left (is_void) => is_void.uninhabited ()
130 }
131 }
132
133 #[test]
134 fn test_noncopyable() {
135 assert_eq!(size_of::<NonCopyable>(), 0);
136
137 // verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
138
139 static mut did_run: bool = false;
140
141 struct Foo { five: int }
142
143 impl Drop for Foo {
144 fn drop(&mut self) {
145 assert_eq!(self.five, 5);
146 unsafe {
147 did_run = true;
148 }
149 }
150 }
151
152 {
153 let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
154 }
155
156 unsafe { assert_eq!(did_run, true); }
157 }
158 }
159
160 /// Completely miscellaneous language-construct benchmarks.
161 #[cfg(test)]
162 mod bench {
163
164 use extra::test::BenchHarness;
165 use option::{Some,None};
166
167 // Static/dynamic method dispatch
168
169 struct Struct {
170 field: int
171 }
172
173 trait Trait {
174 fn method(&self) -> int;
175 }
176
177 impl Trait for Struct {
178 fn method(&self) -> int {
179 self.field
180 }
181 }
182
183 #[bench]
184 fn trait_vtable_method_call(bh: &mut BenchHarness) {
185 let s = Struct { field: 10 };
186 let t = &s as &Trait;
187 do bh.iter {
188 t.method();
189 }
190 }
191
192 #[bench]
193 fn trait_static_method_call(bh: &mut BenchHarness) {
194 let s = Struct { field: 10 };
195 do bh.iter {
196 s.method();
197 }
198 }
199
200 // Overhead of various match forms
201
202 #[bench]
203 fn match_option_some(bh: &mut BenchHarness) {
204 let x = Some(10);
205 do bh.iter {
206 let _q = match x {
207 Some(y) => y,
208 None => 11
209 };
210 }
211 }
212
213 #[bench]
214 fn match_vec_pattern(bh: &mut BenchHarness) {
215 let x = [1,2,3,4,5,6];
216 do bh.iter {
217 let _q = match x {
218 [1,2,3,.._] => 10,
219 _ => 11
220 };
221 }
222 }
223 }
libstd/util.rs:62:23-62:23 -struct- definition:
#[unsafe_no_drop_flag]
pub struct NonCopyable;
references:-61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
71: impl Drop for NonCopyable {
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
68: pub fn new() -> NonCopyable { NonCopyable }
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
65: impl NonCopyable {
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
61: #[deriving(Eq, TotalEq, Ord, TotalOrd)]
libstd/task/mod.rs:
174: can_not_copy: Option<util::NonCopyable>,
libstd/util.rs:54:10-54:10 -fn- definition:
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
references:-libstd/rt/kill.rs:
531: Some(blk(util::replace(&mut inner.child_tombstones, None)));
libstd/rt/uv/process.rs:
65: let io = util::replace(&mut config.io, ~[]);
libstd/rt/args.rs:
76: let val = util::replace(&mut *ptr, None);
libstd/vec.rs:
1597: let v = util::replace(self, ~[x]);
libstd/option.rs:
207: util::replace(self, None)
libstd/hashmap.rs:
212: Some(replace(&mut b.value, v))
159: let old_buckets = replace(&mut self.buckets,
libstd/trie.rs:
423: match replace(child, Nothing) {
libstd/task/spawn.rs:
297: let rest = util::replace(&mut nobe.ancestors,
libstd/local_data.rs:
153: let data = match util::replace(entry, None) {
libstd/util.rs:19:10-19:10 -fn- definition:
#[inline]
pub fn id<T>(x: T) -> T { x }
references:-libstd/rt/uv/net.rs:
96: uv_socket_addr_as_socket_addr(addr, util::id)
libstd/util.rs:75:31-75:31 -enum- definition:
/// A type with no inhabitants
pub enum Void { }
references:-78: impl Void {
libstd/rt/comm.rs:
68: let packet: *mut Void = cast::transmute(packet);
51: void_packet: *mut Void,
57: void_packet: *mut Void,
libstd/fmt/mod.rs:
459: priv value: &'self util::Void,
458: priv formatter: extern "Rust" fn(&util::Void, &mut Formatter),
686: unsafe { Some(*(v as *util::Void as *uint)) }
682: unsafe { Some(*(v as *util::Void as *uint)) }
libstd/util.rs:23:10-23:10 -fn- definition:
#[inline]
pub fn ignore<T>(_x: T) { }
references:-libstd/rt/kill.rs:
577: { use util; util::ignore(group); }
libstd/util.rs:30:10-30:10 -fn- definition:
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
references:-56: swap(dest, &mut src);
libstd/vec.rs:
1841: util::swap(&mut *p_r, &mut *p_w);
1999: util::swap(a, b);
libstd/ptr.rs:
190: swap(cast::transmute(dest), &mut src); // cannot overlap
libstd/iter.rs:
703: (Some(x), Some(y)) => util::swap(x, y),
libstd/trie.rs:
386: swap(&mut tmp, child);