clippy and rustfmt
This commit is contained in:
parent
edecfc9b69
commit
813526e49e
22
src/bench.rs
22
src/bench.rs
|
@ -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))));
|
||||
}
|
||||
}
|
||||
|
|
46
src/impls.rs
46
src/impls.rs
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
39
src/iter.rs
39
src/iter.rs
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
236
src/lib.rs
236
src/lib.rs
|
@ -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
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 _
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/test.rs
19
src/test.rs
|
@ -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]");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue