docs + various things
This commit is contained in:
parent
b633b374cb
commit
2ce9385f85
114
src/lib.rs
114
src/lib.rs
|
@ -1,3 +1,90 @@
|
||||||
|
//! # A [`Vec<T: ?Sized>`]
|
||||||
|
//!
|
||||||
|
//! A dynamic length collection of unsized elements, akin to [`std::vec::Vec`].
|
||||||
|
//!
|
||||||
|
//! This crate depends on a number of unstable features, namely:
|
||||||
|
//! - `#![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.
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//!
|
||||||
|
//! You can create a `Vec` 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;
|
||||||
|
//! let vec: Vec<i32> = vec![1, 2, 3];
|
||||||
|
//! // check the docs for `vec!` for more info on this syntax
|
||||||
|
//! let vec_boxed: Vec<dyn Debug> = vec![box: Box::new(1) as _, Box::new("foo") as _, Box::new(true) as _];
|
||||||
|
//! let vec_unsized: Vec<dyn Debug> = vec![unsized: 1, "foo", true];
|
||||||
|
//! # assert_eq!(format!("{:?}", vec), "[1, 2, 3]");
|
||||||
|
//! # assert_eq!(format!("{:?}", vec_boxed), r#"[1, "foo", true]"#);
|
||||||
|
//! # assert_eq!(format!("{:?}", vec_unsized), r#"[1, "foo", true]"#);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! a `Vec` can be pushed to with [`Vec::push`]:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! # 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]");
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ...and with [`push_box`] and [`push_unsize`]
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! # 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));
|
||||||
|
//!
|
||||||
|
//! vec.push_unsize(2);
|
||||||
|
//! vec.push_unsize("bar");
|
||||||
|
//! vec.push_unsize(false);
|
||||||
|
//! # assert_eq!(format!("{:?}", vec), r#"[1, "foo", true, 2, "bar", false]"#);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! # 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 ─┘
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! [`push_box`]: Vec::push_box
|
||||||
|
//! [`push_unsize`]: Vec::push_unsize
|
||||||
|
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(layout_for_ptr)]
|
#![feature(layout_for_ptr)]
|
||||||
#![feature(coerce_unsized)]
|
#![feature(coerce_unsized)]
|
||||||
|
@ -5,30 +92,29 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
pub mod prelude;
|
// Too small to put in its own file
|
||||||
|
pub mod prelude {
|
||||||
|
pub use super::{Vec, vec};
|
||||||
|
}
|
||||||
|
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::{
|
use std::{
|
||||||
ptr::{NonNull, self, drop_in_place, metadata},
|
ptr::{NonNull, self, drop_in_place, metadata},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
alloc::{alloc, Layout},
|
alloc::{alloc, Layout, dealloc},
|
||||||
mem::{size_of, size_of_val, align_of_val, self, size_of_val_raw},
|
mem::{size_of, size_of_val, align_of_val, self, size_of_val_raw},
|
||||||
slice,
|
slice,
|
||||||
ops::{CoerceUnsized, Index, IndexMut}
|
ops::{CoerceUnsized, Index, IndexMut}
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
|
||||||
std::alloc::dealloc(ptr, layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copy `size` bytes of memory from `src` to `dst`.
|
/// Copy `size` bytes of memory from `src` to `dst`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// `src` must be valid for reads, `dst` must be valid for writes, etc, you get the idea.
|
/// `src` must be valid for reads, `dst` must be valid for writes, etc, you get the idea.
|
||||||
// TODO: inline me! i didnt realize it was avaliable as `copy_from` until the code was mostly complete.
|
// TODO: inline me! i didnt realize it was avaliable as `copy_to` until the code was mostly complete.
|
||||||
unsafe fn memcpy(src: *const u8, dst: *mut u8, size: usize) {
|
unsafe fn memcpy(src: *const u8, dst: *mut u8, size: usize) {
|
||||||
dst.copy_from(src, size);
|
src.copy_to(dst, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align_up<T: ?Sized>(ptr: *const T, align: usize) -> *const T {
|
fn align_up<T: ?Sized>(ptr: *const T, align: usize) -> *const T {
|
||||||
|
@ -41,9 +127,9 @@ fn align_up_mut<T: ?Sized>(ptr: *mut T, align: usize) -> *mut T {
|
||||||
align_up(ptr as _, align) as _
|
align_up(ptr as _, align) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A heap allocated, dynamically sized collection of `?Sized` elements.
|
/// A heap allocated, dynamic length collection of `?Sized` elements.
|
||||||
///
|
///
|
||||||
/// See [`::alloc::vec::Vec`] (the standard library `Vec` type) for more information.
|
/// See [`std::vec::Vec`] (the standard library `Vec` type) for more information.
|
||||||
pub struct Vec<T: ?Sized> {
|
pub struct Vec<T: ?Sized> {
|
||||||
ptr: NonNull<u8>,
|
ptr: NonNull<u8>,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
@ -300,6 +386,12 @@ impl<T: ?Sized> Vec<T> {
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
new_vec
|
new_vec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self) {
|
||||||
|
if self.capacity != 0 {
|
||||||
|
dealloc(self.ptr.as_ptr(), Layout::from_size_align_unchecked(self.capacity, 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Vec<[T]> {
|
impl<T> Vec<[T]> {
|
||||||
|
@ -337,7 +429,7 @@ impl<T: ?Sized> Drop for Vec<T> {
|
||||||
println!("dropping {}", i);
|
println!("dropping {}", i);
|
||||||
drop_in_place(self.get_unchecked_mut(i));
|
drop_in_place(self.get_unchecked_mut(i));
|
||||||
}
|
}
|
||||||
dealloc(self.ptr.as_ptr(), Layout::from_size_align_unchecked(self.capacity, 8));
|
self.dealloc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
pub use super::{Vec, vec};
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::prelude::{Vec, vec};
|
use super::prelude::{*, vec};
|
||||||
use std::{fmt::Debug, sync::atomic::{AtomicBool, Ordering}};
|
use std::{fmt::Debug, sync::atomic::{AtomicBool, Ordering}};
|
||||||
|
|
||||||
trait DebugExt: Debug {
|
trait DebugExt: Debug {
|
||||||
|
@ -47,7 +47,6 @@ fn all_macro() {
|
||||||
Box::new(true) as _,
|
Box::new(true) as _,
|
||||||
];
|
];
|
||||||
let vec3: Vec<dyn Debug> = vec![unsized: 1, String::from("foo"), true];
|
let vec3: Vec<dyn Debug> = vec![unsized: 1, String::from("foo"), true];
|
||||||
// assert_eq!(vec2, vec3); // doesnt compile, but would theoretically work
|
|
||||||
assert_eq!(vec2.debug(), vec3.debug());
|
assert_eq!(vec2.debug(), vec3.debug());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue