about summary refs log tree commit diff
path: root/src/libcollections
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-03-10 16:51:43 -0600
committerAlex Crichton <alex@alexcrichton.com>2017-03-10 20:05:04 -0800
commitdcf41821b88bc9c54aaa621f7e744405a33e2238 (patch)
tree22a88fba065d1d5782e2945788001939eefa407d /src/libcollections
parentd0da85d7257413abcb2b6ab59609f2d8d821ba97 (diff)
parent8062cfb37294082ad5825a105e47e0b7b50a7269 (diff)
downloadrust-dcf41821b88bc9c54aaa621f7e744405a33e2238.tar.gz
rust-dcf41821b88bc9c54aaa621f7e744405a33e2238.zip
Rollup merge of #40389 - F001:placementVecDeque, r=nagisa
Implement placement-in protocol for `VecDeque`

CC #30172

r? @nagisa
Diffstat (limited to 'src/libcollections')
-rw-r--r--src/libcollections/vec_deque.rs185
1 files changed, 160 insertions, 25 deletions
diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs
index 8d42045ff16..24f57c50630 100644
--- a/src/libcollections/vec_deque.rs
+++ b/src/libcollections/vec_deque.rs
@@ -22,7 +22,7 @@ use core::cmp::Ordering;
 use core::fmt;
 use core::iter::{repeat, FromIterator, FusedIterator};
 use core::mem;
-use core::ops::{Index, IndexMut};
+use core::ops::{Index, IndexMut, Place, Placer, InPlace};
 use core::ptr;
 use core::ptr::Shared;
 use core::slice;
@@ -1087,14 +1087,7 @@ impl<T> VecDeque<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, value: T) {
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         self.tail = self.wrap_sub(self.tail, 1);
         let tail = self.tail;
@@ -1117,14 +1110,7 @@ impl<T> VecDeque<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_back(&mut self, value: T) {
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         let head = self.head;
         self.head = self.wrap_add(self.head, 1);
@@ -1257,14 +1243,7 @@ impl<T> VecDeque<T> {
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn insert(&mut self, index: usize, value: T) {
         assert!(index <= self.len(), "index out of bounds");
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         // Move the least number of elements in the ring buffer and insert
         // the given object
@@ -1762,6 +1741,69 @@ impl<T> VecDeque<T> {
             self.truncate(len - del);
         }
     }
+
+    // This may panic or abort
+    #[inline]
+    fn grow_if_necessary(&mut self) {
+        if self.is_full() {
+            let old_cap = self.cap();
+            self.buf.double();
+            unsafe {
+                self.handle_cap_increase(old_cap);
+            }
+            debug_assert!(!self.is_full());
+        }
+    }
+
+    /// Returns a place for insertion at the back of the `VecDeque`.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.place_back() <- 3;
+    /// buf.place_back() <- 4;
+    /// assert_eq!(&buf, &[3, 4]);
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "placement protocol is subject to change",
+               issue = "30172")]
+    pub fn place_back(&mut self) -> PlaceBack<T> {
+        PlaceBack { vec_deque: self }
+    }
+
+    /// Returns a place for insertion at the front of the `VecDeque`.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_front`](#method.push_front),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.place_front() <- 3;
+    /// buf.place_front() <- 4;
+    /// assert_eq!(&buf, &[4, 3]);
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "placement protocol is subject to change",
+               issue = "30172")]
+    pub fn place_front(&mut self) -> PlaceFront<T> {
+        PlaceFront { vec_deque: self }
+    }
 }
 
 impl<T: Clone> VecDeque<T> {
@@ -2442,6 +2484,98 @@ impl<T> From<VecDeque<T>> for Vec<T> {
     }
 }
 
+/// A place for insertion at the back of a `VecDeque`.
+///
+/// See [`VecDeque::place_back`](struct.VecDeque.html#method.place_back) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+#[derive(Debug)]
+pub struct PlaceBack<'a, T: 'a> {
+    vec_deque: &'a mut VecDeque<T>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for PlaceBack<'a, T> {
+    type Place = PlaceBack<'a, T>;
+
+    fn make_place(self) -> Self {
+        self.vec_deque.grow_if_necessary();
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for PlaceBack<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { self.vec_deque.ptr().offset(self.vec_deque.head as isize) }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
+    type Owner = &'a mut T;
+
+    unsafe fn finalize(mut self) -> &'a mut T {
+        let head = self.vec_deque.head;
+        self.vec_deque.head = self.vec_deque.wrap_add(head, 1);
+        &mut *(self.vec_deque.ptr().offset(head as isize))
+    }
+}
+
+/// A place for insertion at the front of a `VecDeque`.
+///
+/// See [`VecDeque::place_front`](struct.VecDeque.html#method.place_front) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+#[derive(Debug)]
+pub struct PlaceFront<'a, T: 'a> {
+    vec_deque: &'a mut VecDeque<T>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for PlaceFront<'a, T> {
+    type Place = PlaceFront<'a, T>;
+
+    fn make_place(self) -> Self {
+        self.vec_deque.grow_if_necessary();
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for PlaceFront<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        let tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
+        unsafe { self.vec_deque.ptr().offset(tail as isize) }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for PlaceFront<'a, T> {
+    type Owner = &'a mut T;
+
+    unsafe fn finalize(mut self) -> &'a mut T {
+        self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
+        &mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize))
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use test;
@@ -2797,4 +2931,5 @@ mod tests {
             }
         }
     }
+
 }