]> git.lizzy.rs Git - rust.git/blob - src/libcore/nonzero.rs
3ff1068b93763581de7f71133b75bd8194eb1ea6
[rust.git] / src / libcore / nonzero.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 //! Exposes the NonZero lang item which provides optimization hints.
12 #![unstable(feature = "nonzero",
13             reason = "needs an RFC to flesh out the design",
14             issue = "27730")]
15
16 use ops::CoerceUnsized;
17
18 /// Unsafe trait to indicate what types are usable with the NonZero struct
19 pub unsafe trait Zeroable {
20     /// Whether this value is zero
21     fn is_zero(&self) -> bool;
22 }
23
24 macro_rules! impl_zeroable_for_pointer_types {
25     ( $( $Ptr: ty )+ ) => {
26         $(
27             /// For fat pointers to be considered "zero", only the "data" part needs to be null.
28             unsafe impl<T: ?Sized> Zeroable for $Ptr {
29                 #[inline]
30                 fn is_zero(&self) -> bool {
31                     // Cast because `is_null` is only available on thin pointers
32                     (*self as *mut u8).is_null()
33                 }
34             }
35         )+
36     }
37 }
38
39 macro_rules! impl_zeroable_for_integer_types {
40     ( $( $Int: ty )+ ) => {
41         $(
42             unsafe impl Zeroable for $Int {
43                 #[inline]
44                 fn is_zero(&self) -> bool {
45                     *self == 0
46                 }
47             }
48         )+
49     }
50 }
51
52 impl_zeroable_for_pointer_types! {
53     *const T
54     *mut T
55 }
56
57 impl_zeroable_for_integer_types! {
58     usize u8 u16 u32 u64 u128
59     isize i8 i16 i32 i64 i128
60 }
61
62 /// A wrapper type for raw pointers and integers that will never be
63 /// NULL or 0 that might allow certain optimizations.
64 #[lang = "non_zero"]
65 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
66 pub struct NonZero<T: Zeroable>(T);
67
68 impl<T: Zeroable> NonZero<T> {
69     /// Creates an instance of NonZero with the provided value.
70     /// You must indeed ensure that the value is actually "non-zero".
71     #[inline]
72     pub const unsafe fn new_unchecked(inner: T) -> Self {
73         NonZero(inner)
74     }
75
76     /// Creates an instance of NonZero with the provided value.
77     #[inline]
78     pub fn new(inner: T) -> Option<Self> {
79         if inner.is_zero() {
80             None
81         } else {
82             Some(NonZero(inner))
83         }
84     }
85
86     /// Gets the inner value.
87     pub fn get(self) -> T {
88         self.0
89     }
90 }
91
92 impl<T: Zeroable+CoerceUnsized<U>, U: Zeroable> CoerceUnsized<NonZero<U>> for NonZero<T> {}
93
94 impl<'a, T: ?Sized> From<&'a mut T> for NonZero<*mut T> {
95     fn from(reference: &'a mut T) -> Self {
96         NonZero(reference)
97     }
98 }
99
100 impl<'a, T: ?Sized> From<&'a mut T> for NonZero<*const T> {
101     fn from(reference: &'a mut T) -> Self {
102         let ptr: *mut T = reference;
103         NonZero(ptr)
104     }
105 }
106
107 impl<'a, T: ?Sized> From<&'a T> for NonZero<*const T> {
108     fn from(reference: &'a T) -> Self {
109         NonZero(reference)
110     }
111 }