]> git.lizzy.rs Git - rust.git/blob - src/libcore/mem.rs
237efcd0096d0e190e7490d4cf64db62d5ff5ac0
[rust.git] / src / libcore / mem.rs
1 // Copyright 2012-2014 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 //! Basic functions for dealing with memory
12 //!
13 //! This module contains functions for querying the size and alignment of
14 //! types, initializing and manipulating memory.
15
16 use ptr;
17 use intrinsics;
18 use intrinsics::{bswap16, bswap32, bswap64};
19
20 pub use intrinsics::transmute;
21
22 /// Returns the size of a type in bytes.
23 #[inline]
24 #[stable]
25 pub fn size_of<T>() -> uint {
26     unsafe { intrinsics::size_of::<T>() }
27 }
28
29 /// Returns the size of the type that `_val` points to in bytes.
30 #[inline]
31 #[stable]
32 pub fn size_of_val<T>(_val: &T) -> uint {
33     size_of::<T>()
34 }
35
36 /// Deprecated, this function will be removed soon
37 #[inline]
38 #[deprecated = "this function will be removed soon"]
39 pub fn nonzero_size_of<T>() -> uint {
40     match size_of::<T>() {
41         0 => 1,
42         n => n,
43     }
44 }
45
46 /// Deprecated, this function will be removed soon
47 #[inline]
48 #[deprecated = "this function will be removed soon"]
49 pub fn nonzero_size_of_val<T>(val: &T) -> uint {
50     match size_of_val::<T>(val) {
51         0 => 1,
52         n => n,
53     }
54 }
55
56 /// Returns the ABI-required minimum alignment of a type
57 ///
58 /// This is the alignment used for struct fields. It may be smaller
59 /// than the preferred alignment.
60 #[inline]
61 #[stable]
62 pub fn min_align_of<T>() -> uint {
63     unsafe { intrinsics::min_align_of::<T>() }
64 }
65
66 /// Returns the ABI-required minimum alignment of the type of the value that
67 /// `_val` points to
68 #[inline]
69 #[stable]
70 pub fn min_align_of_val<T>(_val: &T) -> uint {
71     min_align_of::<T>()
72 }
73
74 /// Returns the alignment in memory for a type.
75 ///
76 /// This function will return the alignment, in bytes, of a type in memory. If
77 /// the alignment returned is adhered to, then the type is guaranteed to
78 /// function properly.
79 #[inline]
80 #[stable]
81 pub fn align_of<T>() -> uint {
82     // We use the preferred alignment as the default alignment for a type. This
83     // appears to be what clang migrated towards as well:
84     //
85     // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
86     unsafe { intrinsics::pref_align_of::<T>() }
87 }
88
89 /// Returns the alignment of the type of the value that `_val` points to.
90 ///
91 /// This is similar to `align_of`, but function will properly handle types such
92 /// as trait objects (in the future), returning the alignment for an arbitrary
93 /// value at runtime.
94 #[inline]
95 #[stable]
96 pub fn align_of_val<T>(_val: &T) -> uint {
97     align_of::<T>()
98 }
99
100 /// Deprecated, this function has been renamed to align_of
101 #[inline]
102 #[deprecated = "use mem::align_of instead"]
103 pub fn pref_align_of<T>() -> uint { align_of::<T>() }
104
105 /// Deprecated, this function has been renamed to align_of_val
106 #[inline]
107 #[deprecated = "use mem::align_of_val instead"]
108 pub fn pref_align_of_val<T>(val: &T) -> uint { align_of_val(val) }
109
110 /// Create a value initialized to zero.
111 ///
112 /// This function is similar to allocating space for a a local variable and
113 /// zeroing it out (an unsafe operation).
114 ///
115 /// Care must be taken when using this function, if the type `T` has a
116 /// destructor and the value falls out of scope (due to unwinding or returning)
117 /// before being initialized, then the destructor will run on zeroed
118 /// data, likely leading to crashes.
119 ///
120 /// This is useful for FFI functions sometimes, but should generally be avoided.
121 #[inline]
122 #[stable]
123 pub unsafe fn zeroed<T>() -> T {
124     intrinsics::init()
125 }
126
127 /// Deprecated, use zeroed() instead
128 #[inline]
129 #[deprecated = "this function has been renamed to zeroed()"]
130 pub unsafe fn init<T>() -> T { zeroed() }
131
132 /// Create an uninitialized value.
133 ///
134 /// Care must be taken when using this function, if the type `T` has a
135 /// destructor and the value falls out of scope (due to unwinding or returning)
136 /// before being initialized, then the destructor will run on uninitialized
137 /// data, likely leading to crashes.
138 ///
139 /// This is useful for FFI functions sometimes, but should generally be avoided.
140 #[inline]
141 #[stable]
142 pub unsafe fn uninitialized<T>() -> T {
143     intrinsics::uninit()
144 }
145
146 /// Deprecated, use `uninitialized` instead.
147 #[inline]
148 #[deprecated = "this function has been renamed to `uninitialized`"]
149 pub unsafe fn uninit<T>() -> T {
150     intrinsics::uninit()
151 }
152
153 /// Unsafely overwrite a memory location with the given value without destroying
154 /// the old value.
155 ///
156 /// This operation is unsafe because it does not destroy the previous value
157 /// contained at the location `dst`. This could leak allocations or resources,
158 /// so care must be taken to previously deallocate the value at `dst`.
159 #[inline]
160 #[deprecated = "use ptr::write"]
161 pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
162     intrinsics::move_val_init(&mut *dst, src)
163 }
164
165 /// Deprecated, use `overwrite` instead
166 #[inline]
167 #[deprecated = "use ptr::write"]
168 pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
169     ptr::write(dst, src)
170 }
171
172 /// Convert an u16 to little endian from the target's endianness.
173 ///
174 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
175 #[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x }
176
177 /// Convert an u16 to little endian from the target's endianness.
178 ///
179 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
180 #[cfg(target_endian = "big")] #[inline] #[stable]
181 pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
182
183 /// Convert an u32 to little endian from the target's endianness.
184 ///
185 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
186 #[cfg(target_endian = "little")] #[inline] #[stable]
187 pub fn to_le32(x: u32) -> u32 { x }
188
189 /// Convert an u32 to little endian from the target's endianness.
190 ///
191 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
192 #[cfg(target_endian = "big")] #[inline] #[stable]
193 pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
194
195 /// Convert an u64 to little endian from the target's endianness.
196 ///
197 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
198 #[cfg(target_endian = "little")] #[inline] #[stable]
199 pub fn to_le64(x: u64) -> u64 { x }
200
201 /// Convert an u64 to little endian from the target's endianness.
202 ///
203 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
204 #[cfg(target_endian = "big")] #[inline] #[stable]
205 pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
206
207
208 /// Convert an u16 to big endian from the target's endianness.
209 ///
210 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
211 #[cfg(target_endian = "little")] #[inline] #[stable]
212 pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
213
214 /// Convert an u16 to big endian from the target's endianness.
215 ///
216 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
217 #[cfg(target_endian = "big")] #[inline] #[stable]
218 pub fn to_be16(x: u16) -> u16 { x }
219
220 /// Convert an u32 to big endian from the target's endianness.
221 ///
222 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
223 #[cfg(target_endian = "little")] #[inline] #[stable]
224 pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
225
226 /// Convert an u32 to big endian from the target's endianness.
227 ///
228 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
229 #[cfg(target_endian = "big")] #[inline] #[stable]
230 pub fn to_be32(x: u32) -> u32 { x }
231
232 /// Convert an u64 to big endian from the target's endianness.
233 ///
234 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
235 #[cfg(target_endian = "little")] #[inline] #[stable]
236 pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
237
238 /// Convert an u64 to big endian from the target's endianness.
239 ///
240 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
241 #[cfg(target_endian = "big")] #[inline] #[stable]
242 pub fn to_be64(x: u64) -> u64 { x }
243
244
245 /// Convert an u16 from little endian to the target's endianness.
246 ///
247 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
248 #[cfg(target_endian = "little")] #[inline] #[stable]
249 pub fn from_le16(x: u16) -> u16 { x }
250
251 /// Convert an u16 from little endian to the target's endianness.
252 ///
253 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
254 #[cfg(target_endian = "big")] #[inline] #[stable]
255 pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
256
257 /// Convert an u32 from little endian to the target's endianness.
258 ///
259 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
260 #[cfg(target_endian = "little")] #[inline] #[stable]
261 pub fn from_le32(x: u32) -> u32 { x }
262
263 /// Convert an u32 from little endian to the target's endianness.
264 ///
265 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
266 #[cfg(target_endian = "big")] #[inline] #[stable]
267 pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
268
269 /// Convert an u64 from little endian to the target's endianness.
270 ///
271 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
272 #[cfg(target_endian = "little")] #[inline] #[stable]
273 pub fn from_le64(x: u64) -> u64 { x }
274
275 /// Convert an u64 from little endian to the target's endianness.
276 ///
277 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
278 #[cfg(target_endian = "big")] #[inline] #[stable]
279 pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
280
281
282 /// Convert an u16 from big endian to the target's endianness.
283 ///
284 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
285 #[cfg(target_endian = "little")] #[inline] #[stable]
286 pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
287
288 /// Convert an u16 from big endian to the target's endianness.
289 ///
290 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
291 #[cfg(target_endian = "big")] #[inline] #[stable]
292 pub fn from_be16(x: u16) -> u16 { x }
293
294 /// Convert an u32 from big endian to the target's endianness.
295 ///
296 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
297 #[cfg(target_endian = "little")] #[inline] #[stable]
298 pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
299
300 /// Convert an u32 from big endian to the target's endianness.
301 ///
302 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
303 #[cfg(target_endian = "big")] #[inline] #[stable]
304 pub fn from_be32(x: u32) -> u32 { x }
305
306 /// Convert an u64 from big endian to the target's endianness.
307 ///
308 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
309 #[cfg(target_endian = "little")] #[inline] #[stable]
310 pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
311
312 /// Convert an u64 from big endian to the target's endianness.
313 ///
314 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
315 #[cfg(target_endian = "big")] #[inline] #[stable]
316 pub fn from_be64(x: u64) -> u64 { x }
317
318 /**
319  * Swap the values at two mutable locations of the same type, without
320  * deinitialising or copying either one.
321  */
322 #[inline]
323 #[stable]
324 pub fn swap<T>(x: &mut T, y: &mut T) {
325     unsafe {
326         // Give ourselves some scratch space to work with
327         let mut t: T = uninitialized();
328
329         // Perform the swap, `&mut` pointers never alias
330         ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
331         ptr::copy_nonoverlapping_memory(x, &*y, 1);
332         ptr::copy_nonoverlapping_memory(y, &t, 1);
333
334         // y and t now point to the same thing, but we need to completely forget `t`
335         // because it's no longer relevant.
336         forget(t);
337     }
338 }
339
340 /**
341  * Replace the value at a mutable location with a new one, returning the old
342  * value, without deinitialising or copying either one.
343  *
344  * This is primarily used for transferring and swapping ownership of a value
345  * in a mutable location. For example, this function allows consumption of
346  * one field of a struct by replacing it with another value. The normal approach
347  * doesn't always work:
348  *
349  * ```rust,ignore
350  * struct Buffer<T> { buf: Vec<T> }
351  *
352  * impl<T> Buffer<T> {
353  *     fn get_and_reset(&mut self) -> Vec<T> {
354  *         // error: cannot move out of dereference of `&mut`-pointer
355  *         let buf = self.buf;
356  *         self.buf = Vec::new();
357  *         buf
358  *     }
359  * }
360  * ```
361  *
362  * Note that `T` does not necessarily implement `Clone`, so it can't even
363  * clone and reset `self.buf`. But `replace` can be used to disassociate
364  * the original value of `self.buf` from `self`, allowing it to be returned:
365  *
366  * ```rust
367  * # struct Buffer<T> { buf: Vec<T> }
368  * impl<T> Buffer<T> {
369  *     fn get_and_reset(&mut self) -> Vec<T> {
370  *         use std::mem::replace;
371  *         replace(&mut self.buf, Vec::new())
372  *     }
373  * }
374  * ```
375  */
376 #[inline]
377 #[stable]
378 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
379     swap(dest, &mut src);
380     src
381 }
382
383 /// Disposes of a value.
384 ///
385 /// This function can be used to destroy any value by allowing `drop` to take
386 /// ownership of its argument.
387 ///
388 /// # Example
389 ///
390 /// ```
391 /// use std::cell::RefCell;
392 ///
393 /// let x = RefCell::new(1);
394 ///
395 /// let mut mutable_borrow = x.borrow_mut();
396 /// *mutable_borrow = 1;
397 /// drop(mutable_borrow); // relinquish the mutable borrow on this slot
398 ///
399 /// let borrow = x.borrow();
400 /// println!("{}", *borrow);
401 /// ```
402 #[inline]
403 #[stable]
404 pub fn drop<T>(_x: T) { }
405
406 /// Moves a thing into the void.
407 ///
408 /// The forget function will take ownership of the provided value but neglect
409 /// to run any required cleanup or memory management operations on it.
410 ///
411 /// This function is the unsafe version of the `drop` function because it does
412 /// not run any destructors.
413 #[inline]
414 #[stable]
415 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing) }
416
417 /// Interprets `src` as `&U`, and then reads `src` without moving the contained
418 /// value.
419 ///
420 /// This function will unsafely assume the pointer `src` is valid for
421 /// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
422 /// will also unsafely create a copy of the contained value instead of moving
423 /// out of `src`.
424 ///
425 /// It is not a compile-time error if `T` and `U` have different sizes, but it
426 /// is highly encouraged to only invoke this function where `T` and `U` have the
427 /// same size. This function triggers undefined behavior if `U` is larger than
428 /// `T`.
429 #[inline]
430 #[stable]
431 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
432     ptr::read(src as *T as *U)
433 }
434
435 /// Transforms lifetime of the second pointer to match the first.
436 #[inline]
437 #[unstable = "this function may be removed in the future due to its \
438               questionable utility"]
439 pub unsafe fn copy_lifetime<'a, S, T>(_ptr: &'a S, ptr: &T) -> &'a T {
440     transmute(ptr)
441 }
442
443 /// Transforms lifetime of the second mutable pointer to match the first.
444 #[inline]
445 #[unstable = "this function may be removed in the future due to its \
446               questionable utility"]
447 pub unsafe fn copy_mut_lifetime<'a, S, T>(_ptr: &'a mut S,
448                                           ptr: &mut T) -> &'a mut T {
449     transmute(ptr)
450 }
451
452 #[cfg(test)]
453 mod tests {
454     use mem::*;
455     use option::{Some,None};
456     use realstd::str::StrAllocating;
457     use realstd::owned::Box;
458     use realstd::vec::Vec;
459     use raw;
460
461     #[test]
462     fn size_of_basic() {
463         assert_eq!(size_of::<u8>(), 1u);
464         assert_eq!(size_of::<u16>(), 2u);
465         assert_eq!(size_of::<u32>(), 4u);
466         assert_eq!(size_of::<u64>(), 8u);
467     }
468
469     #[test]
470     #[cfg(target_arch = "x86")]
471     #[cfg(target_arch = "arm")]
472     #[cfg(target_arch = "mips")]
473     fn size_of_32() {
474         assert_eq!(size_of::<uint>(), 4u);
475         assert_eq!(size_of::<*uint>(), 4u);
476     }
477
478     #[test]
479     #[cfg(target_arch = "x86_64")]
480     fn size_of_64() {
481         assert_eq!(size_of::<uint>(), 8u);
482         assert_eq!(size_of::<*uint>(), 8u);
483     }
484
485     #[test]
486     fn size_of_val_basic() {
487         assert_eq!(size_of_val(&1u8), 1);
488         assert_eq!(size_of_val(&1u16), 2);
489         assert_eq!(size_of_val(&1u32), 4);
490         assert_eq!(size_of_val(&1u64), 8);
491     }
492
493     #[test]
494     fn align_of_basic() {
495         assert_eq!(align_of::<u8>(), 1u);
496         assert_eq!(align_of::<u16>(), 2u);
497         assert_eq!(align_of::<u32>(), 4u);
498     }
499
500     #[test]
501     #[cfg(target_arch = "x86")]
502     #[cfg(target_arch = "arm")]
503     #[cfg(target_arch = "mips")]
504     fn align_of_32() {
505         assert_eq!(align_of::<uint>(), 4u);
506         assert_eq!(align_of::<*uint>(), 4u);
507     }
508
509     #[test]
510     #[cfg(target_arch = "x86_64")]
511     fn align_of_64() {
512         assert_eq!(align_of::<uint>(), 8u);
513         assert_eq!(align_of::<*uint>(), 8u);
514     }
515
516     #[test]
517     fn align_of_val_basic() {
518         assert_eq!(align_of_val(&1u8), 1u);
519         assert_eq!(align_of_val(&1u16), 2u);
520         assert_eq!(align_of_val(&1u32), 4u);
521     }
522
523     #[test]
524     fn test_swap() {
525         let mut x = 31337;
526         let mut y = 42;
527         swap(&mut x, &mut y);
528         assert_eq!(x, 42);
529         assert_eq!(y, 31337);
530     }
531
532     #[test]
533     fn test_replace() {
534         let mut x = Some("test".to_string());
535         let y = replace(&mut x, None);
536         assert!(x.is_none());
537         assert!(y.is_some());
538     }
539
540     #[test]
541     fn test_transmute_copy() {
542         assert_eq!(1u, unsafe { ::mem::transmute_copy(&1) });
543     }
544
545     #[test]
546     fn test_transmute() {
547         trait Foo {}
548         impl Foo for int {}
549
550         let a = box 100 as Box<Foo>;
551         unsafe {
552             let x: raw::TraitObject = transmute(a);
553             assert!(*(x.data as *int) == 100);
554             let _x: Box<Foo> = transmute(x);
555         }
556
557         unsafe {
558             assert!(Vec::from_slice([76u8]) == transmute("L".to_string()));
559         }
560     }
561 }
562
563 // FIXME #13642 (these benchmarks should be in another place)
564 /// Completely miscellaneous language-construct benchmarks.
565 #[cfg(test)]
566 mod bench {
567     extern crate test;
568     use self::test::Bencher;
569     use option::{Some,None};
570
571     // Static/dynamic method dispatch
572
573     struct Struct {
574         field: int
575     }
576
577     trait Trait {
578         fn method(&self) -> int;
579     }
580
581     impl Trait for Struct {
582         fn method(&self) -> int {
583             self.field
584         }
585     }
586
587     #[bench]
588     fn trait_vtable_method_call(b: &mut Bencher) {
589         let s = Struct { field: 10 };
590         let t = &s as &Trait;
591         b.iter(|| {
592             t.method()
593         });
594     }
595
596     #[bench]
597     fn trait_static_method_call(b: &mut Bencher) {
598         let s = Struct { field: 10 };
599         b.iter(|| {
600             s.method()
601         });
602     }
603
604     // Overhead of various match forms
605
606     #[bench]
607     fn match_option_some(b: &mut Bencher) {
608         let x = Some(10);
609         b.iter(|| {
610             match x {
611                 Some(y) => y,
612                 None => 11
613             }
614         });
615     }
616
617     #[bench]
618     fn match_vec_pattern(b: &mut Bencher) {
619         let x = [1,2,3,4,5,6];
620         b.iter(|| {
621             match x {
622                 [1,2,3,..] => 10,
623                 _ => 11
624             }
625         });
626     }
627 }