clippy and rustfmt

This commit is contained in:
missing 2022-08-14 14:21:40 -05:00
parent edecfc9b69
commit 813526e49e
6 changed files with 225 additions and 145 deletions

View file

@ -1,14 +1,14 @@
//! `-Zmiri-disable-isolation` needed to run these under miri
use test::{Bencher, black_box};
use test::{black_box, Bencher};
extern crate test;
use super::Vec;
use std::{vec::Vec as StdVec, fmt::Debug, mem};
use std::{fmt::Debug, mem, vec::Vec as StdVec};
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn std_push(b: &mut Bencher) {
let mut vec = StdVec::new();
@ -18,7 +18,7 @@ fn std_push(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn dyn_push(b: &mut Bencher) {
let mut vec = Vec::new();
@ -28,7 +28,7 @@ fn dyn_push(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn std_push_box(b: &mut Bencher) {
let mut vec = StdVec::new();
@ -38,7 +38,7 @@ fn std_push_box(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn dyn_push_unsize(b: &mut Bencher) {
let mut vec = Vec::new();
@ -48,7 +48,7 @@ fn dyn_push_unsize(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn dyn_push_box(b: &mut Bencher) {
let mut vec = Vec::new();
@ -58,7 +58,7 @@ fn dyn_push_box(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn dyn_push_then_unsize(b: &mut Bencher) {
let mut vec = Vec::new();
@ -70,13 +70,13 @@ fn dyn_push_then_unsize(b: &mut Bencher) {
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn box_forget(b: &mut Bencher) {
b.iter(|| mem::forget(black_box(Box::new(5))));
}
#[bench]
#[ignore = "ignored for miri compat"]
#[cfg_attr(miri, ignore)]
fn box_dealloc(b: &mut Bencher) {
b.iter(|| drop(black_box(Box::new(5))));
}
}

View file

@ -1,8 +1,14 @@
//! Implements `Debug`, `Default`, `Extend`, and `Deref`. Also implements `PartialEq` for various list-like types.
use crate::{Vec, Extra};
use crate::{Extra, Vec};
use std::{fmt::Debug, ops::{Deref, DerefMut}, vec::Vec as StdVec, slice, mem::size_of};
use std::{
fmt::Debug,
mem::size_of,
ops::{Deref, DerefMut},
slice,
vec::Vec as StdVec,
};
#[cfg(feature = "unstable")]
use std::ops::CoerceUnsized;
@ -13,7 +19,6 @@ impl<T: ?Sized> Default for Vec<T> {
}
}
impl<T: ?Sized + Debug> Debug for Vec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.iter()).finish()
@ -23,9 +28,13 @@ impl<T: ?Sized + Debug> Debug for Vec<T> {
// Vec<T> == Vec<U>
impl<T: ?Sized + PartialEq<U>, U: ?Sized> PartialEq<Vec<U>> for Vec<T> {
fn eq(&self, other: &Vec<U>) -> bool {
if self.len != other.len { return false }
if self.len != other.len {
return false;
}
for (el, el2) in self.iter().zip(other.iter()) {
if el != el2 { return false }
if el != el2 {
return false;
}
}
true
}
@ -36,9 +45,13 @@ impl<T: ?Sized + Eq> Eq for Vec<T> {}
// Vec<T> == [U]
impl<T: PartialEq<U>, U> PartialEq<[U]> for Vec<T> {
fn eq(&self, other: &[U]) -> bool {
if self.len != other.len() { return false }
if self.len != other.len() {
return false;
}
for (el, el2) in self.iter().zip(other.iter()) {
if el != el2 { return false }
if el != el2 {
return false;
}
}
true
}
@ -132,7 +145,10 @@ impl<T: ?Sized> Extend<Box<T>> for Vec<T> {
}
#[cfg(feature = "unstable")]
impl<T: ?Sized, U: ?Sized> Extend<Box<U>> for Vec<T> where Box<U>: CoerceUnsized<Box<T>> {
impl<T: ?Sized, U: ?Sized> Extend<Box<U>> for Vec<T>
where
Box<U>: CoerceUnsized<Box<T>>,
{
fn extend<I: IntoIterator<Item = Box<U>>>(&mut self, iter: I) {
for item in iter {
// TODO: optmize
@ -160,9 +176,11 @@ unsafe impl<T: Sync> Sync for Vec<T> {}
impl<T> From<StdVec<T>> for Vec<T> {
fn from(std_vec: StdVec<T>) -> Self {
let mut vec = Vec::new();
let mut vec = Self::new();
let new_cap = (size_of::<T>() + size_of::<Extra<T>>()) * std_vec.len();
unsafe { vec.realloc(new_cap); }
unsafe {
vec.realloc(new_cap);
}
for item in std_vec {
unsafe { vec.push_raw_unchecked(&item) }
@ -174,14 +192,14 @@ impl<T> From<StdVec<T>> for Vec<T> {
impl<T> From<Vec<T>> for StdVec<T> {
fn from(mut vec: Vec<T>) -> Self {
let mut std_vec = StdVec::with_capacity(vec.len);
let mut std_vec = Self::with_capacity(vec.len);
for item in vec.iter() {
std_vec.push(unsafe { (item as *const T).read() });
}
vec.len = 0;
std_vec
}
}
}

View file

@ -2,13 +2,16 @@
use std::{marker::PhantomData, mem, ptr::NonNull};
use crate::{Vec, ptr_ext::PtrExt};
use crate::{ptr_ext::PtrExt, Vec};
struct BaseIter<T: ?Sized> {
ptr: *const *mut T,
ptr_back: *const *mut T,
}
unsafe impl<T: Send> Send for BaseIter<T> {}
unsafe impl<T: Sync> Sync for BaseIter<T> {}
impl<T: ?Sized> BaseIter<T> {
fn new(vec: &Vec<T>) -> Self {
Self {
@ -23,7 +26,7 @@ impl<T: ?Sized> Iterator for BaseIter<T> {
fn next(&mut self) -> Option<Self::Item> {
if self.ptr == self.ptr_back {
return None
return None;
}
self.ptr_back = self.ptr_back.wrapping_sub(1);
@ -34,7 +37,7 @@ impl<T: ?Sized> Iterator for BaseIter<T> {
impl<T: ?Sized> DoubleEndedIterator for BaseIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.ptr == self.ptr_back {
return None
return None;
}
let el = unsafe { self.ptr.read() };
@ -43,7 +46,6 @@ impl<T: ?Sized> DoubleEndedIterator for BaseIter<T> {
}
}
// By-ref iteration
impl<'a, T: ?Sized> IntoIterator for &'a Vec<T> {
type Item = &'a T;
@ -58,7 +60,7 @@ impl<'a, T: ?Sized> IntoIterator for &'a Vec<T> {
/// A by-ref iterator over the elements of a [`Vec`].
pub struct Iter<'a, T: ?Sized> {
base: BaseIter<T>,
_phantom: PhantomData<&'a T>
_phantom: PhantomData<&'a T>,
}
unsafe impl<'a, T: Send> Send for Iter<'a, T> {}
@ -67,7 +69,10 @@ unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
impl<'a, T: ?Sized> Iter<'a, T> {
/// Creates a new by-ref iterator over a [`Vec`]. usually seen as [`Vec::iter`].
pub fn new(vec: &'a Vec<T>) -> Self {
Self { base: BaseIter::new(vec), _phantom: PhantomData }
Self {
base: BaseIter::new(vec),
_phantom: PhantomData,
}
}
}
@ -85,7 +90,6 @@ impl<'a, T: ?Sized> DoubleEndedIterator for Iter<'a, T> {
}
}
// By-mut iteration
impl<'a, T: ?Sized> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
@ -101,7 +105,7 @@ impl<'a, T: ?Sized> IntoIterator for &'a mut Vec<T> {
#[allow(clippy::module_name_repetitions)]
pub struct IterMut<'a, T: ?Sized> {
base: BaseIter<T>,
_phantom: PhantomData<&'a mut T>
_phantom: PhantomData<&'a mut T>,
}
unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
@ -110,7 +114,10 @@ unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
impl<'a, T: ?Sized> IterMut<'a, T> {
/// Creates a new by-mut iterator over a [`Vec`]. usually seen as [`Vec::iter_mut`].
pub fn new(vec: &'a mut Vec<T>) -> Self {
Self { base: BaseIter::new(vec), _phantom: PhantomData }
Self {
base: BaseIter::new(vec),
_phantom: PhantomData,
}
}
}
@ -124,11 +131,10 @@ impl<'a, T: ?Sized> Iterator for IterMut<'a, T> {
impl<'a, T: ?Sized> DoubleEndedIterator for IterMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.base.next_back().map(|v| unsafe { &mut *v })
self.base.next_back().map(|v| unsafe { &mut *v })
}
}
// By-value iteration
impl<T: ?Sized> IntoIterator for Vec<T> {
type Item = Box<T>;
@ -145,7 +151,7 @@ impl<T: ?Sized> IntoIterator for Vec<T> {
pub struct IntoIter<T: ?Sized> {
ptr: NonNull<u8>,
capacity: usize,
base: BaseIter<T>
base: BaseIter<T>,
}
unsafe impl<T: Send> Send for IntoIter<T> {}
@ -157,7 +163,7 @@ impl<T: ?Sized> IntoIter<T> {
let this = Self {
ptr: vec.ptr,
capacity: vec.capacity,
base: BaseIter::new(&vec)
base: BaseIter::new(&vec),
};
mem::forget(vec);
this
@ -185,12 +191,11 @@ impl<T: ?Sized> Drop for IntoIter<T> {
len: 0,
capacity: self.capacity,
end_ptr: self.ptr,
_phantom: PhantomData
_phantom: PhantomData,
});
}
}
// // this implementation will collect *while unsizing*, and would conflict with the other
// impl<T: ?Sized, U> FromIterator<U> for Vec<T> where for<'a> &'a U: CoerceUnsized<&'a T> {
// fn from_iter<I: IntoIterator<Item = U>>(iter: I) -> Self {
@ -206,7 +211,7 @@ impl<T: ?Sized> Drop for IntoIter<T> {
impl<T> FromIterator<T> for Vec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut vec = Vec::new();
let mut vec = Self::new();
for item in iter {
vec.push(item);
@ -214,4 +219,4 @@ impl<T> FromIterator<T> for Vec<T> {
vec
}
}
}

View file

@ -1,28 +1,28 @@
//! # A [`Vec<T: ?Sized>`]
//!
//!
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
//!
//!
//! 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:
//! - `#![feature(coerce_unsized)]`, to add trait bounds for types which can be unsized to another type.
//!
//!
//! and enables the following functionality (note: these links are probably broken):
//! - [`Vec::push_unsize`]
//! - [`Vec::unsize`]
//! - [`Vec::extend_unsize`]
//!
//!
//! # Examples
//!
//!
//! You can create a vector with [`Vec::new`]:
//!
//!
//! ```
//! # 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;
@ -40,9 +40,9 @@
//! # assert_eq!(format!("{:?}", vec_unsized), r#"[1, "foo", true]"#);
//! # assert_eq!(vec_from_elem, [3; 5]);
//! ```
//!
//!
//! A vector can be pushed to with [`Vec::push`]:
//!
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! let mut vec: Vec<i32> = vec![];
@ -51,9 +51,9 @@
//! vec.push(3);
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
//! ```
//!
//!
//! ...and with [`push_box`] and [`push_unsize`] ([`push_unsize_stable`] without the `"unstable"` feature):
//!
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug;
@ -61,16 +61,16 @@
//! vec.push_box(Box::new(1));
//! vec.push_box(Box::new("foo"));
//! vec.push_box(Box::new(true));
//!
//!
//! // 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 _);
//! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#);
//! ```
//!
//!
//! Finally, a vector can be [`unsize`]d to another vector ([`unsize_stable`] on stable):
//!
//!
//! ```
//! # use dyn_vec::prelude::{*, vec};
//! # use std::fmt::Debug;
@ -80,11 +80,11 @@
//! vec.push_unsize_stable("foo", |v| v as _); // now we can!
//! # assert_eq!(format!("{:?}", vec), r#"[1, 2, 3, "foo"]"#);
//! ```
//!
//!
//! To use the `_stable` variations, one can generally add the argument `|v| v as _`.
//!
//!
//! # Data Layout
//!
//!
//! ```text
//! Vec<T>
//! ┌────┬────┬────┬────┐
@ -103,9 +103,9 @@
//! │ │ └──────────────────────────────────────────┘ │ │
//! │ └─────────────────────────────────────────────────────────┘ │
//! │ │
//! └─ aligned to 8 also aligned to 8 ─┘
//! └─ aligned to usize also aligned to usize ─┘
//! ```
//!
//!
//! [`Vec<T: ?Sized>`]: Vec
//! [`Vec::push_unsize`]: Vec::push_unsize
//! [`Vec::unsize`]: Vec::unsize
@ -117,34 +117,35 @@
//! [`unsize_stable`]: Vec::unsize_stable
#![cfg_attr(feature = "unstable", feature(coerce_unsized))]
#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![allow(clippy::must_use_candidate)]
#![allow(unstable_name_collisions)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
mod test;
#[cfg(test)]
mod bench;
#[cfg(test)]
mod test;
// TODO: maybe remove this? Its not that many imports
/// Prelude, suitable for glob imports.
///
///
/// Using `prelude::*` will cause a conflict for the `vec!` macro. `prelude::{*, vec}` is recommended.
pub mod prelude {
pub use super::{Vec, vec};
pub use super::{vec, Vec};
}
use core::panic;
use std::{
ptr::{NonNull, drop_in_place},
alloc::{alloc, dealloc, Layout},
any::Any,
marker::PhantomData,
alloc::{Layout, alloc, dealloc},
mem::{self, size_of, size_of_val, align_of_val},
slice,
mem::{self, align_of_val, size_of, size_of_val},
ops::{Index, IndexMut},
any::Any
ptr::{drop_in_place, NonNull},
slice,
};
#[cfg(feature = "unstable")]
@ -153,17 +154,17 @@ use std::ops::CoerceUnsized;
type Coercer<T, U> = for<'a> fn(&'a T) -> &'a U;
mod ptr_ext;
use ptr_ext::{PtrExt, ConstPtrExt, MutPtrExt};
use ptr_ext::{ConstPtrExt, MutPtrExt, PtrExt};
/// A heap allocated, dynamic length collection of `?Sized` elements.
///
///
/// See [`std::vec::Vec`] (the standard library `Vec` type) for more information.
pub struct Vec<T: ?Sized> {
ptr: NonNull<u8>,
len: usize,
capacity: usize,
end_ptr: NonNull<u8>,
_phantom: PhantomData<T>
_phantom: PhantomData<T>,
}
// keeps this file cleaner
@ -176,21 +177,24 @@ type Extra<T> = *const T;
impl<T: ?Sized> Vec<T> {
/// Creates a new, empty vector.
pub fn new() -> Self {
pub const fn new() -> Self {
let ptr = NonNull::dangling();
Self {
ptr,
len: 0,
capacity: 0,
end_ptr: ptr,
_phantom: PhantomData
_phantom: PhantomData,
}
}
/// 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 {
pub fn from_elem(v: T, len: usize) -> Self
where
T: Sized + Clone,
{
let mut vec = Self::with_capacity(len);
for _ in 0..len {
@ -201,16 +205,21 @@ impl<T: ?Sized> Vec<T> {
}
/// 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 {
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); }
unsafe {
vec.realloc(cap);
}
vec
}
@ -220,9 +229,12 @@ impl<T: ?Sized> Vec<T> {
}
/// Appends an element to the end of the vector.
///
///
/// Only avaliable if `T: Sized`.
pub fn push(&mut self, v: T) where T: Sized {
pub fn push(&mut self, v: T)
where
T: Sized,
{
unsafe { self.push_raw(&v) }
mem::forget(v);
}
@ -239,13 +251,16 @@ impl<T: ?Sized> Vec<T> {
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `T`.
#[cfg(feature = "unstable")]
pub fn push_unsize<U>(&mut self, v: U) where for<'a> &'a U: CoerceUnsized<&'a T> {
pub fn push_unsize<U>(&mut self, v: U)
where
for<'a> &'a U: CoerceUnsized<&'a T>,
{
// 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);
@ -263,7 +278,7 @@ impl<T: ?Sized> Vec<T> {
}
/// 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`.
/// In addition, the extra data for the element must be set using `set_extra_from_ptr`.
@ -330,7 +345,10 @@ impl<T: ?Sized> Vec<T> {
};
extra_src.copy_to(extra_dst.cast(), self.len);
dealloc(self.ptr.as_ptr(), Layout::from_size_align_unchecked(self.capacity, 8));
dealloc(
self.ptr.as_ptr(),
Layout::from_size_align_unchecked(self.capacity, 8),
);
self.ptr = new_alloc;
}
@ -339,13 +357,14 @@ impl<T: ?Sized> Vec<T> {
}
/// for internal use
///
///
/// # Note: 1-indexed, to allow getting a pointer to the end of the alloc easily
fn get_ptr_to_extra(&self, index: usize) -> *mut Extra<T> {
self.ptr.as_ptr()
.add_bytes(self.capacity)
.cast::<Extra<T>>()
.wrapping_sub(index)
self.ptr
.as_ptr()
.add_bytes(self.capacity)
.cast::<Extra<T>>()
.wrapping_sub(index)
}
unsafe fn set_extra_from_ptr(&self, index: usize, ptr: *const T) {
@ -357,11 +376,15 @@ impl<T: ?Sized> Vec<T> {
}
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() })
self.get_ptr(index).with_addr_from(if index > 0 {
self.get_ptr(index - 1).get_end().cast()
} else {
self.ptr.as_ptr()
})
}
/// Gets a reference to the element at the specified index.
///
///
/// Returns `None` if the index is out-of-bounds.
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
@ -372,16 +395,16 @@ impl<T: ?Sized> Vec<T> {
}
/// Gets a reference to the element at the specified index.
///
///
/// # Safety
///
///
/// Immediate UB if the index is out-of-bounds.
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
&*self.get_ptr(index)
}
/// Gets a mutable reference to the element at the specified index.
///
///
/// Returns `None` if the index is out-of-bounds.
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
@ -392,33 +415,33 @@ impl<T: ?Sized> Vec<T> {
}
/// Gets a mutable reference to the element at the specified index.
///
///
/// # Safety
///
///
/// Immediate UB if the index is out-of-bounds.
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
&mut *(self.get_ptr(index) as *mut _)
}
/// Returns the length of the vector, which is how many items it contains.
pub fn len(&self) -> usize {
pub const fn len(&self) -> usize {
self.len
}
/// Returns `true` if the vector holds no elements.
pub fn is_empty(&self) -> bool {
pub const fn is_empty(&self) -> bool {
self.len == 0
}
/// Returns the capacity, which is the size of the allocation in bytes.
///
///
/// Note the distinction from [`std::vec::Vec`], which returns how many elements it can hold.
pub fn capacity(&self) -> usize {
pub const fn capacity(&self) -> usize {
self.capacity
}
/// Returns a pointer to the allocation of the vector.
pub fn as_ptr(&self) -> *const u8 {
pub const fn as_ptr(&self) -> *const u8 {
self.ptr.as_ptr()
}
@ -439,13 +462,16 @@ impl<T: ?Sized> Vec<T> {
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
#[cfg(feature = "unstable")]
pub fn unsize<U: ?Sized>(self) -> Vec<U> where for<'a> &'a T: CoerceUnsized<&'a U> {
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> {
if size_of::<Extra<U>>() > size_of::<Extra<T>>() {
@ -453,7 +479,9 @@ impl<T: ?Sized> Vec<T> {
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); }
unsafe {
self.realloc(needed_size);
}
}
}
@ -489,54 +517,66 @@ impl<T: ?Sized> Vec<T> {
unsafe fn dealloc(&self) {
if self.capacity != 0 {
dealloc(self.ptr.as_ptr(), Layout::from_size_align_unchecked(self.capacity, 8));
dealloc(
self.ptr.as_ptr(),
Layout::from_size_align_unchecked(self.capacity, 8),
);
}
}
/// Extends this vector with an iterator.
///
///
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
#[cfg(feature = "unstable")]
pub fn extend_unsize<U, I: IntoIterator<Item = U>>(&mut self, iter: I) where for<'a> &'a U: CoerceUnsized<&'a T> {
pub fn extend_unsize<U, I: IntoIterator<Item = U>>(&mut self, iter: I)
where
for<'a> &'a U: CoerceUnsized<&'a T>,
{
// 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>) {
pub fn extend_unsize_stable<U, I: IntoIterator<Item = U>>(
&mut self,
iter: I,
coercer: Coercer<U, T>,
) {
for item in iter {
self.push_unsize_stable(item, coercer);
}
}
/// 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>> {
pub fn remove(&mut self, index: usize) -> Option<Box<T>> {
if index >= self.len {
return None
return None;
}
if index == self.len - 1 {
return self.pop()
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 {
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);
new_ptr = new_ptr.align_up(align_of_val(&*next_ptr));
// if its the same, we can break as the rest will be useless
if new_ptr == next_ptr { break }
if new_ptr == next_ptr {
break;
}
// data
next_ptr.copy_val_to(new_ptr as *mut T);
@ -545,7 +585,7 @@ impl<T: ?Sized> Vec<T> {
}
self.len -= 1;
res
}
}
@ -553,11 +593,11 @@ impl<T: ?Sized> Vec<T> {
impl<T> Vec<[T]> {
/// Returns a slice over all the elements in the vector.
///
///
/// Only avaliable for `Vec<[T]>`.
pub fn as_slice_flatten(&self) -> &[T] {
if self.len == 0 {
return unsafe { slice::from_raw_parts(NonNull::dangling().as_ptr(), 0) }
return unsafe { slice::from_raw_parts(NonNull::dangling().as_ptr(), 0) };
}
// SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked`
@ -572,11 +612,11 @@ impl<T> Vec<[T]> {
}
/// Returns a mutable slice over all the elements in the vector.
///
///
/// Only avaliable for `Vec<[T]>`.
pub fn as_mut_slice_flatten(&mut self) -> &mut [T] {
if self.len == 0 {
return unsafe { slice::from_raw_parts_mut(NonNull::dangling().as_ptr(), 0) }
return unsafe { slice::from_raw_parts_mut(NonNull::dangling().as_ptr(), 0) };
}
// SAFETY: the slices should be contiguous by the logic of `push_raw_unchecked`
@ -593,23 +633,23 @@ impl<T> Vec<[T]> {
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 {
@ -640,7 +680,10 @@ impl<T: ?Sized> Index<usize> for Vec<T> {
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),
None => panic!(
"index out of bounds: the len is {} but the index is {}",
self.len, index
),
}
}
}
@ -651,15 +694,18 @@ impl<T: ?Sized> IndexMut<usize> for Vec<T> {
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),
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;
@ -674,7 +720,7 @@ impl<T: ?Sized> IndexMut<usize> for Vec<T> {
#[macro_export]
macro_rules! vec {
() => {
$crate::Vec::new();
$crate::Vec::new();
};
(box: $($elem:expr),+ $(,)?) => {{
let mut vec = $crate::Vec::new();
@ -695,4 +741,4 @@ macro_rules! vec {
$(vec.push($elem);)+
vec
}};
}
}

View file

@ -1,4 +1,8 @@
use std::{alloc::{alloc, Layout}, mem::size_of_val, ptr::addr_of_mut};
use std::{
alloc::{alloc, Layout},
mem::size_of_val,
ptr::addr_of_mut,
};
use self::__priv::Sealed;
@ -177,4 +181,4 @@ impl<T: ?Sized> MutPtrExt for *mut T {
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
ptr.with_addr_from(self) as _
}
}
}

View file

@ -1,7 +1,11 @@
//! Always use `cargo miri test`, and never just `cargo test`.
use super::prelude::{*, vec};
use std::{fmt::Debug, sync::atomic::{AtomicBool, Ordering}, any::Any};
use super::prelude::{vec, *};
use std::{
any::Any,
fmt::Debug,
sync::atomic::{AtomicBool, Ordering},
};
trait DebugExt: Debug {
fn debug(&self) -> String {
@ -111,13 +115,13 @@ fn iteration() {
assert_eq!(iter.next().unwrap().debug(), "1");
assert_eq!(iter.next().unwrap().debug(), "\"foo\"");
assert_eq!(iter.next().unwrap().debug(), "true");
assert_eq!(iter.next().map(|_|()), None);
assert_eq!(iter.next().map(|_| ()), None);
let mut iter = vec.iter_mut(); // TODO: create a trait to properly test this
assert_eq!(iter.next().unwrap().debug(), "1");
assert_eq!(iter.next().unwrap().debug(), "\"foo\"");
assert_eq!(iter.next().unwrap().debug(), "true");
assert_eq!(iter.next().map(|_|()), None);
assert_eq!(iter.next().map(|_| ()), None);
let mut debugs = Vec::new(); // using custom vec instead of std vec >:)
for item in vec {
@ -155,7 +159,10 @@ fn downcast() {
assert_eq!(vec.downcast_get::<f32>(0), None);
assert_eq!(vec.downcast_get::<i32>(0), Some(&1));
assert_eq!(vec.downcast_get_mut::<f32>(1), None);
assert_eq!(vec.downcast_get_mut::<String>(1), Some(&mut String::from("foo")));
assert_eq!(
vec.downcast_get_mut::<String>(1),
Some(&mut String::from("foo"))
);
assert_eq!(vec.downcast_pop::<f32>(), None);
assert_eq!(vec.downcast_pop::<bool>(), Some(true));
}
@ -203,4 +210,4 @@ fn remove() {
let mut vec: Vec<dyn Debug> = vec![unsized: 1, String::from("foo"), true];
assert_eq!(vec.remove(1).unwrap().debug(), "\"foo\"");
assert_eq!(vec.debug(), "[1, true]");
}
}