Implement TryFrom for array reference types

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 commit is contained in:
Nikolai Vazquez 2017-09-21 16:35:23 -04:00
parent 1b55d19479
commit 13221770a3

View file

@ -21,6 +21,7 @@
use borrow::{Borrow, BorrowMut}; use borrow::{Borrow, BorrowMut};
use cmp::Ordering; use cmp::Ordering;
use convert::TryFrom;
use fmt; use fmt;
use hash::{Hash, self}; use hash::{Hash, self};
use marker::Unsize; use marker::Unsize;
@ -57,6 +58,11 @@ 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(());
macro_rules! __impl_slice_eq1 { macro_rules! __impl_slice_eq1 {
($Lhs: ty, $Rhs: ty) => { ($Lhs: ty, $Rhs: ty) => {
__impl_slice_eq1! { $Lhs, $Rhs, Sized } __impl_slice_eq1! { $Lhs, $Rhs, Sized }
@ -123,6 +129,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")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for [T; $N] { impl<T: Hash> Hash for [T; $N] {
fn hash<H: hash::Hasher>(&self, state: &mut H) { fn hash<H: hash::Hasher>(&self, state: &mut H) {