refactor: moving Drain into drain.rs
This commit is contained in:
parent
17593f258b
commit
6bf9608f9f
157
library/alloc/src/vec/drain.rs
Normal file
157
library/alloc/src/vec/drain.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use crate::alloc::{Allocator, Global};
|
||||
use core::iter::{
|
||||
FusedIterator, TrustedLen,
|
||||
};
|
||||
use core::mem::{self};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::slice::{self};
|
||||
use core::fmt;
|
||||
|
||||
use super::{Vec};
|
||||
|
||||
/// A draining iterator for `Vec<T>`.
|
||||
///
|
||||
/// This `struct` is created by [`Vec::drain`].
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = vec![0, 1, 2];
|
||||
/// let iter: std::vec::Drain<_> = v.drain(..);
|
||||
/// ```
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub struct Drain<
|
||||
'a,
|
||||
T: 'a,
|
||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global,
|
||||
> {
|
||||
/// Index of tail to preserve
|
||||
pub(super) tail_start: usize,
|
||||
/// Length of tail
|
||||
pub(super) tail_len: usize,
|
||||
/// Current remaining range to remove
|
||||
pub(super) iter: slice::Iter<'a, T>,
|
||||
pub(super) vec: NonNull<Vec<T, A>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A: Allocator> Drain<'a, T, A> {
|
||||
/// Returns the remaining items of this iterator as a slice.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec = vec!['a', 'b', 'c'];
|
||||
/// let mut drain = vec.drain(..);
|
||||
/// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
|
||||
/// let _ = drain.next().unwrap();
|
||||
/// assert_eq!(drain.as_slice(), &['b', 'c']);
|
||||
/// ```
|
||||
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
self.iter.as_slice()
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying allocator.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
#[inline]
|
||||
pub fn allocator(&self) -> &A {
|
||||
unsafe { self.vec.as_ref().allocator() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
|
||||
impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {}
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> Drop for Drain<'_, T, A> {
|
||||
fn drop(&mut self) {
|
||||
/// Continues dropping the remaining elements in the `Drain`, then moves back the
|
||||
/// un-`Drain`ed elements to restore the original `Vec`.
|
||||
struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
|
||||
|
||||
impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
|
||||
fn drop(&mut self) {
|
||||
// Continue the same loop we have below. If the loop already finished, this does
|
||||
// nothing.
|
||||
self.0.for_each(drop);
|
||||
|
||||
if self.0.tail_len > 0 {
|
||||
unsafe {
|
||||
let source_vec = self.0.vec.as_mut();
|
||||
// memmove back untouched tail, update to new length
|
||||
let start = source_vec.len();
|
||||
let tail = self.0.tail_start;
|
||||
if tail != start {
|
||||
let src = source_vec.as_ptr().add(tail);
|
||||
let dst = source_vec.as_mut_ptr().add(start);
|
||||
ptr::copy(src, dst, self.0.tail_len);
|
||||
}
|
||||
source_vec.set_len(start + self.0.tail_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exhaust self first
|
||||
while let Some(item) = self.next() {
|
||||
let guard = DropGuard(self);
|
||||
drop(item);
|
||||
mem::forget(guard);
|
||||
}
|
||||
|
||||
// Drop a `DropGuard` to move back the non-drained tail of `self`.
|
||||
DropGuard(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
|
@ -84,6 +84,11 @@ pub use self::splice::Splice;
|
||||
|
||||
mod splice;
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub use self::drain::Drain;
|
||||
|
||||
mod drain;
|
||||
|
||||
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
|
||||
///
|
||||
/// # Examples
|
||||
@ -3320,150 +3325,3 @@ impl<T> AsIntoIter for IntoIter<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A draining iterator for `Vec<T>`.
|
||||
///
|
||||
/// This `struct` is created by [`Vec::drain`].
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = vec![0, 1, 2];
|
||||
/// let iter: std::vec::Drain<_> = v.drain(..);
|
||||
/// ```
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub struct Drain<
|
||||
'a,
|
||||
T: 'a,
|
||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global,
|
||||
> {
|
||||
/// Index of tail to preserve
|
||||
tail_start: usize,
|
||||
/// Length of tail
|
||||
tail_len: usize,
|
||||
/// Current remaining range to remove
|
||||
iter: slice::Iter<'a, T>,
|
||||
vec: NonNull<Vec<T, A>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, A: Allocator> Drain<'a, T, A> {
|
||||
/// Returns the remaining items of this iterator as a slice.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec = vec!['a', 'b', 'c'];
|
||||
/// let mut drain = vec.drain(..);
|
||||
/// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
|
||||
/// let _ = drain.next().unwrap();
|
||||
/// assert_eq!(drain.as_slice(), &['b', 'c']);
|
||||
/// ```
|
||||
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
self.iter.as_slice()
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying allocator.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
#[inline]
|
||||
pub fn allocator(&self) -> &A {
|
||||
unsafe { self.vec.as_ref().allocator() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
|
||||
impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {}
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> Drop for Drain<'_, T, A> {
|
||||
fn drop(&mut self) {
|
||||
/// Continues dropping the remaining elements in the `Drain`, then moves back the
|
||||
/// un-`Drain`ed elements to restore the original `Vec`.
|
||||
struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
|
||||
|
||||
impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
|
||||
fn drop(&mut self) {
|
||||
// Continue the same loop we have below. If the loop already finished, this does
|
||||
// nothing.
|
||||
self.0.for_each(drop);
|
||||
|
||||
if self.0.tail_len > 0 {
|
||||
unsafe {
|
||||
let source_vec = self.0.vec.as_mut();
|
||||
// memmove back untouched tail, update to new length
|
||||
let start = source_vec.len();
|
||||
let tail = self.0.tail_start;
|
||||
if tail != start {
|
||||
let src = source_vec.as_ptr().add(tail);
|
||||
let dst = source_vec.as_mut_ptr().add(start);
|
||||
ptr::copy(src, dst, self.0.tail_len);
|
||||
}
|
||||
source_vec.set_len(start + self.0.tail_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exhaust self first
|
||||
while let Some(item) = self.next() {
|
||||
let guard = DropGuard(self);
|
||||
drop(item);
|
||||
mem::forget(guard);
|
||||
}
|
||||
|
||||
// Drop a `DropGuard` to move back the non-drained tail of `self`.
|
||||
DropGuard(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
|
||||
|
Loading…
Reference in New Issue
Block a user