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(layout_for_ptr)]
|
||||
#![feature(coerce_unsized)]
|
||||
|
@ -5,30 +92,29 @@
|
|||
#[cfg(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 std::{
|
||||
ptr::{NonNull, self, drop_in_place, metadata},
|
||||
marker::PhantomData,
|
||||
alloc::{alloc, Layout},
|
||||
alloc::{alloc, Layout, dealloc},
|
||||
mem::{size_of, size_of_val, align_of_val, self, size_of_val_raw},
|
||||
slice,
|
||||
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`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `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) {
|
||||
dst.copy_from(src, size);
|
||||
src.copy_to(dst, size);
|
||||
}
|
||||
|
||||
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 _
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
ptr: NonNull<u8>,
|
||||
len: usize,
|
||||
|
@ -300,6 +386,12 @@ impl<T: ?Sized> Vec<T> {
|
|||
mem::forget(self);
|
||||
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]> {
|
||||
|
@ -337,7 +429,7 @@ impl<T: ?Sized> Drop for Vec<T> {
|
|||
println!("dropping {}", 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}};
|
||||
|
||||
trait DebugExt: Debug {
|
||||
|
@ -47,7 +47,6 @@ fn all_macro() {
|
|||
Box::new(true) as _,
|
||||
];
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue