about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-28 19:36:26 +0000
committerbors <bors@rust-lang.org>2015-07-28 19:36:26 +0000
commitba9224f35451e5d5ef7647bd2b40e5da80ce2735 (patch)
tree3866a42e258bbf3a55cb9d683b64818a7b5a88e1 /src/liballoc
parentaa6efd959e450e1cea177a3f6cd6bab6d80d4154 (diff)
parente24423091f0690a83e63ee234bee5627a86b51f0 (diff)
downloadrust-ba9224f35451e5d5ef7647bd2b40e5da80ce2735.tar.gz
rust-ba9224f35451e5d5ef7647bd2b40e5da80ce2735.zip
Auto merge of #26934 - reem:boxed-slice-clone, r=Gankro
Closes #25097
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/boxed.rs55
-rw-r--r--src/liballoc/lib.rs1
2 files changed, 55 insertions, 1 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index d5a177d3ee5..db338eaaf00 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -56,6 +56,7 @@
 use core::prelude::*;
 
 use heap;
+use raw_vec::RawVec;
 
 use core::any::Any;
 use core::cmp::Ordering;
@@ -65,7 +66,7 @@ use core::marker::{self, Unsize};
 use core::mem;
 use core::ops::{CoerceUnsized, Deref, DerefMut};
 use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
-use core::ptr::Unique;
+use core::ptr::{self, Unique};
 use core::raw::{TraitObject};
 
 /// A value that represents the heap. This is the default place that the `box`
@@ -514,3 +515,55 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
 }
 
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
+
+#[stable(feature = "box_slice_clone", since = "1.3.0")]
+impl<T: Clone> Clone for Box<[T]> {
+    fn clone(&self) -> Self {
+        let mut new = BoxBuilder {
+            data: RawVec::with_capacity(self.len()),
+            len: 0
+        };
+
+        let mut target = new.data.ptr();
+
+        for item in self.iter() {
+            unsafe {
+                ptr::write(target, item.clone());
+                target = target.offset(1);
+            };
+
+            new.len += 1;
+        }
+
+        return unsafe { new.into_box() };
+
+        // Helper type for responding to panics correctly.
+        struct BoxBuilder<T> {
+            data: RawVec<T>,
+            len: usize,
+        }
+
+        impl<T> BoxBuilder<T> {
+            unsafe fn into_box(self) -> Box<[T]> {
+                let raw = ptr::read(&self.data);
+                mem::forget(self);
+                raw.into_box()
+            }
+        }
+
+        impl<T> Drop for BoxBuilder<T> {
+            fn drop(&mut self) {
+                let mut data = self.data.ptr();
+                let max = unsafe { data.offset(self.len as isize) };
+
+                while data != max {
+                    unsafe {
+                        ptr::read(data);
+                        data = data.offset(1);
+                    }
+                }
+            }
+        }
+    }
+}
+
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index fce327398e3..03cf4fc9fc1 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -76,6 +76,7 @@
 #![feature(core)]
 #![feature(core_intrinsics)]
 #![feature(core_prelude)]
+#![feature(core_slice_ext)]
 #![feature(custom_attribute)]
 #![feature(fundamental)]
 #![feature(lang_items)]