]>
Commit | Line | Data |
---|---|---|
1 | //! Implementations of things like `Eq` for fixed-length arrays | |
2 | //! up to a certain length. Eventually, we should be able to generalize | |
3 | //! to all lengths. | |
4 | //! | |
5 | //! *[See also the array primitive type](../../std/primitive.array.html).* | |
6 | ||
7 | #![stable(feature = "core_array", since = "1.36.0")] | |
8 | ||
9 | use crate::borrow::{Borrow, BorrowMut}; | |
10 | use crate::cmp::Ordering; | |
11 | use crate::convert::{Infallible, TryFrom}; | |
12 | use crate::fmt; | |
13 | use crate::hash::{self, Hash}; | |
14 | use crate::marker::Unsize; | |
15 | use crate::slice::{Iter, IterMut}; | |
16 | ||
17 | mod iter; | |
18 | ||
19 | #[unstable(feature = "array_value_iter", issue = "65798")] | |
20 | pub use iter::IntoIter; | |
21 | ||
22 | /// Converts a reference to `T` into a reference to an array of length 1 (without copying). | |
23 | #[unstable(feature = "array_from_ref", issue = "77101")] | |
24 | pub fn from_ref<T>(s: &T) -> &[T; 1] { | |
25 | // SAFETY: Converting `&T` to `&[T; 1]` is sound. | |
26 | unsafe { &*(s as *const T).cast::<[T; 1]>() } | |
27 | } | |
28 | ||
29 | /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). | |
30 | #[unstable(feature = "array_from_ref", issue = "77101")] | |
31 | pub fn from_mut<T>(s: &mut T) -> &mut [T; 1] { | |
32 | // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. | |
33 | unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } | |
34 | } | |
35 | ||
36 | /// Utility trait implemented only on arrays of fixed size | |
37 | /// | |
38 | /// This trait can be used to implement other traits on fixed-size arrays | |
39 | /// without causing much metadata bloat. | |
40 | /// | |
41 | /// The trait is marked unsafe in order to restrict implementors to fixed-size | |
42 | /// arrays. User of this trait can assume that implementors have the exact | |
43 | /// layout in memory of a fixed size array (for example, for unsafe | |
44 | /// initialization). | |
45 | /// | |
46 | /// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that | |
47 | /// may not be fixed-size arrays. Implementors should prefer those traits | |
48 | /// instead. | |
49 | #[unstable(feature = "fixed_size_array", issue = "27778")] | |
50 | pub unsafe trait FixedSizeArray<T> { | |
51 | /// Converts the array to immutable slice | |
52 | #[unstable(feature = "fixed_size_array", issue = "27778")] | |
53 | fn as_slice(&self) -> &[T]; | |
54 | /// Converts the array to mutable slice | |
55 | #[unstable(feature = "fixed_size_array", issue = "27778")] | |
56 | fn as_mut_slice(&mut self) -> &mut [T]; | |
57 | } | |
58 | ||
59 | #[unstable(feature = "fixed_size_array", issue = "27778")] | |
60 | unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A { | |
61 | #[inline] | |
62 | fn as_slice(&self) -> &[T] { | |
63 | self | |
64 | } | |
65 | #[inline] | |
66 | fn as_mut_slice(&mut self) -> &mut [T] { | |
67 | self | |
68 | } | |
69 | } | |
70 | ||
71 | /// The error type returned when a conversion from a slice to an array fails. | |
72 | #[stable(feature = "try_from", since = "1.34.0")] | |
73 | #[derive(Debug, Copy, Clone)] | |
74 | pub struct TryFromSliceError(()); | |
75 | ||
76 | #[stable(feature = "core_array", since = "1.36.0")] | |
77 | impl fmt::Display for TryFromSliceError { | |
78 | #[inline] | |
79 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
80 | fmt::Display::fmt(self.__description(), f) | |
81 | } | |
82 | } | |
83 | ||
84 | impl TryFromSliceError { | |
85 | #[unstable( | |
86 | feature = "array_error_internals", | |
87 | reason = "available through Error trait and this method should not \ | |
88 | be exposed publicly", | |
89 | issue = "none" | |
90 | )] | |
91 | #[inline] | |
92 | #[doc(hidden)] | |
93 | pub fn __description(&self) -> &str { | |
94 | "could not convert slice to array" | |
95 | } | |
96 | } | |
97 | ||
98 | #[stable(feature = "try_from_slice_error", since = "1.36.0")] | |
99 | impl From<Infallible> for TryFromSliceError { | |
100 | fn from(x: Infallible) -> TryFromSliceError { | |
101 | match x {} | |
102 | } | |
103 | } | |
104 | ||
105 | #[stable(feature = "rust1", since = "1.0.0")] | |
106 | impl<T, const N: usize> AsRef<[T]> for [T; N] { | |
107 | #[inline] | |
108 | fn as_ref(&self) -> &[T] { | |
109 | &self[..] | |
110 | } | |
111 | } | |
112 | ||
113 | #[stable(feature = "rust1", since = "1.0.0")] | |
114 | impl<T, const N: usize> AsMut<[T]> for [T; N] { | |
115 | #[inline] | |
116 | fn as_mut(&mut self) -> &mut [T] { | |
117 | &mut self[..] | |
118 | } | |
119 | } | |
120 | ||
121 | #[stable(feature = "array_borrow", since = "1.4.0")] | |
122 | impl<T, const N: usize> Borrow<[T]> for [T; N] { | |
123 | fn borrow(&self) -> &[T] { | |
124 | self | |
125 | } | |
126 | } | |
127 | ||
128 | #[stable(feature = "array_borrow", since = "1.4.0")] | |
129 | impl<T, const N: usize> BorrowMut<[T]> for [T; N] { | |
130 | fn borrow_mut(&mut self) -> &mut [T] { | |
131 | self | |
132 | } | |
133 | } | |
134 | ||
135 | #[stable(feature = "try_from", since = "1.34.0")] | |
136 | impl<T, const N: usize> TryFrom<&[T]> for [T; N] | |
137 | where | |
138 | T: Copy, | |
139 | { | |
140 | type Error = TryFromSliceError; | |
141 | ||
142 | fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> { | |
143 | <&Self>::try_from(slice).map(|r| *r) | |
144 | } | |
145 | } | |
146 | ||
147 | #[stable(feature = "try_from", since = "1.34.0")] | |
148 | impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { | |
149 | type Error = TryFromSliceError; | |
150 | ||
151 | fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> { | |
152 | if slice.len() == N { | |
153 | let ptr = slice.as_ptr() as *const [T; N]; | |
154 | // SAFETY: ok because we just checked that the length fits | |
155 | unsafe { Ok(&*ptr) } | |
156 | } else { | |
157 | Err(TryFromSliceError(())) | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
162 | #[stable(feature = "try_from", since = "1.34.0")] | |
163 | impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { | |
164 | type Error = TryFromSliceError; | |
165 | ||
166 | fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> { | |
167 | if slice.len() == N { | |
168 | let ptr = slice.as_mut_ptr() as *mut [T; N]; | |
169 | // SAFETY: ok because we just checked that the length fits | |
170 | unsafe { Ok(&mut *ptr) } | |
171 | } else { | |
172 | Err(TryFromSliceError(())) | |
173 | } | |
174 | } | |
175 | } | |
176 | ||
177 | #[stable(feature = "rust1", since = "1.0.0")] | |
178 | impl<T: Hash, const N: usize> Hash for [T; N] { | |
179 | fn hash<H: hash::Hasher>(&self, state: &mut H) { | |
180 | Hash::hash(&self[..], state) | |
181 | } | |
182 | } | |
183 | ||
184 | #[stable(feature = "rust1", since = "1.0.0")] | |
185 | impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] { | |
186 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
187 | fmt::Debug::fmt(&&self[..], f) | |
188 | } | |
189 | } | |
190 | ||
191 | #[stable(feature = "rust1", since = "1.0.0")] | |
192 | impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { | |
193 | type Item = &'a T; | |
194 | type IntoIter = Iter<'a, T>; | |
195 | ||
196 | fn into_iter(self) -> Iter<'a, T> { | |
197 | self.iter() | |
198 | } | |
199 | } | |
200 | ||
201 | #[stable(feature = "rust1", since = "1.0.0")] | |
202 | impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { | |
203 | type Item = &'a mut T; | |
204 | type IntoIter = IterMut<'a, T>; | |
205 | ||
206 | fn into_iter(self) -> IterMut<'a, T> { | |
207 | self.iter_mut() | |
208 | } | |
209 | } | |
210 | ||
211 | #[stable(feature = "rust1", since = "1.0.0")] | |
212 | impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N] | |
213 | where | |
214 | A: PartialEq<B>, | |
215 | { | |
216 | #[inline] | |
217 | fn eq(&self, other: &[B; N]) -> bool { | |
218 | self[..] == other[..] | |
219 | } | |
220 | #[inline] | |
221 | fn ne(&self, other: &[B; N]) -> bool { | |
222 | self[..] != other[..] | |
223 | } | |
224 | } | |
225 | ||
226 | #[stable(feature = "rust1", since = "1.0.0")] | |
227 | impl<A, B, const N: usize> PartialEq<[B]> for [A; N] | |
228 | where | |
229 | A: PartialEq<B>, | |
230 | { | |
231 | #[inline] | |
232 | fn eq(&self, other: &[B]) -> bool { | |
233 | self[..] == other[..] | |
234 | } | |
235 | #[inline] | |
236 | fn ne(&self, other: &[B]) -> bool { | |
237 | self[..] != other[..] | |
238 | } | |
239 | } | |
240 | ||
241 | #[stable(feature = "rust1", since = "1.0.0")] | |
242 | impl<A, B, const N: usize> PartialEq<[A; N]> for [B] | |
243 | where | |
244 | B: PartialEq<A>, | |
245 | { | |
246 | #[inline] | |
247 | fn eq(&self, other: &[A; N]) -> bool { | |
248 | self[..] == other[..] | |
249 | } | |
250 | #[inline] | |
251 | fn ne(&self, other: &[A; N]) -> bool { | |
252 | self[..] != other[..] | |
253 | } | |
254 | } | |
255 | ||
256 | #[stable(feature = "rust1", since = "1.0.0")] | |
257 | impl<'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N] | |
258 | where | |
259 | A: PartialEq<B>, | |
260 | { | |
261 | #[inline] | |
262 | fn eq(&self, other: &&'b [B]) -> bool { | |
263 | self[..] == other[..] | |
264 | } | |
265 | #[inline] | |
266 | fn ne(&self, other: &&'b [B]) -> bool { | |
267 | self[..] != other[..] | |
268 | } | |
269 | } | |
270 | ||
271 | #[stable(feature = "rust1", since = "1.0.0")] | |
272 | impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B] | |
273 | where | |
274 | B: PartialEq<A>, | |
275 | { | |
276 | #[inline] | |
277 | fn eq(&self, other: &[A; N]) -> bool { | |
278 | self[..] == other[..] | |
279 | } | |
280 | #[inline] | |
281 | fn ne(&self, other: &[A; N]) -> bool { | |
282 | self[..] != other[..] | |
283 | } | |
284 | } | |
285 | ||
286 | #[stable(feature = "rust1", since = "1.0.0")] | |
287 | impl<'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N] | |
288 | where | |
289 | A: PartialEq<B>, | |
290 | { | |
291 | #[inline] | |
292 | fn eq(&self, other: &&'b mut [B]) -> bool { | |
293 | self[..] == other[..] | |
294 | } | |
295 | #[inline] | |
296 | fn ne(&self, other: &&'b mut [B]) -> bool { | |
297 | self[..] != other[..] | |
298 | } | |
299 | } | |
300 | ||
301 | #[stable(feature = "rust1", since = "1.0.0")] | |
302 | impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B] | |
303 | where | |
304 | B: PartialEq<A>, | |
305 | { | |
306 | #[inline] | |
307 | fn eq(&self, other: &[A; N]) -> bool { | |
308 | self[..] == other[..] | |
309 | } | |
310 | #[inline] | |
311 | fn ne(&self, other: &[A; N]) -> bool { | |
312 | self[..] != other[..] | |
313 | } | |
314 | } | |
315 | ||
316 | // NOTE: some less important impls are omitted to reduce code bloat | |
317 | // __impl_slice_eq2! { [A; $N], &'b [B; $N] } | |
318 | // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } | |
319 | ||
320 | #[stable(feature = "rust1", since = "1.0.0")] | |
321 | impl<T: Eq, const N: usize> Eq for [T; N] {} | |
322 | ||
323 | #[stable(feature = "rust1", since = "1.0.0")] | |
324 | impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] { | |
325 | #[inline] | |
326 | fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> { | |
327 | PartialOrd::partial_cmp(&&self[..], &&other[..]) | |
328 | } | |
329 | #[inline] | |
330 | fn lt(&self, other: &[T; N]) -> bool { | |
331 | PartialOrd::lt(&&self[..], &&other[..]) | |
332 | } | |
333 | #[inline] | |
334 | fn le(&self, other: &[T; N]) -> bool { | |
335 | PartialOrd::le(&&self[..], &&other[..]) | |
336 | } | |
337 | #[inline] | |
338 | fn ge(&self, other: &[T; N]) -> bool { | |
339 | PartialOrd::ge(&&self[..], &&other[..]) | |
340 | } | |
341 | #[inline] | |
342 | fn gt(&self, other: &[T; N]) -> bool { | |
343 | PartialOrd::gt(&&self[..], &&other[..]) | |
344 | } | |
345 | } | |
346 | ||
347 | /// Implements comparison of arrays lexicographically. | |
348 | #[stable(feature = "rust1", since = "1.0.0")] | |
349 | impl<T: Ord, const N: usize> Ord for [T; N] { | |
350 | #[inline] | |
351 | fn cmp(&self, other: &[T; N]) -> Ordering { | |
352 | Ord::cmp(&&self[..], &&other[..]) | |
353 | } | |
354 | } | |
355 | ||
356 | // The Default impls cannot be generated using the array_impls! macro because | |
357 | // they require array literals. | |
358 | ||
359 | macro_rules! array_impl_default { | |
360 | {$n:expr, $t:ident $($ts:ident)*} => { | |
361 | #[stable(since = "1.4.0", feature = "array_default")] | |
362 | impl<T> Default for [T; $n] where T: Default { | |
363 | fn default() -> [T; $n] { | |
364 | [$t::default(), $($ts::default()),*] | |
365 | } | |
366 | } | |
367 | array_impl_default!{($n - 1), $($ts)*} | |
368 | }; | |
369 | {$n:expr,} => { | |
370 | #[stable(since = "1.4.0", feature = "array_default")] | |
371 | impl<T> Default for [T; $n] { | |
372 | fn default() -> [T; $n] { [] } | |
373 | } | |
374 | }; | |
375 | } | |
376 | ||
377 | 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} | |
378 | ||
379 | #[lang = "array"] | |
380 | impl<T, const N: usize> [T; N] { | |
381 | /// Returns an array of the same size as `self`, with function `f` applied to each element | |
382 | /// in order. | |
383 | /// | |
384 | /// # Examples | |
385 | /// | |
386 | /// ``` | |
387 | /// #![feature(array_map)] | |
388 | /// let x = [1, 2, 3]; | |
389 | /// let y = x.map(|v| v + 1); | |
390 | /// assert_eq!(y, [2, 3, 4]); | |
391 | /// | |
392 | /// let x = [1, 2, 3]; | |
393 | /// let mut temp = 0; | |
394 | /// let y = x.map(|v| { temp += 1; v * temp }); | |
395 | /// assert_eq!(y, [1, 4, 9]); | |
396 | /// | |
397 | /// let x = ["Ferris", "Bueller's", "Day", "Off"]; | |
398 | /// let y = x.map(|v| v.len()); | |
399 | /// assert_eq!(y, [6, 9, 3, 3]); | |
400 | /// ``` | |
401 | #[unstable(feature = "array_map", issue = "75243")] | |
402 | pub fn map<F, U>(self, mut f: F) -> [U; N] | |
403 | where | |
404 | F: FnMut(T) -> U, | |
405 | { | |
406 | use crate::mem::MaybeUninit; | |
407 | struct Guard<T, const N: usize> { | |
408 | dst: *mut T, | |
409 | initialized: usize, | |
410 | } | |
411 | ||
412 | impl<T, const N: usize> Drop for Guard<T, N> { | |
413 | fn drop(&mut self) { | |
414 | debug_assert!(self.initialized <= N); | |
415 | ||
416 | let initialized_part = | |
417 | crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized); | |
418 | // SAFETY: this raw slice will contain only initialized objects | |
419 | // that's why, it is allowed to drop it. | |
420 | unsafe { | |
421 | crate::ptr::drop_in_place(initialized_part); | |
422 | } | |
423 | } | |
424 | } | |
425 | let mut dst = MaybeUninit::uninit_array::<N>(); | |
426 | let mut guard: Guard<U, N> = | |
427 | Guard { dst: MaybeUninit::slice_as_mut_ptr(&mut dst), initialized: 0 }; | |
428 | for (src, dst) in IntoIter::new(self).zip(&mut dst) { | |
429 | dst.write(f(src)); | |
430 | guard.initialized += 1; | |
431 | } | |
432 | // FIXME: Convert to crate::mem::transmute once it works with generics. | |
433 | // unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) } | |
434 | crate::mem::forget(guard); | |
435 | // SAFETY: At this point we've properly initialized the whole array | |
436 | // and we just need to cast it to the correct type. | |
437 | unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) } | |
438 | } | |
439 | ||
440 | /// Returns a slice containing the entire array. Equivalent to `&s[..]`. | |
441 | #[unstable(feature = "array_methods", issue = "76118")] | |
442 | pub fn as_slice(&self) -> &[T] { | |
443 | self | |
444 | } | |
445 | ||
446 | /// Returns a mutable slice containing the entire array. Equivalent to | |
447 | /// `&mut s[..]`. | |
448 | #[unstable(feature = "array_methods", issue = "76118")] | |
449 | pub fn as_mut_slice(&mut self) -> &mut [T] { | |
450 | self | |
451 | } | |
452 | } |