2022-05-13 10:29:14 -05:00
//! # A [`Vec<T: ?Sized>`]
//!
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
//!
2022-06-08 23:00:11 -05:00
//! This crate is currently stable, but lacks some functionality. To enable this functionality, use the `"unstable"` crate feature, which depends on the following nightly features:
2022-05-13 10:29:14 -05:00
//! - `#![feature(coerce_unsized)]`, to add trait bounds for types which can be unsized to another type.
//!
2022-06-08 23:00:11 -05:00
//! and enables the following functionality (note: these links are probably broken):
//! - [`Vec::push_unsize`]
//! - [`Vec::unsize`]
//! - [`Vec::extend_unsize`]
//!
2022-05-13 10:29:14 -05:00
//! # Examples
//!
2022-05-13 13:14:18 -05:00
//! You can create a vector with [`Vec::new`]:
2022-05-13 10:29:14 -05:00
//!
//! ```
//! # use std::fmt::Debug;
//! # use dyn_vec::prelude::*;
//! let vec: Vec<dyn Debug> = Vec::new();
//! # assert_eq!(format!("{:?}", vec), "[]");
//! ```
//!
//! or with the [`vec!`] macro:
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug;
//! let vec: Vec<i32> = vec![1, 2, 3];
//! // check the docs for `vec!` for more info on this syntax
2022-05-13 13:14:18 -05:00
//! let vec_boxed: Vec<dyn Debug> = vec![box:
//! Box::new(1) as _,
//! Box::new("foo") as _,
//! Box::new(true) as _
//! ];
2022-05-13 10:29:14 -05:00
//! let vec_unsized: Vec<dyn Debug> = vec![unsized: 1, "foo", true];
2022-05-16 10:02:03 -05:00
//! let vec_from_elem: Vec<i32> = vec![3; 5];
//! # assert_eq!(vec, [1, 2, 3]);
2022-05-13 10:29:14 -05:00
//! # assert_eq!(format!("{:?}", vec_boxed), r#"[1, "foo", true]"#);
//! # assert_eq!(format!("{:?}", vec_unsized), r#"[1, "foo", true]"#);
2022-05-16 10:02:03 -05:00
//! # assert_eq!(vec_from_elem, [3; 5]);
2022-05-13 10:29:14 -05:00
//! ```
//!
2022-05-13 13:14:18 -05:00
//! A vector can be pushed to with [`Vec::push`]:
2022-05-13 10:29:14 -05:00
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! let mut vec: Vec<i32> = vec![];
//! vec.push(1);
//! vec.push(2);
//! vec.push(3);
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
//! ```
//!
2022-06-08 23:00:11 -05:00
//! ...and with [`push_box`] and [`push_unsize`] ([`push_unsize_stable`] without the `"unstable"` feature):
2022-05-13 10:29:14 -05:00
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug;
//! let mut vec: Vec<dyn Debug> = vec![];
//! vec.push_box(Box::new(1));
//! vec.push_box(Box::new("foo"));
//! vec.push_box(Box::new(true));
//!
2022-06-08 23:00:11 -05:00
//! // these closures are only needed for the `_stable` versions
//! vec.push_unsize_stable(2, |v| v as _);
//! vec.push_unsize_stable("bar", |v| v as _);
//! vec.push_unsize_stable(false, |v| v as _);
2022-05-13 10:29:14 -05:00
//! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#);
//! ```
//!
2022-06-08 23:00:11 -05:00
//! Finally, a vector can be [`unsize`]d to another vector ([`unsize_stable`] on stable):
2022-05-16 10:02:03 -05:00
//!
2022-05-16 10:42:55 -05:00
//! ```
2022-05-16 10:02:03 -05:00
//! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug;
//! let vec: Vec<i32> = vec![1, 2, 3];
2022-06-08 23:00:11 -05:00
//! // vec.push_unsize_stable("foo", |v| v as _); // not yet...
//! let mut vec: Vec<dyn Debug> = vec.unsize_stable(|v| v as _);
//! vec.push_unsize_stable("foo", |v| v as _); // now we can!
2022-05-16 10:02:03 -05:00
//! # assert_eq!(format!("{:?}", vec), r#"[1, 2, 3, "foo"]"#);
//! ```
//!
2022-06-08 23:00:11 -05:00
//! To use the `_stable` variations, one can generally add the argument `|v| v as _`.
//!
2022-05-13 10:29:14 -05:00
//! # Data Layout
//!
//! ```text
//! Vec<T>
//! ┌────┬────┬────┬────┐
//! │ptr │len │cap │end │
//! └─┬──┴────┴─┬──┴─┬──┘
//! │ │ │
//! │ └────┼───────────────────────────────────────────────┐
//! ┌─┘ └───────────────────┐ │
//! │ │ │
//! ▼ ▼ ▼
//! ┌────┬────┬─────┬──────────┬───┬─────┬───────────────┬───┬───┬───┐
//! │pad │elem│pad │elem │pad│elem │ │ptr│ptr│ptr│
//! └────┴────┴─────┴──────────┴───┴─────┴───────────────┴─┬─┴─┬─┴─┬─┘
//! ▲ ▲ ▲ ▲ │ │ │ ▲
//! │ │ │ └───────────────────────┘ │ │ │
//! │ │ └──────────────────────────────────────────┘ │ │
//! │ └─────────────────────────────────────────────────────────┘ │
//! │ │
//! └─ aligned to 8 also aligned to 8 ─┘
//! ```
//!
2022-05-13 13:14:18 -05:00
//! [`Vec<T: ?Sized>`]: Vec
2022-06-08 23:00:11 -05:00
//! [`Vec::push_unsize`]: Vec::push_unsize
//! [`Vec::unsize`]: Vec::unsize
//! [`Vec::extend_unsize`]: Vec::extend_unsize
2022-05-13 10:29:14 -05:00
//! [`push_box`]: Vec::push_box
//! [`push_unsize`]: Vec::push_unsize
2022-06-08 23:00:11 -05:00
//! [`push_unsize_stable`]: Vec::push_unsize_stable
//! [`unsize`]: Vec::unsize
//! [`unsize_stable`]: Vec::unsize_stable
2022-05-13 10:29:14 -05:00
2022-06-08 23:00:11 -05:00
#![ cfg_attr(feature = " unstable " , feature(coerce_unsized)) ]
2022-05-17 09:47:54 -05:00
// for `mod bad_things`, still a wip
// #![allow(incomplete_features)]
// #![feature(specialization)]
2022-05-11 13:26:53 -05:00
2022-05-13 13:14:18 -05:00
#![ warn(missing_docs) ]
2022-05-16 09:42:00 -05:00
#![ warn(clippy::pedantic) ]
#![ allow(clippy::must_use_candidate) ]
2022-05-13 13:14:18 -05:00
2022-05-11 13:26:53 -05:00
#[ cfg(test) ]
mod test ;
2022-05-17 09:47:54 -05:00
// TODO: maybe remove this? Its not that many imports
2022-05-13 13:14:18 -05:00
/// Prelude, suitable for glob imports.
///
/// Using `prelude::*` will cause a conflict for the `vec!` macro. `prelude::{*, vec}` is recommended.
2022-05-13 10:29:14 -05:00
pub mod prelude {
pub use super ::{ Vec , vec } ;
}
2022-05-11 13:26:53 -05:00
use core ::panic ;
2022-05-12 08:48:32 -05:00
use std ::{
2022-05-17 09:47:54 -05:00
ptr ::{ NonNull , drop_in_place } ,
2022-05-12 08:48:32 -05:00
marker ::PhantomData ,
2022-05-17 09:47:54 -05:00
alloc ::{ Layout , alloc , dealloc } ,
2022-06-08 23:00:11 -05:00
mem ::{ self , size_of , size_of_val , align_of_val } ,
2022-05-12 08:48:32 -05:00
slice ,
2022-06-08 23:00:11 -05:00
ops ::{ Index , IndexMut } ,
2022-05-13 13:14:18 -05:00
any ::Any
2022-05-12 08:48:32 -05:00
} ;
2022-06-08 23:00:11 -05:00
#[ cfg(feature = " unstable " ) ]
use std ::ops ::CoerceUnsized ;
type Coercer < T , U > = for < ' a > fn ( & ' a T ) -> & ' a U ;
2022-05-17 09:47:54 -05:00
mod ptr_ext ;
2022-05-17 09:57:07 -05:00
#[ allow(clippy::wildcard_imports) ]
2022-05-17 09:47:54 -05:00
use ptr_ext ::* ;
mod bad_things ;
2022-05-11 13:26:53 -05:00
2022-05-13 10:29:14 -05:00
/// A heap allocated, dynamic length collection of `?Sized` elements.
2022-05-13 08:32:53 -05:00
///
2022-05-13 10:29:14 -05:00
/// See [`std::vec::Vec`] (the standard library `Vec` type) for more information.
2022-05-13 08:43:19 -05:00
pub struct Vec < T : ? Sized > {
2022-05-13 08:32:53 -05:00
ptr : NonNull < u8 > ,
len : usize ,
capacity : usize ,
end_ptr : NonNull < u8 > ,
2022-05-13 08:43:19 -05:00
_phantom : PhantomData < T >
2022-05-11 13:26:53 -05:00
}
2022-05-13 08:32:53 -05:00
// keeps this file cleaner
mod impls ;
mod iter ;
pub use iter ::* ;
2022-05-13 08:43:19 -05:00
/// The extra data stored at the end of the allocation.
type Extra < T > = * const T ;
2022-05-12 08:48:32 -05:00
2022-05-13 08:43:19 -05:00
impl < T : ? Sized > Vec < T > {
2022-05-13 13:14:18 -05:00
/// Creates a new, empty vector.
2022-05-11 13:26:53 -05:00
pub fn new ( ) -> Self {
let ptr = NonNull ::dangling ( ) ;
Self {
ptr ,
len : 0 ,
capacity : 0 ,
end_ptr : ptr ,
_phantom : PhantomData
}
}
2022-05-16 09:42:00 -05:00
/// Creates a new vector that holds `len` copies of `v`.
///
/// Only avaliable when `T: Sized`.
pub fn from_elem ( v : T , len : usize ) -> Self where T : Sized + Clone {
let mut vec = Self ::with_capacity ( len ) ;
for _ in 0 .. len {
vec . push ( v . clone ( ) ) ;
2022-05-13 08:59:05 -05:00
}
2022-05-16 09:42:00 -05:00
vec
}
/// Creates a new vector that can hold the given amount of `T`s.
///
/// Only avaliable when `T: Sized`.
pub fn with_capacity ( cap : usize ) -> Self where T : Sized {
Self ::with_capacity_for ::< T > ( cap )
}
/// Creates a new vector with the given capacity, measured in bytes.\
pub fn with_capacity_bytes ( cap : usize ) -> Self {
let mut vec = Self ::new ( ) ;
unsafe { vec . realloc ( cap ) ; }
vec
2022-05-13 08:59:05 -05:00
}
2022-05-13 13:14:18 -05:00
/// Creates a new vector with enough capacity to hold the given amount of `U`s.
pub fn with_capacity_for < U > ( cap : usize ) -> Self {
Self ::with_capacity_bytes ( cap * ( size_of ::< U > ( ) + size_of ::< Extra < U > > ( ) ) )
}
/// Appends an element to the end of the vector.
2022-05-13 08:32:53 -05:00
///
/// Only avaliable if `T: Sized`.
2022-05-11 13:26:53 -05:00
pub fn push ( & mut self , v : T ) where T : Sized {
unsafe { self . push_raw ( & v ) }
mem ::forget ( v ) ;
}
2022-05-13 13:14:18 -05:00
/// Appends an (possibly unsized) boxed element to the end of the vector.
2022-05-11 13:26:53 -05:00
pub fn push_box ( & mut self , v : Box < T > ) {
let ptr = Box ::into_raw ( v ) ;
unsafe {
2022-06-08 23:00:11 -05:00
let layout = Layout ::for_value ( & * ptr ) ; // ref it *before* its logically uninit
2022-05-11 13:26:53 -05:00
self . push_raw ( ptr ) ;
2022-06-08 23:00:11 -05:00
dealloc ( ptr . cast ( ) , layout ) ;
2022-05-11 13:26:53 -05:00
}
}
2022-05-13 13:14:18 -05:00
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`.
2022-06-08 23:00:11 -05:00
#[ cfg(feature = " unstable " ) ]
2022-05-11 13:26:53 -05:00
pub fn push_unsize < U > ( & mut self , v : U ) where for < ' a > & ' a U : CoerceUnsized < & ' a T > {
2022-06-08 23:00:11 -05:00
// TODO: maybe make this not call the stable version for perf?
self . push_unsize_stable ( v , | v | v as _ ) ;
}
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn push_unsize_stable < U > ( & mut self , v : U , coercer : Coercer < U , T > ) {
let v_unsized : & T = coercer ( & v ) ;
2022-05-11 13:26:53 -05:00
unsafe { self . push_raw ( v_unsized ) } ;
mem ::forget ( v ) ;
}
unsafe fn push_raw ( & mut self , v : * const T ) {
if ! self . will_fit ( & * v ) {
2022-06-08 23:00:11 -05:00
let new_alloc_size = self . capacity * 2 + size_of_val ( & * v ) * 2 + size_of ::< Extra < T > > ( ) ;
2022-05-11 13:26:53 -05:00
self . realloc ( new_alloc_size ) ;
}
self . push_raw_unchecked ( v ) ;
}
/// Given an element, returns a pointer to where it would be written if it was pushed, assuming no reallocation is needed.
///
/// The pointer will be aligned, but writing to it may overwrite data belonging to the Vec.
/// To check for this, call `will_fit`.
2022-05-13 08:59:05 -05:00
/// In addition, the extra data for the element must be set using `set_extra_from_ptr`.
2022-05-13 08:32:53 -05:00
fn get_next_elem_ptr ( & self , v : & T ) -> * mut u8 {
2022-05-17 09:47:54 -05:00
self . end_ptr . as_ptr ( ) . align_up ( align_of_val ( v ) )
2022-05-11 13:26:53 -05:00
}
2022-05-13 13:14:18 -05:00
/// Checks if a given element will fit in the vector without reallocations.
2022-05-11 13:26:53 -05:00
pub fn will_fit ( & self , v : & T ) -> bool {
2022-05-17 09:47:54 -05:00
let remaining_space = self . get_ptr_to_extra ( self . len ) . addr ( ) - self . end_ptr . as_ptr ( ) . addr ( ) ;
2022-05-13 08:43:19 -05:00
let needed_space = size_of_val ( v ) + size_of ::< Extra < T > > ( ) ;
2022-05-11 13:26:53 -05:00
remaining_space > = needed_space
}
unsafe fn push_raw_unchecked ( & mut self , v : * const T ) {
2022-05-17 09:47:54 -05:00
let dest = self . get_next_elem_ptr ( & * v ) . with_meta_from ( v ) ;
v . copy_val_to ( dest ) ;
self . set_extra_from_ptr ( self . len , dest ) ;
2022-05-11 13:26:53 -05:00
2022-05-17 09:47:54 -05:00
self . end_ptr = NonNull ::new_unchecked ( dest . get_end ( ) . cast ( ) ) ;
2022-05-11 13:26:53 -05:00
self . len + = 1 ;
}
2022-05-13 13:14:18 -05:00
/// Pops an element off the end of the vector, putting it in a [`Box`].
pub fn pop ( & mut self ) -> Option < Box < T > > {
unsafe {
self . len = self . len . checked_sub ( 1 ) ? ;
let el = self . get_ptr ( self . len ) ;
2022-05-17 09:47:54 -05:00
Some ( el . read_to_box ( ) )
2022-05-13 13:14:18 -05:00
}
}
2022-05-11 13:26:53 -05:00
unsafe fn realloc ( & mut self , size : usize ) {
let layout = Layout ::from_size_align_unchecked ( size , 8 ) . pad_to_align ( ) ;
if self . capacity = = 0 {
// will panic if OOM
self . ptr = NonNull ::new ( alloc ( layout ) ) . unwrap ( ) ;
self . end_ptr = self . ptr ;
} else {
2022-05-17 09:47:54 -05:00
// cannot use mem::realloc here
2022-05-11 13:26:53 -05:00
let new_alloc = NonNull ::new ( alloc ( layout ) ) . unwrap ( ) ;
// data
let mut ptr = new_alloc . as_ptr ( ) ;
for i in 0 .. self . len {
2022-05-17 09:47:54 -05:00
let v = self . get_ptr ( i ) ;
2022-06-08 23:00:11 -05:00
ptr = ptr . align_up ( align_of_val ( & * v ) ) ;
2022-05-17 09:47:54 -05:00
v . copy_val_to ( ptr ) ;
self . set_extra_from_ptr ( i , ptr . with_meta_from ( v ) ) ;
2022-06-08 23:00:11 -05:00
ptr = ptr . wrapping_add ( size_of_val ( & * v ) ) ;
2022-05-11 13:26:53 -05:00
}
self . end_ptr = NonNull ::new_unchecked ( ptr ) ;
2022-05-17 09:47:54 -05:00
// extra
let extra_src = self . get_ptr_to_extra ( self . len ) ;
let extra_dst = {
2022-05-11 13:26:53 -05:00
let current_alloc_end = self . ptr . as_ptr ( ) . wrapping_add ( self . capacity ) ;
let new_alloc_end = new_alloc . as_ptr ( ) . wrapping_add ( layout . size ( ) ) ;
2022-05-17 09:47:54 -05:00
let extra_len = current_alloc_end . addr ( ) - extra_src . addr ( ) ;
new_alloc_end . wrapping_sub ( extra_len )
2022-05-11 13:26:53 -05:00
} ;
2022-05-17 09:47:54 -05:00
extra_src . copy_to ( extra_dst . cast ( ) , self . len ) ;
2022-05-11 13:26:53 -05:00
dealloc ( self . ptr . as_ptr ( ) , Layout ::from_size_align_unchecked ( self . capacity , 8 ) ) ;
self . ptr = new_alloc ;
}
self . capacity = layout . size ( ) ;
}
/// for internal use
///
2022-05-17 09:47:54 -05:00
/// # Note: 1-indexed, to allow getting a pointer to the end of the alloc easily
2022-05-13 08:59:05 -05:00
fn get_ptr_to_extra ( & self , index : usize ) -> * mut Extra < T > {
2022-05-11 13:26:53 -05:00
self . ptr . as_ptr ( )
2022-05-17 09:47:54 -05:00
. add_bytes ( self . capacity )
2022-05-13 08:43:19 -05:00
. cast ::< Extra < T > > ( )
2022-05-11 13:26:53 -05:00
. wrapping_sub ( index )
}
2022-05-13 08:59:05 -05:00
unsafe fn set_extra_from_ptr ( & self , index : usize , ptr : * const T ) {
self . get_ptr_to_extra ( index + 1 ) . write ( ptr ) ;
2022-05-12 08:48:32 -05:00
}
2022-05-11 13:26:53 -05:00
unsafe fn get_ptr ( & self , index : usize ) -> * const T {
2022-05-13 08:59:05 -05:00
* self . get_ptr_to_extra ( index + 1 )
2022-05-11 13:26:53 -05:00
}
2022-05-17 09:47:54 -05:00
unsafe fn get_ptr_before_pad ( & self , index : usize ) -> * const T {
self . get_ptr ( index ) . with_addr_from ( if index > 0 { self . get_ptr ( index - 1 ) . get_end ( ) . cast ( ) } else { self . ptr . as_ptr ( ) } )
}
2022-05-13 13:14:18 -05:00
/// Gets a reference to the element at the specified index.
///
/// Returns `None` if the index is out-of-bounds.
2022-05-11 13:26:53 -05:00
pub fn get ( & self , index : usize ) -> Option < & T > {
if index < self . len {
Some ( unsafe { self . get_unchecked ( index ) } )
} else {
None
}
}
2022-05-13 13:14:18 -05:00
/// Gets a reference to the element at the specified index.
///
2022-05-16 09:42:00 -05:00
/// # Safety
///
2022-05-13 13:14:18 -05:00
/// Immediate UB if the index is out-of-bounds.
2022-05-11 13:26:53 -05:00
pub unsafe fn get_unchecked ( & self , index : usize ) -> & T {
& * self . get_ptr ( index )
}
2022-05-13 13:14:18 -05:00
/// Gets a mutable reference to the element at the specified index.
///
/// Returns `None` if the index is out-of-bounds.
2022-05-11 13:26:53 -05:00
pub fn get_mut ( & mut self , index : usize ) -> Option < & mut T > {
if index < self . len {
Some ( unsafe { self . get_unchecked_mut ( index ) } )
} else {
None
}
}
2022-05-13 13:14:18 -05:00
/// Gets a mutable reference to the element at the specified index.
///
2022-05-16 09:42:00 -05:00
/// # Safety
///
2022-05-13 13:14:18 -05:00
/// Immediate UB if the index is out-of-bounds.
2022-05-11 13:26:53 -05:00
pub unsafe fn get_unchecked_mut ( & mut self , index : usize ) -> & mut T {
& mut * ( self . get_ptr ( index ) as * mut _ )
}
2022-05-13 13:14:18 -05:00
/// Returns the length of the vector, which is how many items it contains.
2022-05-11 13:26:53 -05:00
pub fn len ( & self ) -> usize {
self . len
}
2022-05-16 09:42:00 -05:00
/// Returns `true` if the vector holds no elements.
pub fn is_empty ( & self ) -> bool {
self . len = = 0
}
2022-05-12 08:48:32 -05:00
/// Returns the capacity, which is the size of the allocation in bytes.
2022-05-17 09:47:54 -05:00
///
/// Note the distinction from [`std::vec::Vec`], which returns how many elements it can hold.
2022-05-11 13:26:53 -05:00
pub fn capacity ( & self ) -> usize {
self . capacity
}
2022-05-13 13:14:18 -05:00
/// Returns a pointer to the allocation of the vector.
2022-05-11 13:26:53 -05:00
pub fn as_ptr ( & self ) -> * const u8 {
self . ptr . as_ptr ( )
}
2022-05-13 13:14:18 -05:00
/// Returns a mutable pointer to the allocation of the vector.
2022-05-11 13:26:53 -05:00
pub fn as_mut_ptr ( & mut self ) -> * mut u8 {
self . ptr . as_ptr ( )
}
2022-05-13 13:14:18 -05:00
/// Iterates over the vector by-ref.
2022-05-11 13:26:53 -05:00
pub fn iter ( & self ) -> Iter < T > {
Iter ::new ( self )
}
2022-05-13 13:14:18 -05:00
/// Iterates over the vector by-mut.
2022-05-11 13:26:53 -05:00
pub fn iter_mut ( & mut self ) -> IterMut < T > {
IterMut ::new ( self )
}
2022-05-12 08:48:32 -05:00
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
2022-06-08 23:00:11 -05:00
#[ cfg(feature = " unstable " ) ]
pub fn unsize < U : ? Sized > ( self ) -> Vec < U > where for < ' a > & ' a T : CoerceUnsized < & ' a U > {
// TODO: maybe make this not call the stable version for perf?
self . unsize_stable ( | v | v as _ )
}
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn unsize_stable < U : ? Sized > ( mut self , coercer : Coercer < T , U > ) -> Vec < U > {
2022-05-16 10:42:55 -05:00
if size_of ::< Extra < U > > ( ) > size_of ::< Extra < T > > ( ) {
2022-05-17 09:47:54 -05:00
let elem_size = self . end_ptr . as_ptr ( ) . addr ( ) - self . ptr . as_ptr ( ) . addr ( ) ;
2022-05-16 10:42:55 -05:00
let extra_size = self . len * size_of ::< Extra < U > > ( ) ;
let needed_size = elem_size + extra_size ;
if needed_size > self . capacity {
unsafe { self . realloc ( needed_size ) ; }
}
}
2022-05-16 10:02:03 -05:00
2022-05-11 13:26:53 -05:00
let new_vec = Vec ::< U > {
ptr : self . ptr ,
len : self . len ,
capacity : self . capacity ,
end_ptr : self . end_ptr ,
_phantom : PhantomData ,
} ;
2022-05-13 08:43:19 -05:00
if size_of ::< Extra < U > > ( ) > size_of ::< Extra < T > > ( ) {
// new extra larger than old extra, must go from back to front
2022-05-11 13:26:53 -05:00
2022-05-12 08:48:32 -05:00
for i in ( 0 .. self . len ) . rev ( ) {
2022-05-17 09:47:54 -05:00
// using references here is necessary for unsizing coercion to work
2022-05-12 08:48:32 -05:00
let current = unsafe { & * self . get_ptr ( i ) } ;
2022-06-08 23:00:11 -05:00
unsafe { new_vec . set_extra_from_ptr ( i , coercer ( current ) ) }
2022-05-11 13:26:53 -05:00
}
} else {
2022-05-13 08:43:19 -05:00
// new extra smaller or same size as old extra, must go from front to back
2022-05-11 13:26:53 -05:00
2022-05-12 08:48:32 -05:00
for i in 0 .. self . len {
2022-05-17 09:47:54 -05:00
// using references here is necessary for unsizing coercion to work
2022-05-12 08:48:32 -05:00
let current = unsafe { & * self . get_ptr ( i ) } ;
2022-06-08 23:00:11 -05:00
unsafe { new_vec . set_extra_from_ptr ( i , coercer ( current ) ) }
2022-05-11 13:26:53 -05:00
}
}
mem ::forget ( self ) ;
new_vec
}
2022-05-13 10:29:14 -05:00
unsafe fn dealloc ( & self ) {
if self . capacity ! = 0 {
dealloc ( self . ptr . as_ptr ( ) , Layout ::from_size_align_unchecked ( self . capacity , 8 ) ) ;
}
}
2022-05-13 14:26:32 -05:00
/// Extends this vector with an iterator.
///
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
2022-06-08 23:00:11 -05:00
#[ cfg(feature = " unstable " ) ]
2022-05-13 14:26:32 -05:00
pub fn extend_unsize < U , I : IntoIterator < Item = U > > ( & mut self , iter : I ) where for < ' a > & ' a U : CoerceUnsized < & ' a T > {
2022-06-08 23:00:11 -05:00
// TODO: maybe make this not call the stable version for perf?
self . extend_unsize_stable ( iter , | v | v as _ ) ;
}
/// Extends this vector with an iterator.
///
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
///
/// The coercion is done through a closure, since `CoerceUnsized` is unstable. Usually you can pass `|v| v as _`.
pub fn extend_unsize_stable < U , I : IntoIterator < Item = U > > ( & mut self , iter : I , coercer : Coercer < U , T > ) {
2022-05-13 14:26:32 -05:00
for item in iter {
2022-06-08 23:00:11 -05:00
self . push_unsize_stable ( item , coercer ) ;
2022-05-13 14:26:32 -05:00
}
}
2022-05-17 09:47:54 -05:00
/// Removes the element at the specified index, shifting other elements over to fill the gap.
pub fn remove ( & mut self , index : usize ) -> Option < Box < T > > where T : std ::fmt ::Debug {
if index > = self . len {
return None
}
if index = = self . len - 1 {
return self . pop ( )
}
unsafe {
let res = Some ( self . get_ptr ( index ) . read_to_box ( ) ) ;
// starting from the now-empty spot, up to but not including the end...
for index in index .. self . len - 1 {
// get a pointer to the end of the previous element
let mut new_ptr = self . get_ptr_before_pad ( index ) ;
// align it up to the align of the NEXT element
let next_ptr = self . get_ptr ( index + 1 ) ;
2022-06-08 23:00:11 -05:00
new_ptr = new_ptr . align_up ( align_of_val ( & * next_ptr ) ) ;
2022-05-17 09:47:54 -05:00
// if its the same, we can break as the rest will be useless
if new_ptr = = next_ptr { break }
// data
next_ptr . copy_val_to ( new_ptr as * mut T ) ;
// extra
self . set_extra_from_ptr ( index , new_ptr . with_meta_from ( next_ptr ) ) ;
}
self . len - = 1 ;
res
}
}
2022-05-11 13:26:53 -05:00
}
impl < T > Vec < [ T ] > {
2022-05-13 13:14:18 -05:00
/// Returns a slice over all the elements in the vector.
///
/// Only avaliable for `Vec<[T]>`.
2022-05-11 13:26:53 -05:00
pub fn as_slice_flatten ( & self ) -> & [ T ] {
2022-05-16 09:42:00 -05:00
if self . len = = 0 {
return unsafe { slice ::from_raw_parts ( NonNull ::dangling ( ) . as_ptr ( ) , 0 ) }
}
2022-05-11 13:26:53 -05:00
// SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked`
unsafe {
2022-05-17 09:47:54 -05:00
slice ::from_raw_parts ( self . get_ptr ( 0 ) . data_ptr ( ) . cast ( ) , {
let start = self . get_ptr ( 0 ) . addr ( ) ;
let end = self . end_ptr . as_ptr ( ) . addr ( ) ;
2022-05-16 09:42:00 -05:00
debug_assert_eq! ( ( end - start ) % size_of ::< T > ( ) , 0 ) ;
2022-05-11 13:26:53 -05:00
( end - start ) / size_of ::< T > ( ) // integer division!
} )
}
}
2022-05-13 13:14:18 -05:00
/// Returns a mutable slice over all the elements in the vector.
///
/// Only avaliable for `Vec<[T]>`.
2022-05-11 13:26:53 -05:00
pub fn as_mut_slice_flatten ( & mut self ) -> & mut [ T ] {
2022-05-16 09:42:00 -05:00
if self . len = = 0 {
return unsafe { slice ::from_raw_parts_mut ( NonNull ::dangling ( ) . as_ptr ( ) , 0 ) }
}
2022-05-11 13:26:53 -05:00
// SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked`
unsafe {
2022-05-17 09:47:54 -05:00
slice ::from_raw_parts_mut ( self . get_ptr ( 0 ) . data_ptr ( ) as _ , {
let start = self . get_ptr ( 0 ) . addr ( ) ;
let end = self . end_ptr . as_ptr ( ) . addr ( ) ;
2022-05-16 09:42:00 -05:00
debug_assert_eq! ( ( end - start ) % size_of ::< T > ( ) , 0 ) ;
2022-05-11 13:26:53 -05:00
( end - start ) / size_of ::< T > ( ) // integer division!
} )
}
}
}
2022-05-13 13:14:18 -05:00
impl Vec < dyn Any > {
/// Gets a reference to the element at then specified index, downcasting it to the specified type.
///
/// Same as `.get().map(|v| v.downcast()).flatten()`.
pub fn downcast_get < T : Any > ( & self , index : usize ) -> Option < & T > {
self . get ( index ) ? . downcast_ref ( )
}
/// Gets a mutable reference to the element at then specified index, downcasting it to the specified type.
///
/// Same as `.get_mut().map(|v| v.downcast_mut()).flatten()`.
pub fn downcast_get_mut < T : Any > ( & mut self , index : usize ) -> Option < & mut T > {
self . get_mut ( index ) ? . downcast_mut ( )
}
/// Pops an element off the end of the vector, downcasting it to the specified type.
///
/// If the element is not of type `T`, the element will not be popped.
///
/// Similiar to `.pop().map(|v| v.downcast()).flatten()`, but without an intermediate allocation.
pub fn downcast_pop < T : Any > ( & mut self ) -> Option < T > {
unsafe {
2022-05-17 09:47:54 -05:00
let el = self . get_unchecked_mut ( self . len . checked_sub ( 1 ) ? ) ;
let v = Some ( ( el . downcast_mut ( ) ? as * mut T ) . read ( ) ) ;
2022-05-13 13:14:18 -05:00
self . len - = 1 ;
v
}
}
}
2022-05-11 13:26:53 -05:00
impl < T : ? Sized > Drop for Vec < T > {
fn drop ( & mut self ) {
unsafe {
2022-06-08 23:00:11 -05:00
for el in self . iter_mut ( ) {
drop_in_place ( el ) ;
2022-05-11 13:26:53 -05:00
}
2022-06-08 23:00:11 -05:00
2022-05-13 10:29:14 -05:00
self . dealloc ( ) ;
2022-05-11 13:26:53 -05:00
}
}
}
impl < T : ? Sized > Index < usize > for Vec < T > {
type Output = T ;
#[ track_caller ]
fn index ( & self , index : usize ) -> & Self ::Output {
match self . get ( index ) {
Some ( v ) = > v ,
None = > panic! ( " index out of bounds: the len is {} but the index is {} " , self . len , index ) ,
}
}
}
impl < T : ? Sized > IndexMut < usize > for Vec < T > {
#[ track_caller ]
fn index_mut ( & mut self , index : usize ) -> & mut Self ::Output {
let len = self . len ;
match self . get_mut ( index ) {
Some ( v ) = > v ,
None = > panic! ( " index out of bounds: the len is {} but the index is {} " , len , index ) ,
}
}
}
/// Creates a [`Vec`].
///
/// # Examples
///
/// ```
/// # use dyn_vec::prelude::{vec, Vec};
/// # use std::fmt::Debug;
2022-05-16 10:02:03 -05:00
/// let vec1: Vec<i32> = vec![1, 2, 3];
2022-05-11 13:26:53 -05:00
/// let vec2: Vec<dyn Debug> = vec![box:
/// Box::new(1) as _,
/// Box::new(String::from("foo")) as _,
/// Box::new(true) as _
/// ];
/// let vec3: Vec<dyn Debug> = vec![unsized: 1, String::from("foo"), true];
/// ```
#[ macro_export ]
macro_rules ! vec {
( ) = > {
$crate ::Vec ::new ( ) ;
} ;
( box : $( $elem :expr ) , + $(, ) ? ) = > { {
let mut vec = $crate ::Vec ::new ( ) ;
$( vec . push_box ( $elem ) ; ) +
vec
} } ;
( unsized : $( $elem :expr ) , + $(, ) ? ) = > { {
let mut vec = $crate ::Vec ::new ( ) ;
2022-06-08 23:00:11 -05:00
// TODO: when stuff stabalizes change this
$( vec . push_unsize_stable ( $elem , | v | v as _ ) ; ) +
2022-05-11 13:26:53 -05:00
vec
} } ;
( $elem :expr ; $n :expr ) = > {
2022-05-16 09:42:00 -05:00
$crate ::Vec ::from_elem ( $elem , $n )
2022-05-11 13:26:53 -05:00
} ;
( $( $elem :expr ) , + $(, ) ? ) = > { {
let mut vec = $crate ::Vec ::new ( ) ;
$( vec . push ( $elem ) ; ) +
vec
} } ;
}