diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index abf50a5fe3ec1..9c6fdc217dc42 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,6 +27,7 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(test, allow(deprecated))] // rand +#![cfg_attr(not(test), feature(copy_from_slice))] // impl [T] #![cfg_attr(not(stage0), deny(warnings))] #![feature(alloc)] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index eab69088aa2b9..1446d00b9ea6b 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -837,6 +837,30 @@ impl [T] { core_slice::SliceExt::clone_from_slice(self, src) } + /// Copies all elements from `src` into `self`, using a memcpy. + /// + /// The length of `src` must be the same as `self`. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Example + /// + /// ```rust + /// #![feature(copy_from_slice)] + /// let mut dst = [0, 0, 0]; + /// let src = [1, 2, 3]; + /// + /// dst.copy_from_slice(&src); + /// assert_eq!(src, dst); + /// ``` + #[unstable(feature = "copy_from_slice", issue = "31755")] + pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy { + core_slice::SliceExt::copy_from_slice(self, src) + } + + /// Copies `self` into a new `Vec`. #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 891ca22265e99..bf76d0b847caa 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -16,6 +16,7 @@ #![feature(btree_range)] #![feature(collections)] #![feature(collections_bound)] +#![feature(copy_from_slice)] #![feature(const_fn)] #![feature(fn_traits)] #![feature(enumset)] diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index cde7fcaaf51a2..f3bb58ba45b7e 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -1138,6 +1138,30 @@ fn test_box_slice_clone_panics() { assert_eq!(drop_count.load(Ordering::SeqCst), 8); } +#[test] +fn test_copy_from_slice() { + let src = [0, 1, 2, 3, 4, 5]; + let mut dst = [0; 6]; + dst.copy_from_slice(&src); + assert_eq!(src, dst) +} + +#[test] +#[should_panic(expected = "destination and source slices have different lengths")] +fn test_copy_from_slice_dst_longer() { + let src = [0, 1, 2, 3]; + let mut dst = [0; 5]; + dst.copy_from_slice(&src); +} + +#[test] +#[should_panic(expected = "destination and source slices have different lengths")] +fn test_copy_from_slice_dst_shorter() { + let src = [0, 1, 2, 3]; + let mut dst = [0; 3]; + dst.copy_from_slice(&src); +} + mod bench { use std::{mem, ptr}; use std::__rand::{Rng, thread_rng}; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 40041c748e7ff..afda70f4fcc0a 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -48,7 +48,7 @@ use result::Result; use result::Result::{Ok, Err}; use ptr; use mem; -use marker::{Send, Sync, self}; +use marker::{Copy, Send, Sync, self}; use raw::Repr; // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. use raw::Slice as RawSlice; @@ -152,6 +152,8 @@ pub trait SliceExt { #[stable(feature = "clone_from_slice", since = "1.7.0")] fn clone_from_slice(&mut self, &[Self::Item]) where Self::Item: Clone; + #[unstable(feature = "copy_from_slice", issue = "31755")] + fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; } // Use macros to be generic over const/mut @@ -488,6 +490,16 @@ impl SliceExt for [T] { self[i].clone_from(&src[i]); } } + + #[inline] + fn copy_from_slice(&mut self, src: &[T]) where T: Copy { + assert!(self.len() == src.len(), + "destination and source slices have different lengths"); + unsafe { + ptr::copy_nonoverlapping( + src.as_ptr(), self.as_mut_ptr(), self.len()); + } + } } #[stable(feature = "rust1", since = "1.0.0")]