diff options
| author | bors <bors@rust-lang.org> | 2017-10-31 23:06:37 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-10-31 23:06:37 +0000 |
| commit | f3b900cc3b122c7e9eb78ca28bec18df68791b08 (patch) | |
| tree | 0fa55ce4def4412af633d90d87e52c18fe195fc9 /src/libcore | |
| parent | 8b22e70b2de5152db3b0c53cfa16eb96b0b9e40e (diff) | |
| parent | 4c853adce9103b8bc84cd6b0026bcdc2eed7da31 (diff) | |
Auto merge of #44764 - nvzqz:master, r=alexcrichton
Implement TryFrom<&[T]> for &[T; N] There are many cases where a buffer with a static compile-time size is preferred over a slice with a dynamic size. This allows for performing a checked conversion from `&[T]` to `&[T; N]`. This may also lead to compile-time optimizations involving `[T; N]` such as loop unrolling. This is my first PR to Rust, so I'm not sure if discussion of this change should happen here or does it need its own RFC? I figured these changes would be a subset of #33417.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/array.rs | 53 | ||||
| -rw-r--r-- | src/libcore/tests/array.rs | 23 |
2 files changed, 76 insertions, 0 deletions
diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 6a7926fecde..3d24f8902bd 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -21,6 +21,7 @@ use borrow::{Borrow, BorrowMut}; use cmp::Ordering; +use convert::TryFrom; use fmt; use hash::{Hash, self}; use marker::Unsize; @@ -57,6 +58,30 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A { } } +/// The error type returned when a conversion from a slice to an array fails. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Debug, Copy, Clone)] +pub struct TryFromSliceError(()); + +impl fmt::Display for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.__description(), f) + } +} + +impl TryFromSliceError { + #[unstable(feature = "array_error_internals", + reason = "available through Error trait and this method should not \ + be exposed publicly", + issue = "0")] + #[inline] + #[doc(hidden)] + pub fn __description(&self) -> &str { + "could not convert slice to array" + } +} + macro_rules! __impl_slice_eq1 { ($Lhs: ty, $Rhs: ty) => { __impl_slice_eq1! { $Lhs, $Rhs, Sized } @@ -123,6 +148,34 @@ macro_rules! array_impls { } } + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { + type Error = TryFromSliceError; + + fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { + if slice.len() == $N { + let ptr = slice.as_ptr() as *const [T; $N]; + unsafe { Ok(&*ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + + #[unstable(feature = "try_from", issue = "33417")] + impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { + type Error = TryFromSliceError; + + fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> { + if slice.len() == $N { + let ptr = slice.as_mut_ptr() as *mut [T; $N]; + unsafe { Ok(&mut *ptr) } + } else { + Err(TryFromSliceError(())) + } + } + } + #[stable(feature = "rust1", since = "1.0.0")] impl<T: Hash> Hash for [T; $N] { fn hash<H: hash::Hasher>(&self, state: &mut H) { diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index 6af031dee58..6278d5e23e0 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use core::array::FixedSizeArray; +use core::convert::TryFrom; #[test] fn fixed_size_array() { @@ -26,3 +27,25 @@ fn fixed_size_array() { assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } + +#[test] +fn array_try_from() { + macro_rules! test { + ($($N:expr)+) => { + $({ + type Array = [u8; $N]; + let array: Array = [0; $N]; + let slice: &[u8] = &array[..]; + + let result = <&Array>::try_from(slice); + assert_eq!(&array, result.unwrap()); + })+ + } + } + test! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 + } +} |
