| // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| // Exceptions. See /LICENSE for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| extern crate alloc; |
| use alloc::borrow::Borrow; |
| use alloc::borrow::BorrowMut; |
| use core::cmp::Ordering; |
| |
| use alloc::collections::TryReserveError; |
| use alloc::vec::Vec; |
| #[cfg(sanitize = "address")] |
| use core::ffi::c_void; |
| use core::fmt::Debug; |
| use core::hash::Hash; |
| use core::hash::Hasher; |
| use core::iter::FromIterator; |
| use core::mem::ManuallyDrop; |
| use core::ops::RangeBounds; |
| use core::ops::{Deref, DerefMut}; |
| use core::ops::{Index, IndexMut}; |
| use core::slice; |
| use core::slice::SliceIndex; |
| |
| use crate::crubit_cc_std_internal::std_allocator as cpp_std_allocator; |
| |
| extern "C" { |
| // https://github.com/llvm/llvm-project/blob/9d0616ce52fc2a75c8e4808adec41d5189f4240c/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h#L70 |
| #[cfg(sanitize = "address")] |
| fn __sanitizer_annotate_contiguous_container( |
| beg: *const c_void, |
| end: *const c_void, |
| old_mid: *const c_void, |
| new_mid: *const c_void, |
| ); |
| } |
| |
| /// A mutable, contiguous, dynamically-sized container of elements |
| /// of type `T`, ABI-compatible with `std::vector` from C++. |
| /// 2 layouts are supported. |
| /// 1. This layout was found empirically on Linux with modern g++ and libc++. If |
| /// for some version of libc++ it is different, we will need to update it with |
| /// conditional compilation. |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| #[repr(C)] |
| pub struct vector<T> { |
| // Note: the pointers are mutable, but `const` for covariance. |
| begin: *const T, |
| _end: *const T, |
| _capacity_end: *const T, |
| } |
| |
| /// 2. This layout is experimental. |
| #[cfg(feature = "len_capacity_encoding")] |
| #[repr(C)] |
| pub struct vector<T> { |
| /// The pointer to the first element of the vector. |
| /// |
| /// This pointer is mutable, but `const` for covariance. |
| begin: *const T, |
| len: usize, |
| capacity: usize, |
| } |
| |
| impl<T> vector<T> { |
| pub fn new() -> vector<T> { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| vector { begin: core::ptr::null_mut(), len: 0, capacity: 0 } |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| vector { |
| begin: core::ptr::null_mut(), |
| _end: core::ptr::null_mut(), |
| _capacity_end: core::ptr::null_mut(), |
| } |
| } |
| } |
| |
| pub fn len(&self) -> usize { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| self.len |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| use core::convert::TryInto; |
| // SAFETY: |
| // 1: self.begin - self._end are either both null (for the empty vector), |
| // or point to the beginning and ending of the vector inside the allocation |
| // for the vector. |
| // 2: The vector is aligned for `T`. |
| unsafe { self._end.offset_from(self.begin).try_into().unwrap() } |
| } |
| } |
| |
| pub fn is_empty(&self) -> bool { |
| self.len() == 0 |
| } |
| |
| pub fn capacity(&self) -> usize { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| self.capacity |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| use core::convert::TryInto; |
| // SAFETY: |
| // 1: self.begin - self._capacity_end are either both null (for the empty vector), |
| // or point to the beginning and ending of the whole allocation for the vector. |
| // 2: The vector is aligned for `T`. |
| unsafe { self._capacity_end.offset_from(self.begin).try_into().unwrap() } |
| } |
| } |
| |
| fn end(&self) -> *mut T { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| unsafe { self.begin.add(self.len) as *mut _ } |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| self._end as *mut _ |
| } |
| } |
| |
| fn capacity_end(&self) -> *mut T { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| unsafe { self.begin.add(self.capacity) as *mut _ } |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| self._capacity_end as *mut _ |
| } |
| } |
| |
| /// Sets the begin, len and capacity of the vector. |
| /// |
| /// This function overrides the pointer `self.begin` w/o deleting the |
| /// pointed memory. That is the responsibility of the caller to ensure that |
| /// no leaks occur. |
| /// |
| /// # Safety |
| /// |
| /// - `begin` must be a null and (len == capacity == 0) or `begin` must be |
| /// a valid pointer and the memory pointed by `begin` must be allocated |
| /// with `StdAllocator`. |
| /// - `len` must be less than or equal to `capacity`. |
| /// - The first `len` values must be properly initialized values of type |
| /// `T`. |
| /// - The size of `T `times the `capacity` (i.e. the allocated size in |
| /// bytes) needs to be the same size as the pointer was allocated with. |
| /// - `T` needs to have the same alignment as what `begin` was allocated |
| /// with. |
| /// - nothing else believes to have ownership over the memory of `begin`, |
| /// and that no outstanding references to this memory are still present by |
| /// the time `self` is next used. |
| /// |
| /// These requirements are always upheld by any `begin` that has been |
| /// allocated via Vec<T, StdAllocator> and the corresponding Vec is |
| /// forgotten after the call of this function. It follows by the properties |
| /// of the `Vec`. |
| unsafe fn set_begin_len_capacity(&mut self, begin: *mut T, len: usize, capacity: usize) { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| self.begin = begin as *const _; |
| self.len = len; |
| self.capacity = capacity; |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| self.begin = begin as *const _; |
| self._end = self.begin.add(len); |
| self._capacity_end = self.begin.add(capacity); |
| } |
| } |
| |
| /// Prepares the vector to write into the tail. |
| /// See docstring of [`vector::set_len`] for more details. |
| pub fn prepare_to_write_into_tail(&mut self) { |
| self.asan_unpoison_tail(); |
| } |
| |
| /// Sets the length of the vector. |
| /// |
| /// # Safety |
| /// |
| /// - `new_len` must be less than or equal to [`capacity()`]. |
| /// - The elements at `old_len..new_len` must be initialized. |
| /// |
| /// See [`alloc::vec::Vec::set_len`] for more details. |
| /// |
| /// The difference with `alloc::vec::Vec::set_len` is that the tail of the |
| /// vector is poisoned with ASan, so when writing to the tail for |
| /// avoiding ASan errors [`vector::prepare_to_write_into_tail`] must be |
| /// called first: |
| /// ``` |
| /// v.prepare_to_write_into_tail() |
| /// // write to tail (i.e. between v.len() and v.capacity()) |
| /// v.set_len(len) |
| /// ``` |
| pub unsafe fn set_len(&mut self, len: usize) { |
| #[cfg(feature = "len_capacity_encoding")] |
| { |
| self.len = len; |
| } |
| #[cfg(not(feature = "len_capacity_encoding"))] |
| { |
| self._end = self.begin.add(len); |
| } |
| self.asan_poison_tail(); |
| } |
| |
| #[inline] |
| #[cfg(not(sanitize = "address"))] |
| fn asan_poison_tail(&self) {} |
| |
| #[inline] |
| #[cfg(not(sanitize = "address"))] |
| fn asan_unpoison_tail(&self) {} |
| |
| #[inline] |
| #[cfg(sanitize = "address")] |
| fn asan_poison_tail(&self) { |
| // C++ std::vector supports an ASan container annotation feature |
| // (https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow) |
| // that allows ASan to detect reads and writes in the uninitialized tail of the |
| // std::vector's storage (between the end iterator and capacity). |
| // |
| // Rust alloc::vec::Vec intentionally does not support this ASan annotation |
| // feature, because it allows users to initialize the elements in the |
| // tail of the storage and then call set_len to tell the Vec about new |
| // elements. |
| // |
| // ASan uses the term "poisoned" for data that cannot be accessed. When marking |
| // data as inaccessible, we poison it, to make them accessible we |
| // unpoison the data. So, the tail of a Rust Vec's storage is always |
| // unpoisoned, even when ASan is enabled. |
| // |
| // Thus, when we use Rust Vec to implement operations on C++ std::vector's |
| // storage, we hit an incompatibility: the tail of the C++ std::vector |
| // is poisoned, but Rust Vec does not unpoison before writing into it. |
| // |
| // Therefore, when we create a Rust Vec using the storage of a C++ std::vector |
| // we need to establish the ASan poision/unpoison invariants that the Rust Vec |
| // expects. Specifically, we unpoison the storage before a Rust Vec |
| // writes into the uninitialized tail. Furthermore, once we are done |
| // using a Rust Vec to manipulate the storage, we poison the tail agail. |
| // |
| // As an optimization we don't poison/unpoison the tail when we create a Rust |
| // Vec purely to perform reads, or to mutate existing elements in-place. |
| unsafe { |
| // The following call is the same as __annotate_new in C++ std::vector |
| // https://github.com/llvm/llvm-project/blob/9d0616ce52fc2a75c8e4808adec41d5189f4240c/libcxx/include/vector#L920 |
| __sanitizer_annotate_contiguous_container( |
| self.begin as *const c_void, |
| self.capacity_end() as *const c_void, |
| self.capacity_end() as *const c_void, |
| self.end() as *const c_void, |
| ); |
| } |
| } |
| |
| #[inline] |
| #[cfg(sanitize = "address")] |
| fn asan_unpoison_tail(&self) { |
| unsafe { |
| // The following call is the same as __annotate_delete in C++ |
| // std::vector https://github.com/llvm/llvm-project/blob/9d0616ce52fc2a75c8e4808adec41d5189f4240c/libcxx/include/vector#L927 |
| __sanitizer_annotate_contiguous_container( |
| self.begin as *const c_void, |
| self.capacity_end() as *const c_void, |
| self.end() as *const c_void, |
| self.capacity_end() as *const c_void, |
| ); |
| } |
| } |
| } |
| |
| impl<T: Unpin> vector<T> { |
| /// Mutates `self` as if it were a `Vec<T>`. |
| fn mutate_self_as_vec<F, R>(&mut self, mutate_self: F) -> R |
| where |
| F: FnOnce(&mut Vec<T, cpp_std_allocator::StdAllocator>) -> R, |
| { |
| unsafe { |
| self.asan_unpoison_tail(); |
| let mut v = ManuallyDrop::new(create_vec_from_raw_parts( |
| self.begin as *mut _, |
| self.len(), |
| self.capacity(), |
| )); |
| let result = mutate_self(v.deref_mut()); |
| self.set_begin_len_capacity(v.as_mut_ptr(), v.len(), v.capacity()); |
| self.asan_poison_tail(); |
| result |
| } |
| } |
| |
| // Methods for changing the capacity of the vector. |
| pub fn reserve(&mut self, capacity: usize) { |
| self.mutate_self_as_vec(|v| v.reserve(capacity)); |
| } |
| |
| pub fn reserve_exact(&mut self, additional: usize) { |
| self.mutate_self_as_vec(|v| v.reserve_exact(additional)); |
| } |
| |
| pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { |
| self.mutate_self_as_vec(|v| v.try_reserve(additional)) |
| } |
| |
| pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { |
| self.mutate_self_as_vec(|v| v.try_reserve_exact(additional)) |
| } |
| |
| pub fn shrink_to_fit(&mut self) { |
| self.mutate_self_as_vec(|v| v.shrink_to_fit()); |
| } |
| |
| pub fn shrink_to(&mut self, min_capacity: usize) { |
| self.mutate_self_as_vec(|v| v.shrink_to(min_capacity)); |
| } |
| |
| pub fn with_capacity(capacity: usize) -> vector<T> { |
| let mut result = vector::new(); |
| result.reserve(capacity); |
| result |
| } |
| |
| // Methods for adding elements to the vector. |
| pub fn push(&mut self, value: T) { |
| self.mutate_self_as_vec(|v| v.push(value)); |
| } |
| |
| pub fn insert(&mut self, index: usize, element: T) { |
| self.mutate_self_as_vec(|v| v.insert(index, element)); |
| } |
| |
| pub fn append(&mut self, other: &mut Self) { |
| self.mutate_self_as_vec(|v| other.mutate_self_as_vec(|other_v| v.append(other_v))) |
| } |
| |
| // Methods for deleting elements from the vector. |
| pub fn swap_remove(&mut self, index: usize) -> T { |
| self.mutate_self_as_vec(|v| v.swap_remove(index)) |
| } |
| |
| pub fn remove(&mut self, index: usize) -> T { |
| self.mutate_self_as_vec(|v| v.remove(index)) |
| } |
| |
| pub fn pop(&mut self) -> Option<T> { |
| self.mutate_self_as_vec(|v| v.pop()) |
| } |
| |
| pub fn clear(&mut self) { |
| self.mutate_self_as_vec(|v| v.clear()); |
| } |
| |
| pub fn truncate(&mut self, len: usize) { |
| self.mutate_self_as_vec(|v| v.truncate(len)); |
| } |
| |
| // Different vector transformations. |
| pub fn dedup_by<F>(&mut self, same_bucket: F) |
| where |
| F: FnMut(&mut T, &mut T) -> bool, |
| { |
| self.mutate_self_as_vec(|v| v.dedup_by(same_bucket)); |
| } |
| |
| pub fn dedup_by_key<F, K>(&mut self, key: F) |
| where |
| F: FnMut(&mut T) -> K, |
| K: PartialEq, |
| { |
| self.mutate_self_as_vec(|v| v.dedup_by_key(key)); |
| } |
| |
| pub fn retain<F>(&mut self, f: F) |
| where |
| F: FnMut(&T) -> bool, |
| { |
| self.mutate_self_as_vec(|v| v.retain(f)); |
| } |
| |
| pub fn retain_mut<F>(&mut self, f: F) |
| where |
| F: FnMut(&mut T) -> bool, |
| { |
| self.mutate_self_as_vec(|v| v.retain_mut(f)); |
| } |
| |
| pub fn split_off(&mut self, at: usize) -> Self { |
| vector::from(self.mutate_self_as_vec(|v| v.split_off(at))) |
| } |
| |
| // Methods returning different vector representations. |
| pub fn into_vec(mut self) -> Vec<T> { |
| let mut result = Vec::<T>::with_capacity(self.len()); |
| unsafe { |
| core::ptr::copy_nonoverlapping(self.as_ptr(), result.as_mut_ptr(), self.len()); |
| result.set_len(self.len()); |
| |
| // The elements were moved out. Now mark `self` empty, without calling drop on |
| // elements. |
| self.asan_unpoison_tail(); |
| self.set_len(0); |
| } |
| result |
| } |
| |
| pub fn as_ptr(&self) -> *const T { |
| self.begin |
| } |
| |
| pub fn as_mut_ptr(&mut self) -> *mut T { |
| self.begin as *mut _ |
| } |
| |
| pub fn as_slice(&self) -> &[T] { |
| unsafe { |
| if self.begin.is_null() { |
| &[] |
| } else { |
| core::slice::from_raw_parts(self.begin, self.len()) |
| } |
| } |
| } |
| |
| pub fn as_mut_slice(&mut self) -> &mut [T] { |
| unsafe { |
| if self.begin.is_null() { |
| &mut [] |
| } else { |
| core::slice::from_raw_parts_mut(self.begin as *mut _, self.len()) |
| } |
| } |
| } |
| } |
| |
| impl<T: Unpin + Clone> vector<T> { |
| pub fn extend_from_slice(&mut self, src: &[T]) { |
| self.mutate_self_as_vec(|v| v.extend_from_slice(src)); |
| } |
| |
| pub fn extend_from_within<R>(&mut self, src: R) |
| where |
| R: RangeBounds<usize>, |
| { |
| self.mutate_self_as_vec(|v| v.extend_from_within(src)); |
| } |
| |
| pub fn resize(&mut self, new_len: usize, value: T) { |
| self.mutate_self_as_vec(|v| v.resize(new_len, value)); |
| } |
| |
| pub fn resize_with<F>(&mut self, new_len: usize, f: F) |
| where |
| F: FnMut() -> T, |
| { |
| self.mutate_self_as_vec(|v| v.resize_with(new_len, f)); |
| } |
| } |
| |
| impl<T: Unpin + PartialEq> vector<T> { |
| pub fn dedup(&mut self) { |
| self.mutate_self_as_vec(|v| v.dedup()); |
| } |
| } |
| |
| impl<T> AsRef<vector<T>> for vector<T> { |
| fn as_ref(&self) -> &vector<T> { |
| self |
| } |
| } |
| |
| impl<T> AsMut<vector<T>> for vector<T> { |
| fn as_mut(&mut self) -> &mut vector<T> { |
| self |
| } |
| } |
| |
| impl<T: Unpin> AsRef<[T]> for vector<T> { |
| fn as_ref(&self) -> &[T] { |
| self.as_slice() |
| } |
| } |
| |
| impl<T: Unpin> AsMut<[T]> for vector<T> { |
| fn as_mut(&mut self) -> &mut [T] { |
| self.as_mut_slice() |
| } |
| } |
| |
| impl<T: Unpin> Borrow<[T]> for vector<T> { |
| fn borrow(&self) -> &[T] { |
| self.as_slice() |
| } |
| } |
| |
| impl<T: Unpin> BorrowMut<[T]> for vector<T> { |
| fn borrow_mut(&mut self) -> &mut [T] { |
| self.as_mut_slice() |
| } |
| } |
| |
| impl<T: Unpin + Debug> Debug for vector<T> { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| f.debug_list().entries(self.as_slice()).finish() |
| } |
| } |
| |
| impl<T> Default for vector<T> { |
| fn default() -> Self { |
| Self::new() |
| } |
| } |
| |
| impl<T> Drop for vector<T> { |
| fn drop(&mut self) { |
| if !self.begin.is_null() { |
| unsafe { |
| self.asan_unpoison_tail(); |
| _ = Vec::from_raw_parts_in( |
| self.begin as *mut T, |
| self.len(), |
| self.capacity(), |
| cpp_std_allocator::StdAllocator {}, |
| ); |
| } |
| } |
| } |
| } |
| |
| impl<T: Unpin, I: SliceIndex<[T]>> Index<I> for vector<T> { |
| type Output = I::Output; |
| fn index(&self, index: I) -> &Self::Output { |
| self.as_slice().index(index) |
| } |
| } |
| |
| impl<T: Unpin, I: SliceIndex<[T]>> IndexMut<I> for vector<T> { |
| fn index_mut(&mut self, index: I) -> &mut Self::Output { |
| self.as_mut_slice().index_mut(index) |
| } |
| } |
| |
| impl<T> Deref for vector<T> { |
| type Target = [T]; |
| fn deref(&self) -> &Self::Target { |
| if self.is_empty() { |
| &[] |
| } else { |
| unsafe { core::slice::from_raw_parts(self.begin, self.len()) } |
| } |
| } |
| } |
| |
| impl<T: Unpin> DerefMut for vector<T> { |
| fn deref_mut(&mut self) -> &mut Self::Target { |
| if self.is_empty() { |
| &mut [] |
| } else { |
| unsafe { core::slice::from_raw_parts_mut(self.begin as *mut _, self.len()) } |
| } |
| } |
| } |
| |
| impl<T: Clone> vector<T> { |
| /// Clone elements from `self` to `Vec<T>`. |
| pub fn to_vec(&self) -> Vec<T> { |
| let mut v = Vec::<T>::with_capacity(self.len()); |
| for el in self.iter() { |
| v.push(el.clone()); |
| } |
| v |
| } |
| } |
| |
| impl<T: Unpin + Clone> Clone for vector<T> { |
| fn clone(&self) -> Self { |
| unsafe { |
| let vec = ManuallyDrop::new(create_vec_from_raw_parts( |
| self.begin as *mut _, |
| self.len(), |
| self.capacity(), |
| )); |
| vector::from((*vec).clone()) |
| } |
| } |
| } |
| |
| impl<T: Unpin> Extend<T> for vector<T> { |
| fn extend<I>(&mut self, iter: I) |
| where |
| I: IntoIterator<Item = T>, |
| { |
| self.mutate_self_as_vec(|v| v.extend(iter)); |
| } |
| } |
| |
| impl<T: Hash + Unpin> Hash for vector<T> { |
| #[inline] |
| fn hash<H: Hasher>(&self, state: &mut H) { |
| self.as_slice().hash(state); |
| } |
| } |
| |
| /// `vector` is `Send` if `T` is `Send` because it uniquely owns its contents. |
| unsafe impl<T: Send> Send for vector<T> {} |
| |
| /// `vector` is `Sync` if `T` is `Sync` because it uniquely owns its contents. |
| unsafe impl<T: Sync> Sync for vector<T> {} |
| |
| impl<T: PartialOrd + Unpin> PartialOrd<vector<T>> for vector<T> { |
| #[inline] |
| fn partial_cmp(&self, other: &vector<T>) -> Option<Ordering> { |
| PartialOrd::partial_cmp(self.as_slice(), other.as_slice()) |
| } |
| } |
| |
| impl<T: Eq> Eq for vector<T> {} |
| |
| impl<T: Ord + Unpin> Ord for vector<T> { |
| #[inline] |
| fn cmp(&self, other: &Self) -> Ordering { |
| Ord::cmp(self.as_slice(), other.as_slice()) |
| } |
| } |
| |
| /// Helper method for creating a `Vec<T>` from raw parts. |
| /// |
| /// # Safety |
| /// |
| /// - `begin` must be a null or `begin` must be a valid pointer and the memory |
| /// pointed by `begin` must be allocated with `StdAllocator`. |
| /// - `len` must be less than or equal to `capacity`. |
| /// - The first `len` values must be properly initialized values of type `T`. |
| /// - The size of `T `times the `capacity` (i.e. the allocated size in bytes) |
| /// needs to be the same size as the pointer was allocated with. |
| /// - `T` needs to have the same alignment as what `begin` was allocated with. |
| /// |
| /// These requirements are always upheld by any `begin` that has been |
| /// allocated via Vec<T, StdAllocator>. |
| unsafe fn create_vec_from_raw_parts<T>( |
| begin: *mut T, |
| len: usize, |
| capacity: usize, |
| ) -> Vec<T, cpp_std_allocator::StdAllocator> { |
| if begin.is_null() { |
| Vec::new_in(cpp_std_allocator::StdAllocator {}) |
| } else { |
| Vec::from_raw_parts_in(begin, len, capacity, cpp_std_allocator::StdAllocator {}) |
| } |
| } |
| |
| mod iter { |
| use super::alloc; |
| use super::cpp_std_allocator; |
| use super::vector; |
| use core::fmt; |
| use core::fmt::Debug; |
| use core::iter::FusedIterator; |
| /// An iterator that moves out of a vector. |
| /// |
| /// This type is currently a wrapper around `alloc::vec::IntoIter`, |
| /// however users should not depend on it, and the wrapped iterator |
| /// should not be made public. If the current implementation |
| /// strategy stops working, the wrapped iterator will be replaced with |
| /// a more complex implementation. |
| pub struct VectorIntoIter<T>(alloc::vec::IntoIter<T, cpp_std_allocator::StdAllocator>); |
| |
| impl<T> VectorIntoIter<T> { |
| pub fn new(v: alloc::vec::IntoIter<T, cpp_std_allocator::StdAllocator>) -> Self { |
| VectorIntoIter(v) |
| } |
| |
| /// Returns the remaining items of this iterator as a slice. |
| #[inline] |
| pub fn as_slice(&mut self) -> &[T] { |
| self.0.as_slice() |
| } |
| |
| /// Returns the remaining items of this iterator as a mutable slice. |
| #[inline] |
| pub fn as_mut_slice(&mut self) -> &mut [T] { |
| self.0.as_mut_slice() |
| } |
| } |
| |
| impl<T> Iterator for VectorIntoIter<T> { |
| type Item = T; |
| |
| #[inline] |
| fn next(&mut self) -> Option<Self::Item> { |
| self.0.next() |
| } |
| #[inline] |
| fn size_hint(&self) -> (usize, Option<usize>) { |
| self.0.size_hint() |
| } |
| |
| // TODO(b/356638830): Uncomment when feature advance_by is stable |
| // fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { |
| // self.0.advance_by(n) |
| // } |
| |
| #[inline] |
| fn count(self) -> usize { |
| self.0.len() |
| } |
| } |
| |
| impl<T> AsRef<[T]> for VectorIntoIter<T> { |
| fn as_ref(&self) -> &[T] { |
| self.0.as_ref() |
| } |
| } |
| |
| impl<T: fmt::Debug> Debug for VectorIntoIter<T> { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| self.0.fmt(f) |
| } |
| } |
| |
| impl<T: Unpin> Default for VectorIntoIter<T> { |
| fn default() -> Self { |
| vector::<T>::default().into_iter() |
| } |
| } |
| |
| impl<T> DoubleEndedIterator for VectorIntoIter<T> { |
| #[inline] |
| fn next_back(&mut self) -> Option<T> { |
| self.0.next_back() |
| } |
| |
| // TODO(b/356638830): Uncomment when feature advance_back_by is stable |
| // #[inline] |
| // fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { |
| // self.0.advance_back_by() |
| // } |
| } |
| |
| impl<T> ExactSizeIterator for VectorIntoIter<T> { |
| // TODO(b/356638830): Uncomment when feature is_empty is stable |
| // #[inline] |
| // fn is_empty(&self) -> bool { |
| // self.0.is_empty() |
| // } |
| } |
| |
| impl<T> FusedIterator for VectorIntoIter<T> {} |
| // TODO(b/356638830): Uncomment when feature TrustedLen is stable |
| // unsafe impl<T> TrustedLen for VectorIntoIter<T> {} |
| } |
| |
| use iter::*; |
| |
| impl<T: Unpin> IntoIterator for vector<T> { |
| type Item = T; |
| type IntoIter = VectorIntoIter<T>; |
| fn into_iter(self) -> Self::IntoIter { |
| #[allow(unused_unsafe)] |
| unsafe { |
| self.asan_unpoison_tail(); |
| let v = create_vec_from_raw_parts(self.begin as *mut _, self.len(), self.capacity()); |
| core::mem::forget(self); |
| VectorIntoIter::new(v.into_iter()) |
| } |
| } |
| } |
| |
| impl<'a, T: Unpin> IntoIterator for &'a vector<T> { |
| type Item = &'a T; |
| type IntoIter = slice::Iter<'a, T>; |
| |
| fn into_iter(self) -> Self::IntoIter { |
| self.iter() |
| } |
| } |
| |
| impl<'a, T: Unpin> IntoIterator for &'a mut vector<T> { |
| type Item = &'a mut T; |
| type IntoIter = slice::IterMut<'a, T>; |
| |
| fn into_iter(self) -> Self::IntoIter { |
| self.iter_mut() |
| } |
| } |
| |
| impl<T: Unpin> FromIterator<T> for vector<T> { |
| fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { |
| let mut v = Self::new(); |
| v.mutate_self_as_vec(|u| { |
| u.extend(iter); |
| }); |
| v |
| } |
| } |
| |
| impl<T: Unpin> From<vector<T>> for alloc::vec::Vec<T> { |
| fn from(v: vector<T>) -> alloc::vec::Vec<T> { |
| v.into_vec() |
| } |
| } |
| |
| impl<T: Unpin> From<Vec<T>> for vector<T> { |
| fn from(v: Vec<T>) -> Self { |
| // Elements from `v` are moved. It would be more efficient to steal a buffer |
| // from `v`. But `v` might have different allocator than vector. |
| // TODO(b/356221873): Figure out conditions when it is possible to steal buffer |
| // from `v`. |
| let mut result = vector::<T>::with_capacity(v.len()); |
| result.mutate_self_as_vec(|u| { |
| u.extend(v); |
| }); |
| result |
| } |
| } |
| |
| impl<T: Unpin> From<Vec<T, cpp_std_allocator::StdAllocator>> for vector<T> { |
| /// Creates a `vector<T>` from a `Vec<T, StdAllocator>`. |
| /// |
| /// Ownership of elements from `v` are taken by the returned `vector<T>`. |
| fn from(mut v: Vec<T, cpp_std_allocator::StdAllocator>) -> Self { |
| let mut result = vector::new(); |
| // Safety: |
| // |
| // It is safe since the memory is allocated with `Vec<T, StdAllocator>`. |
| unsafe { |
| result.set_begin_len_capacity(v.as_mut_ptr(), v.len(), v.capacity()); |
| core::mem::forget(v); |
| |
| result.asan_poison_tail(); |
| result |
| } |
| } |
| } |
| |
| impl<T: Unpin + Clone> From<&[T]> for vector<T> { |
| fn from(s: &[T]) -> Self { |
| let mut result = vector::<T>::with_capacity(s.len()); |
| result.mutate_self_as_vec(|u| { |
| u.extend_from_slice(s); |
| }); |
| result |
| } |
| } |
| |
| impl<T: Unpin + Clone> From<&mut [T]> for vector<T> { |
| fn from(slice: &mut [T]) -> Self { |
| let mut result = vector::with_capacity(slice.len()); |
| result.mutate_self_as_vec(|u| { |
| u.extend_from_slice(slice); |
| }); |
| result |
| } |
| } |
| |
| impl<T: Unpin + Clone, const N: usize> From<&[T; N]> for vector<T> { |
| fn from(s: &[T; N]) -> Self { |
| Self::from(s.as_slice()) |
| } |
| } |
| impl<T: Unpin + Clone, const N: usize> From<&mut [T; N]> for vector<T> { |
| fn from(s: &mut [T; N]) -> Self { |
| Self::from(s.as_mut_slice()) |
| } |
| } |
| |
| impl<T: Unpin + Clone, const N: usize> From<[T; N]> for vector<T> { |
| fn from(s: [T; N]) -> Self { |
| Self::from(s.as_slice()) |
| } |
| } |