stable
This commit is contained in:
parent
d46bdc4a57
commit
192099e60b
|
@ -6,3 +6,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
unstable = []
|
|
@ -1,2 +1,5 @@
|
||||||
# dyn_vec
|
# A `Vec<T: ?Sized>`
|
||||||
|
|
||||||
|
A dynamic length collection of unsized elements, akin to `std::vec::Vec`.
|
||||||
|
|
||||||
|
Check the crate-level documentation for more info.
|
11
src/impls.rs
11
src/impls.rs
|
@ -63,6 +63,17 @@ impl<T: PartialEq<U>, U, const N: usize> PartialEq<Vec<T>> for [U; N] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unstable"))]
|
||||||
|
impl<T: ?Sized> Extend<Box<T>> for Vec<T> {
|
||||||
|
fn extend<I: IntoIterator<Item = Box<T>>>(&mut self, iter: I) {
|
||||||
|
for item in iter {
|
||||||
|
// TODO: optmize
|
||||||
|
self.push_box(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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) {
|
fn extend<I: IntoIterator<Item = Box<U>>>(&mut self, iter: I) {
|
||||||
for item in iter {
|
for item in iter {
|
||||||
|
|
|
@ -60,6 +60,9 @@ pub struct Iter<'a, T: ?Sized> {
|
||||||
_phantom: PhantomData<&'a T>
|
_phantom: PhantomData<&'a T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a, T: Send> Send for Iter<'a, T> {}
|
||||||
|
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> Iter<'a, T> {
|
impl<'a, T: ?Sized> Iter<'a, T> {
|
||||||
/// Creates a new by-ref iterator over a [`Vec`]. usually seen as [`Vec::iter`].
|
/// Creates a new by-ref iterator over a [`Vec`]. usually seen as [`Vec::iter`].
|
||||||
pub fn new(vec: &'a Vec<T>) -> Self {
|
pub fn new(vec: &'a Vec<T>) -> Self {
|
||||||
|
@ -100,6 +103,9 @@ pub struct IterMut<'a, T: ?Sized> {
|
||||||
_phantom: PhantomData<&'a mut T>
|
_phantom: PhantomData<&'a mut T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
|
||||||
|
unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
|
||||||
|
|
||||||
impl<'a, T: ?Sized> 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`].
|
/// Creates a new by-mut iterator over a [`Vec`]. usually seen as [`Vec::iter_mut`].
|
||||||
pub fn new(vec: &'a mut Vec<T>) -> Self {
|
pub fn new(vec: &'a mut Vec<T>) -> Self {
|
||||||
|
@ -141,6 +147,9 @@ pub struct IntoIter<T: ?Sized> {
|
||||||
base: BaseIter<T>
|
base: BaseIter<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Send> Send for IntoIter<T> {}
|
||||||
|
unsafe impl<T: Sync> Sync for IntoIter<T> {}
|
||||||
|
|
||||||
impl<T: ?Sized> IntoIter<T> {
|
impl<T: ?Sized> IntoIter<T> {
|
||||||
/// Creates a new by-value iterator over a [`Vec`]. usually seen as [`Vec::into_iter`].
|
/// Creates a new by-value iterator over a [`Vec`]. usually seen as [`Vec::into_iter`].
|
||||||
pub fn new(vec: Vec<T>) -> Self {
|
pub fn new(vec: Vec<T>) -> Self {
|
||||||
|
|
106
src/lib.rs
106
src/lib.rs
|
@ -2,11 +2,14 @@
|
||||||
//!
|
//!
|
||||||
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
|
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
|
||||||
//!
|
//!
|
||||||
//! This crate depends on a number of unstable features, namely:
|
//! 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(ptr_metadata)]`, to allow manipulating the metadata of pointers.
|
|
||||||
//! - `#![feature(layout_for_ptr)]`, to allow getting the size/alignment of a value with only a pointer to it.
|
|
||||||
//! - `#![feature(coerce_unsized)]`, to add trait bounds for types which can be unsized to another type.
|
//! - `#![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
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! You can create a vector with [`Vec::new`]:
|
//! You can create a vector with [`Vec::new`]:
|
||||||
|
@ -49,7 +52,7 @@
|
||||||
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
|
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ...and with [`push_box`] and [`push_unsize`]:
|
//! ...and with [`push_box`] and [`push_unsize`] ([`push_unsize_stable`] without the `"unstable"` feature):
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # use dyn_vec::prelude::{*, vec};
|
//! # use dyn_vec::prelude::{*, vec};
|
||||||
|
@ -59,24 +62,27 @@
|
||||||
//! vec.push_box(Box::new("foo"));
|
//! vec.push_box(Box::new("foo"));
|
||||||
//! vec.push_box(Box::new(true));
|
//! vec.push_box(Box::new(true));
|
||||||
//!
|
//!
|
||||||
//! vec.push_unsize(2);
|
//! // these closures are only needed for the `_stable` versions
|
||||||
//! vec.push_unsize("bar");
|
//! vec.push_unsize_stable(2, |v| v as _);
|
||||||
//! vec.push_unsize(false);
|
//! 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]"#);
|
//! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Finally, a vector can be `unsize`d to another vector:
|
//! Finally, a vector can be [`unsize`]d to another vector ([`unsize_stable`] on stable):
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # use dyn_vec::prelude::{*, vec};
|
//! # use dyn_vec::prelude::{*, vec};
|
||||||
//! # use std::fmt::Debug;
|
//! # use std::fmt::Debug;
|
||||||
//! let vec: Vec<i32> = vec![1, 2, 3];
|
//! let vec: Vec<i32> = vec![1, 2, 3];
|
||||||
//! // vec.push_unsize("foo"); // not yet...
|
//! // vec.push_unsize_stable("foo", |v| v as _); // not yet...
|
||||||
//! let mut vec: Vec<dyn Debug> = vec.unsize();
|
//! let mut vec: Vec<dyn Debug> = vec.unsize_stable(|v| v as _);
|
||||||
//! vec.push_unsize("foo"); // now we can!
|
//! vec.push_unsize_stable("foo", |v| v as _); // now we can!
|
||||||
//! # assert_eq!(format!("{:?}", vec), r#"[1, 2, 3, "foo"]"#);
|
//! # 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
|
//! # Data Layout
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
|
@ -101,12 +107,17 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [`Vec<T: ?Sized>`]: Vec
|
//! [`Vec<T: ?Sized>`]: Vec
|
||||||
|
//! [`Vec::push_unsize`]: Vec::push_unsize
|
||||||
|
//! [`Vec::unsize`]: Vec::unsize
|
||||||
|
//! [`Vec::extend_unsize`]: Vec::extend_unsize
|
||||||
//! [`push_box`]: Vec::push_box
|
//! [`push_box`]: Vec::push_box
|
||||||
//! [`push_unsize`]: Vec::push_unsize
|
//! [`push_unsize`]: Vec::push_unsize
|
||||||
|
//! [`push_unsize_stable`]: Vec::push_unsize_stable
|
||||||
|
//! [`unsize`]: Vec::unsize
|
||||||
|
//! [`unsize_stable`]: Vec::unsize_stable
|
||||||
|
|
||||||
#![feature(ptr_metadata)]
|
#![cfg_attr(feature = "unstable", feature(coerce_unsized))]
|
||||||
#![feature(layout_for_ptr)]
|
#![feature(backtrace)] // for debugging, REMOVE IT BEFORE COMMIT
|
||||||
#![feature(coerce_unsized)]
|
|
||||||
// for `mod bad_things`, still a wip
|
// for `mod bad_things`, still a wip
|
||||||
// #![allow(incomplete_features)]
|
// #![allow(incomplete_features)]
|
||||||
// #![feature(specialization)]
|
// #![feature(specialization)]
|
||||||
|
@ -131,12 +142,17 @@ use std::{
|
||||||
ptr::{NonNull, drop_in_place},
|
ptr::{NonNull, drop_in_place},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
alloc::{Layout, alloc, dealloc},
|
alloc::{Layout, alloc, dealloc},
|
||||||
mem::{self, size_of, size_of_val, align_of_val, size_of_val_raw, align_of_val_raw},
|
mem::{self, size_of, size_of_val, align_of_val},
|
||||||
slice,
|
slice,
|
||||||
ops::{CoerceUnsized, Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
any::Any
|
any::Any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
use std::ops::CoerceUnsized;
|
||||||
|
|
||||||
|
type Coercer<T, U> = for<'a> fn(&'a T) -> &'a U;
|
||||||
|
|
||||||
mod ptr_ext;
|
mod ptr_ext;
|
||||||
#[allow(clippy::wildcard_imports)]
|
#[allow(clippy::wildcard_imports)]
|
||||||
use ptr_ext::*;
|
use ptr_ext::*;
|
||||||
|
@ -218,21 +234,31 @@ impl<T: ?Sized> Vec<T> {
|
||||||
pub fn push_box(&mut self, v: Box<T>) {
|
pub fn push_box(&mut self, v: Box<T>) {
|
||||||
let ptr = Box::into_raw(v);
|
let ptr = Box::into_raw(v);
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let layout = Layout::for_value(&*ptr); // ref it *before* its logically uninit
|
||||||
self.push_raw(ptr);
|
self.push_raw(ptr);
|
||||||
dealloc(ptr.cast(), Layout::for_value_raw(ptr));
|
dealloc(ptr.cast(), layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends a sized element of type `U` to the end of the vector, given that it can be `CoerceUnsized` to a `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> {
|
||||||
let v_unsized: &T = &v;
|
// 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);
|
||||||
unsafe { self.push_raw(v_unsized) };
|
unsafe { self.push_raw(v_unsized) };
|
||||||
mem::forget(v);
|
mem::forget(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn push_raw(&mut self, v: *const T) {
|
unsafe fn push_raw(&mut self, v: *const T) {
|
||||||
if !self.will_fit(&*v) {
|
if !self.will_fit(&*v) {
|
||||||
let new_alloc_size = self.capacity * 2 + size_of_val_raw(v) * 2 + size_of::<Extra<T>>();
|
let new_alloc_size = self.capacity * 2 + size_of_val(&*v) * 2 + size_of::<Extra<T>>();
|
||||||
self.realloc(new_alloc_size);
|
self.realloc(new_alloc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,10 +316,10 @@ impl<T: ?Sized> Vec<T> {
|
||||||
for i in 0..self.len {
|
for i in 0..self.len {
|
||||||
let v = self.get_ptr(i);
|
let v = self.get_ptr(i);
|
||||||
|
|
||||||
ptr = ptr.align_up(align_of_val_raw(v));
|
ptr = ptr.align_up(align_of_val(&*v));
|
||||||
v.copy_val_to(ptr);
|
v.copy_val_to(ptr);
|
||||||
self.set_extra_from_ptr(i, ptr.with_meta_from(v));
|
self.set_extra_from_ptr(i, ptr.with_meta_from(v));
|
||||||
ptr = ptr.wrapping_add(size_of_val_raw(v));
|
ptr = ptr.wrapping_add(size_of_val(&*v));
|
||||||
}
|
}
|
||||||
self.end_ptr = NonNull::new_unchecked(ptr);
|
self.end_ptr = NonNull::new_unchecked(ptr);
|
||||||
|
|
||||||
|
@ -415,7 +441,16 @@ impl<T: ?Sized> Vec<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
|
/// Converts a `Vec<T: Sized>` into a `Vec<U: ?Sized>`, given that `T` can be `CoerceUnsized` into `U`.
|
||||||
pub fn unsize<U: ?Sized>(mut self) -> Vec<U> where for<'a> &'a T: CoerceUnsized<&'a U> {
|
#[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> {
|
||||||
if size_of::<Extra<U>>() > size_of::<Extra<T>>() {
|
if size_of::<Extra<U>>() > size_of::<Extra<T>>() {
|
||||||
let elem_size = self.end_ptr.as_ptr().addr() - self.ptr.as_ptr().addr();
|
let elem_size = self.end_ptr.as_ptr().addr() - self.ptr.as_ptr().addr();
|
||||||
let extra_size = self.len * size_of::<Extra<U>>();
|
let extra_size = self.len * size_of::<Extra<U>>();
|
||||||
|
@ -439,7 +474,7 @@ impl<T: ?Sized> Vec<T> {
|
||||||
for i in (0..self.len).rev() {
|
for i in (0..self.len).rev() {
|
||||||
// using references here is necessary for unsizing coercion to work
|
// using references here is necessary for unsizing coercion to work
|
||||||
let current = unsafe { &*self.get_ptr(i) };
|
let current = unsafe { &*self.get_ptr(i) };
|
||||||
unsafe { new_vec.set_extra_from_ptr(i, current as &U) }
|
unsafe { new_vec.set_extra_from_ptr(i, coercer(current)) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// new extra smaller or same size as old extra, must go from front to back
|
// new extra smaller or same size as old extra, must go from front to back
|
||||||
|
@ -447,7 +482,7 @@ impl<T: ?Sized> Vec<T> {
|
||||||
for i in 0..self.len {
|
for i in 0..self.len {
|
||||||
// using references here is necessary for unsizing coercion to work
|
// using references here is necessary for unsizing coercion to work
|
||||||
let current = unsafe { &*self.get_ptr(i) };
|
let current = unsafe { &*self.get_ptr(i) };
|
||||||
unsafe { new_vec.set_extra_from_ptr(i, current as &U) }
|
unsafe { new_vec.set_extra_from_ptr(i, coercer(current)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,9 +499,20 @@ impl<T: ?Sized> Vec<T> {
|
||||||
/// Extends this vector with an iterator.
|
/// Extends this vector with an iterator.
|
||||||
///
|
///
|
||||||
/// Similar to [`Extend::extend`], but seperate to prevent conflicting implementations.
|
/// 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>) {
|
||||||
for item in iter {
|
for item in iter {
|
||||||
self.push_unsize(item);
|
self.push_unsize_stable(item, coercer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +535,7 @@ impl<T: ?Sized> Vec<T> {
|
||||||
let mut new_ptr = self.get_ptr_before_pad(index);
|
let mut new_ptr = self.get_ptr_before_pad(index);
|
||||||
// align it up to the align of the NEXT element
|
// align it up to the align of the NEXT element
|
||||||
let next_ptr = self.get_ptr(index + 1);
|
let next_ptr = self.get_ptr(index + 1);
|
||||||
new_ptr = new_ptr.align_up(align_of_val_raw(next_ptr));
|
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 its the same, we can break as the rest will be useless
|
||||||
if new_ptr == next_ptr { break }
|
if new_ptr == next_ptr { break }
|
||||||
|
@ -581,9 +627,10 @@ impl Vec<dyn Any> {
|
||||||
impl<T: ?Sized> Drop for Vec<T> {
|
impl<T: ?Sized> Drop for Vec<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
for i in 0..self.len {
|
for el in self.iter_mut() {
|
||||||
drop_in_place(self.get_unchecked_mut(i));
|
drop_in_place(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dealloc();
|
self.dealloc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,7 +686,8 @@ macro_rules! vec {
|
||||||
}};
|
}};
|
||||||
(unsized: $($elem:expr),+ $(,)?) => {{
|
(unsized: $($elem:expr),+ $(,)?) => {{
|
||||||
let mut vec = $crate::Vec::new();
|
let mut vec = $crate::Vec::new();
|
||||||
$(vec.push_unsize($elem);)+
|
// TODO: when stuff stabalizes change this
|
||||||
|
$(vec.push_unsize_stable($elem, |v| v as _);)+
|
||||||
vec
|
vec
|
||||||
}};
|
}};
|
||||||
($elem:expr; $n:expr) => {
|
($elem:expr; $n:expr) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{ptr::{self, Pointee}, mem::size_of_val_raw, alloc::{alloc, Layout}};
|
use std::{alloc::{alloc, Layout}, mem::size_of_val, ptr::addr_of_mut};
|
||||||
|
|
||||||
use self::__priv::Sealed;
|
use self::__priv::Sealed;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ impl<T: ?Sized> PtrExt for *const T {
|
||||||
type Pointee = T;
|
type Pointee = T;
|
||||||
|
|
||||||
fn addr(self) -> usize {
|
fn addr(self) -> usize {
|
||||||
self.to_raw_parts().0 as usize
|
self.data_ptr() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_up(self, align: usize) -> Self {
|
fn align_up(self, align: usize) -> Self {
|
||||||
|
@ -48,12 +48,15 @@ impl<T: ?Sized> PtrExt for *const T {
|
||||||
self.with_addr(addr.addr())
|
self.with_addr(addr.addr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_addr(self, addr: usize) -> Self {
|
fn with_addr(mut self, addr: usize) -> Self {
|
||||||
ptr::from_raw_parts(addr as _, self.to_raw_parts().1)
|
// TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
|
||||||
|
unsafe { *addr_of_mut!(self).cast() = addr }
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_end(self) -> Self {
|
unsafe fn get_end(self) -> Self {
|
||||||
self.add_bytes(size_of_val_raw(self))
|
// TODO: _raw
|
||||||
|
self.add_bytes(size_of_val(&*self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_bytes(self, offset: usize) -> Self {
|
fn add_bytes(self, offset: usize) -> Self {
|
||||||
|
@ -69,11 +72,13 @@ impl<T: ?Sized> PtrExt for *const T {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
||||||
self.copy_bytes_to(dest, size_of_val_raw(self));
|
// TODO: _raw
|
||||||
|
self.copy_bytes_to(dest, size_of_val(&*self));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
||||||
let alloc = alloc(Layout::for_value_raw(self));
|
// TODO: _raw
|
||||||
|
let alloc = alloc(Layout::for_value(&*self));
|
||||||
self.copy_val_to(alloc);
|
self.copy_val_to(alloc);
|
||||||
Box::from_raw(alloc.with_meta_from(self))
|
Box::from_raw(alloc.with_meta_from(self))
|
||||||
}
|
}
|
||||||
|
@ -83,7 +88,7 @@ impl<T: ?Sized> PtrExt for *mut T {
|
||||||
type Pointee = T;
|
type Pointee = T;
|
||||||
|
|
||||||
fn addr(self) -> usize {
|
fn addr(self) -> usize {
|
||||||
self.to_raw_parts().0 as usize
|
self.data_ptr() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_up(self, align: usize) -> Self {
|
fn align_up(self, align: usize) -> Self {
|
||||||
|
@ -94,12 +99,15 @@ impl<T: ?Sized> PtrExt for *mut T {
|
||||||
self.with_addr(addr.addr())
|
self.with_addr(addr.addr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_addr(self, addr: usize) -> Self {
|
fn with_addr(mut self, addr: usize) -> Self {
|
||||||
ptr::from_raw_parts_mut(addr as _, self.to_raw_parts().1)
|
// TODO: aaaaand this is cheating. sorry yall, cant do this until `set_ptr_value` lands
|
||||||
|
unsafe { *addr_of_mut!(self).cast() = addr }
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_end(self) -> Self {
|
unsafe fn get_end(self) -> Self {
|
||||||
self.add_bytes(size_of_val_raw(self))
|
// TODO: _raw
|
||||||
|
self.add_bytes(size_of_val(&*self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_bytes(self, offset: usize) -> Self {
|
fn add_bytes(self, offset: usize) -> Self {
|
||||||
|
@ -115,11 +123,13 @@ impl<T: ?Sized> PtrExt for *mut T {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
unsafe fn copy_val_to<U: ?Sized>(self, dest: *mut U) {
|
||||||
self.copy_bytes_to(dest, size_of_val_raw(self));
|
// TODO: _raw
|
||||||
|
self.copy_bytes_to(dest, size_of_val(&*self));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
unsafe fn read_to_box(self) -> Box<Self::Pointee> {
|
||||||
let alloc = alloc(Layout::for_value_raw(self));
|
// TODO: _raw
|
||||||
|
let alloc = alloc(Layout::for_value(&*self));
|
||||||
self.copy_val_to(alloc);
|
self.copy_val_to(alloc);
|
||||||
Box::from_raw(alloc.with_meta_from(self))
|
Box::from_raw(alloc.with_meta_from(self))
|
||||||
}
|
}
|
||||||
|
@ -129,22 +139,20 @@ impl<T: ?Sized> PtrExt for *mut T {
|
||||||
pub trait ConstPtrExt: Sealed {
|
pub trait ConstPtrExt: Sealed {
|
||||||
fn data_ptr(self) -> *const ();
|
fn data_ptr(self) -> *const ();
|
||||||
|
|
||||||
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U;
|
|
||||||
|
|
||||||
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U;
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> ConstPtrExt for *const T {
|
impl<T: ?Sized> ConstPtrExt for *const T {
|
||||||
fn data_ptr(self) -> *const () {
|
fn data_ptr(self) -> *const () {
|
||||||
self.to_raw_parts().0
|
self.cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U {
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *const U {
|
||||||
ptr::from_raw_parts(self.data_ptr(), meta)
|
// ptr::from_raw_parts(self.data_ptr(), meta)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U {
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *const U {
|
||||||
self.with_meta(ptr.to_raw_parts().1)
|
ptr.with_addr_from(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,21 +160,21 @@ impl<T: ?Sized> ConstPtrExt for *const T {
|
||||||
pub trait MutPtrExt: Sealed {
|
pub trait MutPtrExt: Sealed {
|
||||||
fn data_ptr(self) -> *mut ();
|
fn data_ptr(self) -> *mut ();
|
||||||
|
|
||||||
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U;
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U;
|
||||||
|
|
||||||
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U;
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> MutPtrExt for *mut T {
|
impl<T: ?Sized> MutPtrExt for *mut T {
|
||||||
fn data_ptr(self) -> *mut () {
|
fn data_ptr(self) -> *mut () {
|
||||||
self.to_raw_parts().0
|
self.cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U {
|
// fn with_meta<U: ?Sized>(self, meta: <U as Pointee>::Metadata) -> *mut U {
|
||||||
ptr::from_raw_parts_mut(self.data_ptr(), meta)
|
// ptr::from_raw_parts_mut(self.data_ptr(), meta)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
|
fn with_meta_from<U: ?Sized>(self, ptr: *const U) -> *mut U {
|
||||||
self.with_meta(ptr.to_raw_parts().1)
|
ptr.with_addr_from(self) as _
|
||||||
}
|
}
|
||||||
}
|
}
|
33
src/test.rs
33
src/test.rs
|
@ -32,9 +32,9 @@ fn box_push() {
|
||||||
#[test]
|
#[test]
|
||||||
fn unsize_push() {
|
fn unsize_push() {
|
||||||
let mut vec: Vec<dyn Debug> = Vec::new();
|
let mut vec: Vec<dyn Debug> = Vec::new();
|
||||||
vec.push_unsize(1);
|
vec.push_unsize_stable(1, |v| v as _);
|
||||||
vec.push_unsize(String::from("foo"));
|
vec.push_unsize_stable(String::from("foo"), |v| v as _);
|
||||||
vec.push_unsize(true);
|
vec.push_unsize_stable(true, |v| v as _);
|
||||||
assert_eq!(vec.debug(), "[1, \"foo\", true]");
|
assert_eq!(vec.debug(), "[1, \"foo\", true]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,11 +69,11 @@ fn dropped() {
|
||||||
|
|
||||||
let vec: Vec<dyn Debug> = vec![unsized: 1, FunkyDrop, true];
|
let vec: Vec<dyn Debug> = vec![unsized: 1, FunkyDrop, true];
|
||||||
|
|
||||||
assert_eq!(DROPPED.load(Ordering::SeqCst), false);
|
assert!(!DROPPED.load(Ordering::SeqCst));
|
||||||
|
|
||||||
drop(vec);
|
drop(vec);
|
||||||
|
|
||||||
assert_eq!(DROPPED.load(Ordering::SeqCst), true);
|
assert!(DROPPED.load(Ordering::SeqCst));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -92,7 +92,7 @@ fn index() {
|
||||||
assert_eq!(vec[0], 3);
|
assert_eq!(vec[0], 3);
|
||||||
assert_eq!(vec[1], 5);
|
assert_eq!(vec[1], 5);
|
||||||
assert_eq!(vec[2], 7);
|
assert_eq!(vec[2], 7);
|
||||||
vec[3];
|
let _ = vec[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -128,21 +128,24 @@ fn iteration() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zst() {
|
fn zst() {
|
||||||
let vec: Vec<()> = vec![(), (), ()];
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
struct Zst;
|
||||||
|
|
||||||
assert_eq!(vec[1], ());
|
let vec: Vec<Zst> = vec![Zst, Zst, Zst];
|
||||||
|
|
||||||
|
assert_eq!(vec[1], Zst);
|
||||||
for el in vec.iter() {
|
for el in vec.iter() {
|
||||||
drop(el);
|
let _ = el;
|
||||||
}
|
}
|
||||||
assert_eq!(vec.debug(), "[(), (), ()]");
|
assert_eq!(vec.debug(), "[Zst, Zst, Zst]");
|
||||||
|
|
||||||
let vec: Vec<dyn Debug> = vec![unsized: (), (), ()];
|
let vec: Vec<dyn Debug> = vec![unsized: Zst, (), Zst];
|
||||||
|
|
||||||
assert_eq!(vec[1].debug(), "()");
|
assert_eq!(vec[1].debug(), "()");
|
||||||
for el in vec.iter() {
|
for el in vec.iter() {
|
||||||
drop(el);
|
let _ = el;
|
||||||
}
|
}
|
||||||
assert_eq!(vec.debug(), "[(), (), ()]");
|
assert_eq!(vec.debug(), "[Zst, (), Zst]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -190,8 +193,8 @@ fn with_capacity() {
|
||||||
#[test]
|
#[test]
|
||||||
fn unsize() {
|
fn unsize() {
|
||||||
let vec = vec![1, 2, 3];
|
let vec = vec![1, 2, 3];
|
||||||
let mut vec: Vec<dyn Debug> = vec.unsize();
|
let mut vec: Vec<dyn Debug> = vec.unsize_stable(|v| v as _);
|
||||||
vec.push_unsize(String::from("foo"));
|
vec.push_unsize_stable(String::from("foo"), |v| v as _);
|
||||||
assert_eq!(vec.debug(), "[1, 2, 3, \"foo\"]");
|
assert_eq!(vec.debug(), "[1, 2, 3, \"foo\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue