blob: 5fb2772da3794ed8cd85702246bf380fc839ac89 [file] [log] [blame] [edit]
// 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())
}
}