]> git.lizzy.rs Git - rust.git/blob - src/libcore/array.rs
Auto merge of #53133 - Zoxc:gen-int, r=eddyb
[rust.git] / src / libcore / array.rs
1 // Copyright 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 //! Implementations of things like `Eq` for fixed-length arrays
12 //! up to a certain length. Eventually we should able to generalize
13 //! to all lengths.
14 //!
15 //! *[See also the array primitive type](../../std/primitive.array.html).*
16
17 #![unstable(feature = "fixed_size_array",
18             reason = "traits and impls are better expressed through generic \
19                       integer constants",
20             issue = "27778")]
21
22 use borrow::{Borrow, BorrowMut};
23 use cmp::Ordering;
24 use convert::TryFrom;
25 use fmt;
26 use hash::{Hash, self};
27 use marker::Unsize;
28 use slice::{Iter, IterMut};
29
30 /// Utility trait implemented only on arrays of fixed size
31 ///
32 /// This trait can be used to implement other traits on fixed-size arrays
33 /// without causing much metadata bloat.
34 ///
35 /// The trait is marked unsafe in order to restrict implementors to fixed-size
36 /// arrays. User of this trait can assume that implementors have the exact
37 /// layout in memory of a fixed size array (for example, for unsafe
38 /// initialization).
39 ///
40 /// Note that the traits AsRef and AsMut provide similar methods for types that
41 /// may not be fixed-size arrays. Implementors should prefer those traits
42 /// instead.
43 pub unsafe trait FixedSizeArray<T> {
44     /// Converts the array to immutable slice
45     fn as_slice(&self) -> &[T];
46     /// Converts the array to mutable slice
47     fn as_mut_slice(&mut self) -> &mut [T];
48 }
49
50 unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
51     #[inline]
52     fn as_slice(&self) -> &[T] {
53         self
54     }
55     #[inline]
56     fn as_mut_slice(&mut self) -> &mut [T] {
57         self
58     }
59 }
60
61 /// The error type returned when a conversion from a slice to an array fails.
62 #[unstable(feature = "try_from", issue = "33417")]
63 #[derive(Debug, Copy, Clone)]
64 pub struct TryFromSliceError(());
65
66 impl fmt::Display for TryFromSliceError {
67     #[inline]
68     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69         fmt::Display::fmt(self.__description(), f)
70     }
71 }
72
73 impl TryFromSliceError {
74     #[unstable(feature = "array_error_internals",
75            reason = "available through Error trait and this method should not \
76                      be exposed publicly",
77            issue = "0")]
78     #[inline]
79     #[doc(hidden)]
80     pub fn __description(&self) -> &str {
81         "could not convert slice to array"
82     }
83 }
84
85 macro_rules! __impl_slice_eq1 {
86     ($Lhs: ty, $Rhs: ty) => {
87         __impl_slice_eq1! { $Lhs, $Rhs, Sized }
88     };
89     ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
90         #[stable(feature = "rust1", since = "1.0.0")]
91         impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
92             #[inline]
93             fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
94             #[inline]
95             fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
96         }
97     }
98 }
99
100 macro_rules! __impl_slice_eq2 {
101     ($Lhs: ty, $Rhs: ty) => {
102         __impl_slice_eq2! { $Lhs, $Rhs, Sized }
103     };
104     ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
105         __impl_slice_eq1!($Lhs, $Rhs, $Bound);
106
107         #[stable(feature = "rust1", since = "1.0.0")]
108         impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
109             #[inline]
110             fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
111             #[inline]
112             fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
113         }
114     }
115 }
116
117 // macro for implementing n-element array functions and operations
118 macro_rules! array_impls {
119     ($($N:expr)+) => {
120         $(
121             #[stable(feature = "rust1", since = "1.0.0")]
122             impl<T> AsRef<[T]> for [T; $N] {
123                 #[inline]
124                 fn as_ref(&self) -> &[T] {
125                     &self[..]
126                 }
127             }
128
129             #[stable(feature = "rust1", since = "1.0.0")]
130             impl<T> AsMut<[T]> for [T; $N] {
131                 #[inline]
132                 fn as_mut(&mut self) -> &mut [T] {
133                     &mut self[..]
134                 }
135             }
136
137             #[stable(feature = "array_borrow", since = "1.4.0")]
138             impl<T> Borrow<[T]> for [T; $N] {
139                 fn borrow(&self) -> &[T] {
140                     self
141                 }
142             }
143
144             #[stable(feature = "array_borrow", since = "1.4.0")]
145             impl<T> BorrowMut<[T]> for [T; $N] {
146                 fn borrow_mut(&mut self) -> &mut [T] {
147                     self
148                 }
149             }
150
151             #[unstable(feature = "try_from", issue = "33417")]
152             impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
153                 type Error = TryFromSliceError;
154
155                 fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
156                     if slice.len() == $N {
157                         let ptr = slice.as_ptr() as *const [T; $N];
158                         unsafe { Ok(&*ptr) }
159                     } else {
160                         Err(TryFromSliceError(()))
161                     }
162                 }
163             }
164
165             #[unstable(feature = "try_from", issue = "33417")]
166             impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
167                 type Error = TryFromSliceError;
168
169                 fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
170                     if slice.len() == $N {
171                         let ptr = slice.as_mut_ptr() as *mut [T; $N];
172                         unsafe { Ok(&mut *ptr) }
173                     } else {
174                         Err(TryFromSliceError(()))
175                     }
176                 }
177             }
178
179             #[stable(feature = "rust1", since = "1.0.0")]
180             impl<T: Hash> Hash for [T; $N] {
181                 fn hash<H: hash::Hasher>(&self, state: &mut H) {
182                     Hash::hash(&self[..], state)
183                 }
184             }
185
186             #[stable(feature = "rust1", since = "1.0.0")]
187             impl<T: fmt::Debug> fmt::Debug for [T; $N] {
188                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189                     fmt::Debug::fmt(&&self[..], f)
190                 }
191             }
192
193             #[stable(feature = "rust1", since = "1.0.0")]
194             impl<'a, T> IntoIterator for &'a [T; $N] {
195                 type Item = &'a T;
196                 type IntoIter = Iter<'a, T>;
197
198                 fn into_iter(self) -> Iter<'a, T> {
199                     self.iter()
200                 }
201             }
202
203             #[stable(feature = "rust1", since = "1.0.0")]
204             impl<'a, T> IntoIterator for &'a mut [T; $N] {
205                 type Item = &'a mut T;
206                 type IntoIter = IterMut<'a, T>;
207
208                 fn into_iter(self) -> IterMut<'a, T> {
209                     self.iter_mut()
210                 }
211             }
212
213             // NOTE: some less important impls are omitted to reduce code bloat
214             __impl_slice_eq1! { [A; $N], [B; $N] }
215             __impl_slice_eq2! { [A; $N], [B] }
216             __impl_slice_eq2! { [A; $N], &'b [B] }
217             __impl_slice_eq2! { [A; $N], &'b mut [B] }
218             // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
219             // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
220
221             #[stable(feature = "rust1", since = "1.0.0")]
222             impl<T:Eq> Eq for [T; $N] { }
223
224             #[stable(feature = "rust1", since = "1.0.0")]
225             impl<T:PartialOrd> PartialOrd for [T; $N] {
226                 #[inline]
227                 fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
228                     PartialOrd::partial_cmp(&&self[..], &&other[..])
229                 }
230                 #[inline]
231                 fn lt(&self, other: &[T; $N]) -> bool {
232                     PartialOrd::lt(&&self[..], &&other[..])
233                 }
234                 #[inline]
235                 fn le(&self, other: &[T; $N]) -> bool {
236                     PartialOrd::le(&&self[..], &&other[..])
237                 }
238                 #[inline]
239                 fn ge(&self, other: &[T; $N]) -> bool {
240                     PartialOrd::ge(&&self[..], &&other[..])
241                 }
242                 #[inline]
243                 fn gt(&self, other: &[T; $N]) -> bool {
244                     PartialOrd::gt(&&self[..], &&other[..])
245                 }
246             }
247
248             #[stable(feature = "rust1", since = "1.0.0")]
249             impl<T:Ord> Ord for [T; $N] {
250                 #[inline]
251                 fn cmp(&self, other: &[T; $N]) -> Ordering {
252                     Ord::cmp(&&self[..], &&other[..])
253                 }
254             }
255         )+
256     }
257 }
258
259 array_impls! {
260      0  1  2  3  4  5  6  7  8  9
261     10 11 12 13 14 15 16 17 18 19
262     20 21 22 23 24 25 26 27 28 29
263     30 31 32
264 }
265
266 // The Default impls cannot be generated using the array_impls! macro because
267 // they require array literals.
268
269 macro_rules! array_impl_default {
270     {$n:expr, $t:ident $($ts:ident)*} => {
271         #[stable(since = "1.4.0", feature = "array_default")]
272         impl<T> Default for [T; $n] where T: Default {
273             fn default() -> [T; $n] {
274                 [$t::default(), $($ts::default()),*]
275             }
276         }
277         array_impl_default!{($n - 1), $($ts)*}
278     };
279     {$n:expr,} => {
280         #[stable(since = "1.4.0", feature = "array_default")]
281         impl<T> Default for [T; $n] {
282             fn default() -> [T; $n] { [] }
283         }
284     };
285 }
286
287 array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}