Skip to content

Commit

Permalink
Rollup merge of rust-lang#40389 - F001:placementVecDeque, r=nagisa
Browse files Browse the repository at this point in the history
Implement placement-in protocol for `VecDeque`

CC rust-lang#30172

r? @nagisa
  • Loading branch information
Ariel Ben-Yehuda committed Mar 10, 2017
2 parents f1cd2f2 + 8062cfb commit 1b81660
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 26 deletions.
185 changes: 160 additions & 25 deletions src/libcollections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2797,4 +2931,5 @@ mod tests {
}
}
}

}
1 change: 1 addition & 0 deletions src/libcollectionstest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
extern crate collections;
extern crate test;
extern crate std_unicode;
extern crate core;

use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
Expand Down
24 changes: 23 additions & 1 deletion src/libcollectionstest/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use std::collections::VecDeque;
use std::fmt::Debug;
use std::collections::vec_deque::Drain;
use std::collections::vec_deque::{Drain};

use self::Taggy::*;
use self::Taggypar::*;
Expand Down Expand Up @@ -1000,3 +1000,25 @@ fn test_is_empty() {
assert!(v.iter_mut().is_empty());
assert!(v.into_iter().is_empty());
}

#[test]
fn test_placement_in() {
let mut buf: VecDeque<isize> = VecDeque::new();
buf.place_back() <- 1;
buf.place_back() <- 2;
assert_eq!(buf, [1,2]);

buf.place_front() <- 3;
buf.place_front() <- 4;
assert_eq!(buf, [4,3,1,2]);

{
let ptr_head = buf.place_front() <- 5;
assert_eq!(*ptr_head, 5);
}
{
let ptr_tail = buf.place_back() <- 6;
assert_eq!(*ptr_tail, 6);
}
assert_eq!(buf, [5,4,3,1,2,6]);
}

0 comments on commit 1b81660

Please sign in to comment.