diff --git a/Cargo.toml b/Cargo.toml index 5e94c84..b409461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "stack-vec" +description = "Ad-hoc compile-time sized `Vec` like types on the stack" +keywords = ["vec", "stack", "macro"] version = "0.1.0" authors = ["Avril "] edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license = "MIT" [dependencies] diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0ae467 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# stack-vec - Ad-hoc stack vectors + +This crate defines the macro `stack![]`, which can be used to create ad-hoc `Vec` like structs of a specific compile-time size on the stack. + +These structs never allocate on the heap, and expose an API similar to `Vec`. + +## Usage +The macro can be used like `vec!`, with optional type inference. + +``` rust +let sv = stack![100]; // Implicitly typed. Will cause a type inference error if the compiler cannot find the type of `sv` later. +let sv = stack![usize; 100]; // Explicitly typed, circumvents that error. +``` + +To see documentation of the types themselves, see one of the pre-defined `StackVec` types in the crate's root. + +# Pre-defined types +`StackVec` types of powers of 2 up until 4096 are defined in this crate too. +You can use the macro to create your own named non-opaque `StackVec` types as well. +``` rust +stack!(pub type S10Elements S10IntoIter 10); // A `StackVec` type with a capacity of 10. +``` + +# License +MIT + diff --git a/src/lib.rs b/src/lib.rs index f8ebe82..c7c5547 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,26 @@ +//! # Ad-hoc stack vectors +//! This crate defines the macro `stack![]`, which can be used to create ad-hoc `Vec` like structs of a specific compile-time size on the stack. +//! These structs never allocate on the heap, and expose an API similar to `Vec`. +//! ## Usage +//! The macro can be used like `vec!`, with optional type inference. +//! +//! ``` +//! # use stack_vec::stack; +//! let mut sv = stack![100]; // Implicitly typed. +//! sv.push(10usize); +//! let sv = stack![usize; 100]; // Explicitly typed, circumvents that error. +//! ``` +//! +//! To see documentation of the types themselves, see one of the pre-defined `StackVec` types in the crate's root. +//! # Pre-defined types +//! `StackVec` types of powers of 2 up until 4096 are defined in this crate too. +//! +//! You can use the macro to create your own named non-opaque `StackVec` types as well. +//! ``` +//! # use stack_vec::stack; +//! stack!(pub type S10Elements S10IntoIter 10); // A `StackVec` type with a capacity of 10. +//! ``` + /// Create an ad-hoc sized `Vec`-like array on the stack. /// @@ -424,19 +447,31 @@ output } } - - + + /// Consuming iterator type for a `StackVec` pub struct $into_iter_name($name, usize); impl $into_iter_name { #![allow(dead_code)] - pub fn rest(&self) -> &[std::mem::MaybeUninit] + /// The rest of the initialised buffer that has not been consumed yet. + #[inline] pub fn rest(&self) -> &[T] + { + &self.0.as_slice()[self.1..] + } + + #[inline(always)] fn m_rest(&self) -> &[std::mem::MaybeUninit] { &self.0.init_buffer()[self.1..] } - pub fn rest_mut(&mut self) -> &mut [std::mem::MaybeUninit] + /// A mutable reference to the rest of the initialised buffer that has not been consumed yet. + #[inline] pub fn rest_mut(&mut self) -> &mut [T] + { + &mut self.0.as_mut_slice()[self.1..] + } + + #[inline(always)] fn m_rest_mut(&mut self) -> &mut [std::mem::MaybeUninit] { &mut self.0.init_buffer_mut()[self.1..] } @@ -469,7 +504,7 @@ { if std::mem::needs_drop::() { unsafe { - for init in self.rest_mut() { + for init in self.m_rest_mut() { drop(std::mem::replace(init, std::mem::MaybeUninit::uninit()).assume_init()); }