diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6f125cdba8190..c8540c53d4ff9 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -61,6 +61,7 @@ use raw_vec::RawVec; use core::any::Any; use core::borrow; use core::cmp::Ordering; +use core::convert::TryFrom; use core::fmt; use core::hash::{self, Hash, Hasher}; use core::iter::FusedIterator; @@ -623,6 +624,79 @@ impl From> for Box<[u8]> { } } +/// The error type returned when a conversion from a boxed slice to a boxed +/// array fails. +#[unstable(feature = "try_from", issue = "33417")] +#[derive(Clone)] +pub struct TryFromSliceError(Box<[T]>); + +#[unstable(feature = "try_from", issue = "33417")] +impl fmt::Debug for TryFromSliceError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("TryFromSliceError").finish() + } +} + +#[unstable(feature = "try_from", issue = "33417")] +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 boxed slice to boxed array" + } + + /// Returns the boxed slice that was attempted to convert to a boxed array. + /// + /// This method is meant to avoid allocation. It will consume the error, + /// moving out the boxed slice, so that a copy of the slice does not need to + /// be made. + #[unstable(feature = "try_from", issue = "33417")] + #[inline] + pub fn into_boxed_slice(self) -> Box<[T]> { + self.0 + } +} + +macro_rules! array_impls { + ($($N:expr)+) => { + $( + #[unstable(feature = "try_from", issue = "33417")] + impl TryFrom> for Box<[T; $N]> { + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: Box<[T]>) -> Result, TryFromSliceError> { + if slice.len() == $N { + let ptr = Box::into_raw(slice) as *mut [T; $N]; + unsafe { Ok(Box::from_raw(ptr)) } + } else { + Err(TryFromSliceError(slice)) + } + } + } + )+ + } +} + +array_impls! { + 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 +} + impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 3cc3ea467966b..903cd73703b50 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -118,6 +118,7 @@ #![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] +#![feature(try_from)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd83..77087b55bcd90 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -152,6 +152,7 @@ macro_rules! array_impls { impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; + #[inline] fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> { if slice.len() == $N { let ptr = slice.as_ptr() as *const [T; $N]; @@ -166,6 +167,7 @@ macro_rules! array_impls { impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { type Error = TryFromSliceError; + #[inline] 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]; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index eb5022ad5776a..a55807766c9e1 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -54,6 +54,7 @@ use alloc::allocator; use any::TypeId; use borrow::Cow; +use boxed; use cell; use char; use convert; @@ -290,6 +291,13 @@ impl Error for array::TryFromSliceError { } } +#[unstable(feature = "try_from", issue = "33417")] +impl Error for boxed::TryFromSliceError { + fn description(&self) -> &str { + self.__description() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseFloatError { fn description(&self) -> &str {