(index<- ) ./libstd/cast.rs
git branch: * master c7553ea auto merge of #13609 : richo/rust/str-type-vim, r=alexcrichton
modified: Sat Apr 19 11:22:39 2014
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 //! Unsafe casting functions
12
13 use mem;
14 use intrinsics;
15 use ptr::copy_nonoverlapping_memory;
16
17 /// Casts the value at `src` to U. The two types must have the same length.
18 #[inline]
19 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
20 let mut dest: U = mem::uninit();
21 let dest_ptr: *mut u8 = transmute(&mut dest);
22 let src_ptr: *u8 = transmute(src);
23 copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
24 dest
25 }
26
27 /**
28 * Move a thing into the void
29 *
30 * The forget function will take ownership of the provided value but neglect
31 * to run any required cleanup or memory-management operations on it. This
32 * can be used for various acts of magick.
33 */
34 #[inline]
35 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
36
37 /**
38 * Force-increment the reference count on a shared box. If used
39 * carelessly, this can leak the box.
40 */
41 #[inline]
42 pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
43
44 /**
45 * Transform a value of one type into a value of another type.
46 * Both types must have the same size and alignment.
47 *
48 * # Example
49 *
50 * ```rust
51 * use std::cast;
52 *
53 * let v: &[u8] = unsafe { cast::transmute("L") };
54 * assert!(v == [76u8]);
55 * ```
56 */
57 #[inline]
58 pub unsafe fn transmute<L, G>(thing: L) -> G {
59 intrinsics::transmute(thing)
60 }
61
62 /// Coerce an immutable reference to be mutable.
63 #[inline]
64 pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
65
66 /// Coerce a reference to have an arbitrary associated lifetime.
67 #[inline]
68 pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
69 transmute(ptr)
70 }
71
72 /// Coerce an immutable reference to be mutable.
73 #[inline]
74 pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
75 transmute(ptr)
76 }
77
78 /// Coerce a mutable reference to have an arbitrary associated lifetime.
79 #[inline]
80 pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
81 transmute(ptr)
82 }
83
84 /// Transforms lifetime of the second pointer to match the first.
85 #[inline]
86 pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
87 transmute_lifetime(ptr)
88 }
89
90 /// Transforms lifetime of the second pointer to match the first.
91 #[inline]
92 pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
93 transmute_mut_lifetime(ptr)
94 }
95
96 /// Transforms lifetime of the second pointer to match the first.
97 #[inline]
98 pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
99 transmute_lifetime(ptr)
100 }
101
102
103 /****************************************************************************
104 * Tests
105 ****************************************************************************/
106
107 #[cfg(test)]
108 mod tests {
109 use cast::{bump_box_refcount, transmute};
110 use raw;
111 use str::StrSlice;
112
113 #[test]
114 fn test_transmute_copy() {
115 assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
116 }
117
118 #[test]
119 fn test_bump_managed_refcount() {
120 unsafe {
121 let managed = @"box box box".to_owned(); // refcount 1
122 bump_box_refcount(managed); // refcount 2
123 let ptr: *int = transmute(managed); // refcount 2
124 let _box1: @~str = ::cast::transmute_copy(&ptr);
125 let _box2: @~str = ::cast::transmute_copy(&ptr);
126 assert!(*_box1 == "box box box".to_owned());
127 assert!(*_box2 == "box box box".to_owned());
128 // Will destroy _box1 and _box2. Without the bump, this would
129 // use-after-free. With too many bumps, it would leak.
130 }
131 }
132
133 #[test]
134 fn test_transmute() {
135 unsafe {
136 let x = @100u8;
137 let x: *raw::Box<u8> = transmute(x);
138 assert!((*x).data == 100);
139 let _x: @int = transmute(x);
140 }
141 }
142
143 #[test]
144 fn test_transmute2() {
145 unsafe {
146 assert_eq!(~[76u8], transmute("L".to_owned()));
147 }
148 }
149 }
libstd/cast.rs:57:10-57:10 -fn- definition:
pub unsafe fn transmute<L, G>(thing: L) -> G {
intrinsics::transmute(thing)
}
references:- 193libstd/fmt/mod.rs:
libstd/repr.rs:
libstd/unstable/dynamic_lib.rs:
libstd/rt/task.rs:
libstd/rt/thread.rs:
libstd/rt/local_heap.rs:
libstd/rt/local_ptr.rs:
libstd/rt/unwind.rs:
libstd/rt/backtrace.rs:
libstd/rt/args.rs:
libstd/rt/at_exit_imp.rs:
libstd/num/f32.rs:
libstd/num/f64.rs:
libstd/char.rs:
libstd/slice.rs:
libstd/vec.rs:
libstd/str.rs:
libstd/strbuf.rs:
libstd/ascii.rs:
libstd/ptr.rs:
libstd/rc.rs:
libstd/any.rs:
libstd/comm/select.rs:
libstd/comm/sync.rs:
libstd/local_data.rs:
libstd/sync/arc.rs:
libstd/sync/atomics.rs:
libstd/sync/deque.rs:
libstd/sync/mpsc_queue.rs:
libstd/sync/spsc_queue.rs:
libstd/c_str.rs:
libstd/c_vec.rs:
libstd/io/mod.rs:
libstd/io/extensions.rs:
libstd/path/windows.rs:
libstd/ptr.rs:
libstd/cast.rs:73:10-73:10 -fn- definition:
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
transmute(ptr)
}
references:- 2libstd/ty.rs:
65: #[inline]
66: pub unsafe fn get(&self) -> *mut T { cast::transmute_mut_unsafe(&self.value) }
libstd/c_str.rs:
156: if self.buf.is_null() { fail!("CString is null!"); }
157: f(unsafe { cast::transmute_mut_unsafe(self.buf) })
158: }
libstd/cast.rs:18:10-18:10 -fn- definition:
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
let mut dest: U = mem::uninit();
let dest_ptr: *mut u8 = transmute(&mut dest);
references:- 8libstd/repr.rs:
159: var_stk: vec!(),
160: writer: ::cast::transmute_copy(&self.writer),
161: last_err: None,
libstd/raw.rs:
75: #[inline]
76: fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } }
77: }
libstd/rt/rtio.rs:
141: unsafe {
142: cast::transmute_copy(&self.factory)
143: }
libstd/any.rs:
108: // Get the raw representation of the trait object
109: let to: TraitObject = transmute_copy(&self);
--
132: // Get the raw representation of the trait object
133: let to: TraitObject = transmute_copy(&self);
libstd/slice.rs:
1669: let len = self.len();
1670: let self2: &'a mut [T] = cast::transmute_copy(&self);
1671: (self.mut_slice(0, mid), self2.mut_slice(mid, len))
libstd/cast.rs:67:10-67:10 -fn- definition:
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
transmute(ptr)
}
references:- 298: pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
99: transmute_lifetime(ptr)
100: }
libstd/cast.rs:63:10-63:10 -fn- definition:
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
/// Coerce a reference to have an arbitrary associated lifetime.
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
references:- 10libstd/slice.rs:
1719: let s: &mut Slice<T> = transmute(self);
1720: Some(cast::transmute_mut(&*raw::shift_ptr(s)))
1721: }
--
1727: let s: &mut Slice<T> = transmute(self);
1728: Some(cast::transmute_mut(&*raw::pop_ptr(s)))
1729: }
libstd/comm/mod.rs:
908: unsafe {
909: mem::swap(&mut cast::transmute_mut(self).inner,
910: &mut new_port.inner);
--
932: unsafe {
933: mem::swap(&mut cast::transmute_mut(self).inner,
934: &mut new_port.inner);
libstd/local_data.rs:
202: // there is no need to be upset!
203: Some(x) => { f(Some(unsafe { cast::transmute_mut(x) })) }
204: }
libstd/comm/mod.rs:
567: let mut tmp = Sender::new(Stream(new_inner));
568: mem::swap(&mut cast::transmute_mut(self).inner, &mut tmp.inner);
569: }
libstd/cast.rs:34:10-34:10 -fn- definition:
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
/**
* Force-increment the reference count on a shared box. If used
references:- 842: pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
libstd/mem.rs:
242: // because it's no longer relevant.
243: cast::forget(t);
244: }
libstd/slice.rs:
1230: 1);
1231: cast::forget(tmp);
1232: }
libstd/vec.rs:
639: let ptr = self.ptr as *mut c_void;
640: forget(self);
641: MoveItems { allocation: ptr, iter: iter }
libstd/ptr.rs:
258: // because it's no longer relevant.
259: cast::forget(tmp);
260: }
libstd/sync/deque.rs:
295: } else {
296: cast::forget(data); // someone else stole this value
297: Abort
--
374: ptr::copy_nonoverlapping_memory(ptr as *mut T, &t as *T, 1);
375: cast::forget(t);
376: }