]> git.proxmox.com Git - rustc.git/blame - src/libstd/cast.rs
Imported Upstream version 0.7
[rustc.git] / src / libstd / cast.rs
CommitLineData
223e47cc
LB
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
970d7e83
LB
13use sys;
14use unstable::intrinsics;
15
16/// Casts the value at `src` to U. The two types must have the same length.
17/// Casts the value at `src` to U. The two types must have the same length.
18#[cfg(target_word_size = "32")]
19#[inline]
20pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
21 let mut dest: U = intrinsics::uninit();
22 let dest_ptr: *mut u8 = transmute(&mut dest);
23 let src_ptr: *u8 = transmute(src);
24 intrinsics::memcpy32(dest_ptr, src_ptr, sys::size_of::<U>() as u32);
25 dest
223e47cc
LB
26}
27
28/// Casts the value at `src` to U. The two types must have the same length.
970d7e83
LB
29#[cfg(target_word_size = "64")]
30#[inline]
31pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
32 let mut dest: U = intrinsics::uninit();
33 let dest_ptr: *mut u8 = transmute(&mut dest);
34 let src_ptr: *u8 = transmute(src);
35 intrinsics::memcpy64(dest_ptr, src_ptr, sys::size_of::<U>() as u64);
36 dest
223e47cc
LB
37}
38
39/**
40 * Move a thing into the void
41 *
42 * The forget function will take ownership of the provided value but neglect
43 * to run any required cleanup or memory-management operations on it. This
970d7e83 44 * can be used for various acts of magick.
223e47cc 45 */
970d7e83
LB
46#[inline]
47pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
223e47cc
LB
48
49/**
50 * Force-increment the reference count on a shared box. If used
970d7e83 51 * carelessly, this can leak the box.
223e47cc 52 */
970d7e83 53#[inline]
223e47cc
LB
54pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
55
56/**
57 * Transform a value of one type into a value of another type.
58 * Both types must have the same size and alignment.
59 *
60 * # Example
61 *
62 * assert!(transmute("L") == ~[76u8, 0u8]);
63 */
970d7e83 64#[inline]
223e47cc 65pub unsafe fn transmute<L, G>(thing: L) -> G {
970d7e83 66 intrinsics::transmute(thing)
223e47cc
LB
67}
68
69/// Coerce an immutable reference to be mutable.
970d7e83 70#[inline]
223e47cc
LB
71pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
72
73/// Coerce a mutable reference to be immutable.
970d7e83 74#[inline]
223e47cc
LB
75pub unsafe fn transmute_immut<'a,T>(ptr: &'a mut T) -> &'a T {
76 transmute(ptr)
77}
78
79/// Coerce a borrowed pointer to have an arbitrary associated region.
970d7e83 80#[inline]
223e47cc
LB
81pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
82 transmute(ptr)
83}
84
85/// Coerce an immutable reference to be mutable.
970d7e83 86#[inline]
223e47cc
LB
87pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
88 transmute(ptr)
89}
90
91/// Coerce an immutable reference to be mutable.
970d7e83 92#[inline]
223e47cc
LB
93pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
94 transmute(ptr)
95}
96
97/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
970d7e83 98#[inline]
223e47cc
LB
99pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
100 transmute(ptr)
101}
102
103/// Transforms lifetime of the second pointer to match the first.
970d7e83 104#[inline]
223e47cc
LB
105pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
106 transmute_region(ptr)
107}
108
109/// Transforms lifetime of the second pointer to match the first.
970d7e83
LB
110#[inline]
111pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
112 transmute_mut_region(ptr)
113}
114
115/// Transforms lifetime of the second pointer to match the first.
116#[inline]
223e47cc
LB
117pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
118 transmute_region(ptr)
119}
120
121
122/****************************************************************************
123 * Tests
124 ****************************************************************************/
125
126#[cfg(test)]
970d7e83
LB
127mod tests {
128 use cast::{bump_box_refcount, transmute};
223e47cc
LB
129
130 #[test]
970d7e83
LB
131 fn test_transmute_copy() {
132 assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
223e47cc
LB
133 }
134
135 #[test]
970d7e83 136 fn test_bump_box_refcount() {
223e47cc
LB
137 unsafe {
138 let box = @~"box box box"; // refcount 1
139 bump_box_refcount(box); // refcount 2
140 let ptr: *int = transmute(box); // refcount 2
970d7e83
LB
141 let _box1: @~str = ::cast::transmute_copy(&ptr);
142 let _box2: @~str = ::cast::transmute_copy(&ptr);
223e47cc
LB
143 assert!(*_box1 == ~"box box box");
144 assert!(*_box2 == ~"box box box");
145 // Will destroy _box1 and _box2. Without the bump, this would
146 // use-after-free. With too many bumps, it would leak.
147 }
148 }
149
150 #[test]
970d7e83 151 fn test_transmute() {
223e47cc
LB
152 use managed::raw::BoxRepr;
153 unsafe {
154 let x = @100u8;
155 let x: *BoxRepr = transmute(x);
156 assert!((*x).data == 100);
157 let _x: @int = transmute(x);
158 }
159 }
160
161 #[test]
970d7e83 162 fn test_transmute2() {
223e47cc 163 unsafe {
970d7e83 164 assert_eq!(~[76u8, 0u8], transmute(~"L"));
223e47cc
LB
165 }
166 }
167}