(index<- ) ./libstd/sys.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 //! Misc low level stuff
12
13 #[allow(missing_doc)];
14
15 use c_str::ToCStr;
16 use cast;
17 use libc::size_t;
18 use libc;
19 use repr;
20 use rt::task;
21 use str;
22 use unstable::intrinsics;
23
24 /// Returns the size of a type
25 #[inline]
26 pub fn size_of<T>() -> uint {
27 unsafe { intrinsics::size_of::<T>() }
28 }
29
30 /// Returns the size of the type that `_val` points to
31 #[inline]
32 pub fn size_of_val<T>(_val: &T) -> uint {
33 size_of::<T>()
34 }
35
36 /**
37 * Returns the size of a type, or 1 if the actual size is zero.
38 *
39 * Useful for building structures containing variable-length arrays.
40 */
41 #[inline]
42 pub fn nonzero_size_of<T>() -> uint {
43 let s = size_of::<T>();
44 if s == 0 { 1 } else { s }
45 }
46
47 /// Returns the size of the type of the value that `_val` points to
48 #[inline]
49 pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
50 nonzero_size_of::<T>()
51 }
52
53
54 /**
55 * Returns the ABI-required minimum alignment of a type
56 *
57 * This is the alignment used for struct fields. It may be smaller
58 * than the preferred alignment.
59 */
60 #[inline]
61 pub fn min_align_of<T>() -> uint {
62 unsafe { intrinsics::min_align_of::<T>() }
63 }
64
65 /// Returns the ABI-required minimum alignment of the type of the value that
66 /// `_val` points to
67 #[inline]
68 pub fn min_align_of_val<T>(_val: &T) -> uint {
69 min_align_of::<T>()
70 }
71
72 /// Returns the preferred alignment of a type
73 #[inline]
74 pub fn pref_align_of<T>() -> uint {
75 unsafe { intrinsics::pref_align_of::<T>() }
76 }
77
78 /// Returns the preferred alignment of the type of the value that
79 /// `_val` points to
80 #[inline]
81 pub fn pref_align_of_val<T>(_val: &T) -> uint {
82 pref_align_of::<T>()
83 }
84
85 /// Returns the refcount of a shared box (as just before calling this)
86 #[inline]
87 pub fn refcount<T>(t: @T) -> uint {
88 unsafe {
89 let ref_ptr: *uint = cast::transmute_copy(&t);
90 *ref_ptr - 1
91 }
92 }
93
94 pub fn log_str<T>(t: &T) -> ~str {
95 use rt::io;
96 use rt::io::Decorator;
97
98 let mut result = io::mem::MemWriter::new();
99 repr::write_repr(&mut result as &mut io::Writer, t);
100 str::from_utf8_owned(result.inner())
101 }
102
103 /// Trait for initiating task failure.
104 pub trait FailWithCause {
105 /// Fail the current task, taking ownership of `cause`
106 fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
107 }
108
109 impl FailWithCause for ~str {
110 fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
111 do cause.with_c_str |msg_buf| {
112 do file.with_c_str |file_buf| {
113 task::begin_unwind(msg_buf, file_buf, line as libc::size_t)
114 }
115 }
116 }
117 }
118
119 impl FailWithCause for &'static str {
120 fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
121 do cause.with_c_str |msg_buf| {
122 do file.with_c_str |file_buf| {
123 task::begin_unwind(msg_buf, file_buf, line as libc::size_t)
124 }
125 }
126 }
127 }
128
129 #[cfg(test)]
130 mod tests {
131 use cast;
132 use sys::*;
133
134 #[test]
135 fn size_of_basic() {
136 assert_eq!(size_of::<u8>(), 1u);
137 assert_eq!(size_of::<u16>(), 2u);
138 assert_eq!(size_of::<u32>(), 4u);
139 assert_eq!(size_of::<u64>(), 8u);
140 }
141
142 #[test]
143 #[cfg(target_arch = "x86")]
144 #[cfg(target_arch = "arm")]
145 #[cfg(target_arch = "mips")]
146 fn size_of_32() {
147 assert_eq!(size_of::<uint>(), 4u);
148 assert_eq!(size_of::<*uint>(), 4u);
149 }
150
151 #[test]
152 #[cfg(target_arch = "x86_64")]
153 fn size_of_64() {
154 assert_eq!(size_of::<uint>(), 8u);
155 assert_eq!(size_of::<*uint>(), 8u);
156 }
157
158 #[test]
159 fn size_of_val_basic() {
160 assert_eq!(size_of_val(&1u8), 1);
161 assert_eq!(size_of_val(&1u16), 2);
162 assert_eq!(size_of_val(&1u32), 4);
163 assert_eq!(size_of_val(&1u64), 8);
164 }
165
166 #[test]
167 fn nonzero_size_of_basic() {
168 type Z = [i8, ..0];
169 assert_eq!(size_of::<Z>(), 0u);
170 assert_eq!(nonzero_size_of::<Z>(), 1u);
171 assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
172 }
173
174 #[test]
175 fn nonzero_size_of_val_basic() {
176 let z = [0u8, ..0];
177 assert_eq!(size_of_val(&z), 0u);
178 assert_eq!(nonzero_size_of_val(&z), 1u);
179 assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
180 }
181
182 #[test]
183 fn align_of_basic() {
184 assert_eq!(pref_align_of::<u8>(), 1u);
185 assert_eq!(pref_align_of::<u16>(), 2u);
186 assert_eq!(pref_align_of::<u32>(), 4u);
187 }
188
189 #[test]
190 #[cfg(target_arch = "x86")]
191 #[cfg(target_arch = "arm")]
192 #[cfg(target_arch = "mips")]
193 fn align_of_32() {
194 assert_eq!(pref_align_of::<uint>(), 4u);
195 assert_eq!(pref_align_of::<*uint>(), 4u);
196 }
197
198 #[test]
199 #[cfg(target_arch = "x86_64")]
200 fn align_of_64() {
201 assert_eq!(pref_align_of::<uint>(), 8u);
202 assert_eq!(pref_align_of::<*uint>(), 8u);
203 }
204
205 #[test]
206 fn align_of_val_basic() {
207 assert_eq!(pref_align_of_val(&1u8), 1u);
208 assert_eq!(pref_align_of_val(&1u16), 2u);
209 assert_eq!(pref_align_of_val(&1u32), 4u);
210 }
211
212 #[test]
213 fn synthesize_closure() {
214 use unstable::raw::Closure;
215 unsafe {
216 let x = 10;
217 let f: &fn(int) -> int = |y| x + y;
218
219 assert_eq!(f(20), 30);
220
221 let original_closure: Closure = cast::transmute(f);
222
223 let actual_function_pointer = original_closure.code;
224 let environment = original_closure.env;
225
226 let new_closure = Closure {
227 code: actual_function_pointer,
228 env: environment
229 };
230
231 let new_f: &fn(int) -> int = cast::transmute(new_closure);
232 assert_eq!(new_f(20), 30);
233 }
234 }
235
236 #[test]
237 #[should_fail]
238 fn fail_static() { FailWithCause::fail_with("cause", file!(), line!()) }
239
240 #[test]
241 #[should_fail]
242 fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!()) }
243 }