From cbabf7444959273793a4cd18f25f4d7cf779c976 Mon Sep 17 00:00:00 2001 From: Caio Date: Mon, 28 Sep 2020 12:47:08 -0300 Subject: [PATCH] Tweak API --- text/2978-stack_based_vec.md | 73 ++++++++++++------------------------ 1 file changed, 23 insertions(+), 50 deletions(-) diff --git a/text/2978-stack_based_vec.md b/text/2978-stack_based_vec.md index 679345be65f..0b3a4ebb38d 100644 --- a/text/2978-stack_based_vec.md +++ b/text/2978-stack_based_vec.md @@ -86,22 +86,28 @@ Of course, fixed buffers lead to some inflexibility because unlike `Vec`, the un # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -`ArrayVec` is a contiguous memory block where elements can be collected, threfore, a collection by definition and even though `core::collections` doesn't exist, it is the most natural module placement. +`ArrayVec` is a contiguous memory block where elements can be collected, therefore, a collection by definition and even though `core::collections` doesn't exist, it is the most natural module placement. -The API basically mimics most of the current `Vec` surface with some tweaks and additional methods to manage capacity. Notably, these additional methods are fallible versions of some well-known functions like `insert` that will return `Result` instead of panicking at run-time. +The API basically mimics most of the current `Vec` surface with some tweaks to manage capacity. + +Notably, these tweaked methods are fallible versions of some well-known functions like `push` that will return `Result` instead of panicking at run-time. Since the upper capacity bound is known at compile-time, the compiler is likely going to remove most of the conditional bounding checking. ```rust // core::collections pub struct ArrayVec { data: MaybeUninit<[T; N]>, - len: usize + len: usize, } impl ArrayVec { // Constructors - pub unsafe fn from_raw_parts(_ptr: *mut T, _len: usize) -> Self; + #[inline] + pub fn from_array(array: [T; N]) -> Self; + + #[inline] + pub fn from_array_and_len(array: [T; N], len: usize) -> Self; #[inline] pub const fn new() -> Self; @@ -140,15 +146,15 @@ impl ArrayVec { where R: RangeBounds; - pub fn extend_from_cloneable_slice(&mut self, other: &[T]) + pub fn extend_from_cloneable_slice(&mut self, other: &[T]) -> Result<(), &[T]> where - T: Clone; // Panics at run-time + T: Clone; - pub fn extend_from_copyable_slice(&mut self, other: &[T]) + pub fn extend_from_copyable_slice(&mut self, other: &[T]) -> Result<(), &[T]> where - T: Copy; // Panics at run-time + T: Copy; - pub fn insert(&mut self, idx: usize, element: T); // Panics at run-time + pub fn insert(&mut self, _idx: usize, element: T) -> Result<(), T>; #[inline] pub const fn is_empty(&self) -> bool; @@ -156,11 +162,12 @@ impl ArrayVec { #[inline] pub const fn len(&self) -> usize; - pub fn pop(&mut self) -> T; // Panics at run-time + pub fn pop(&mut self) -> Option; - pub fn push(&mut self, element: T); // Panics at run-time + #[inline] + pub fn push(&mut self, element: T) -> Result<(), T>; - pub fn remove(&mut self, idx: usize) -> T; // Panics at run-time + pub fn remove(&mut self, idx: usize) -> Option; pub fn retain(&mut self, f: F) where @@ -176,49 +183,15 @@ impl ArrayVec { pub fn split_off(&mut self, at: usize) -> Self; - pub fn swap_remove(&mut self, idx: usize) -> T; // Panics at run-time + pub fn swap_remove(&mut self, idx: usize) -> Option; pub fn truncate(&mut self, len: usize); - - pub fn try_extend_from_cloneable_slice(&mut self, other: &[T]) -> Result<(), ArrayVecError> - where - T: Clone; - - pub fn try_extend_from_copyable_slice(&mut self, other: &[T]) -> Result<(), ArrayVecError> - where - T: Copy; - - pub fn try_insert(&mut self, _idx: usize, element: T) -> Result<(), ArrayVecError>; - - pub fn try_pop(&mut self) -> Result; - - pub fn try_push(&mut self, element: T) -> Result<(), ArrayVecError>; - - pub fn try_remove(&mut self, idx: usize) -> Result; - - pub fn try_swap_remove(&mut self, idx: usize) -> Result; -} - -#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] -pub enum ArrayVecError { - CapacityOverflow, - NoElement -} - -impl fmt::Display for ArrayVecError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - Self::CapacityOverflow => "It is not possible to add more elements", - Self::NoElement => "There are no elements in the vector", - }; - write!(f, "{}", s) - } } ``` -Meaningless, unstable and deprecated methods like `reserve` or `drain_filter` weren't considered and in general, everything that includes or removes elements have a fallible version: `extend_from_cloneable_slice`, `extend_from_copyable_slice`, `pop`, `remove` and `swap_remove`. +Since it is known at compile-time the upper capacity bound, the compiler is likely going to remove the conditional bounding checking of the newly -A concrete implementation is available at https://github.com/c410-f3r/stack-based-vec. +Meaningless, unstable and deprecated methods like `reserve` or `drain_filter` weren't considered. A concrete implementation is available at https://github.com/c410-f3r/stack-based-vec. # Drawbacks [drawbacks]: #drawbacks @@ -229,7 +202,7 @@ New and existing users are likely to find it difficult to differentiate the purp ### The current ecosystem is fine -Even with all the fragmentation, different types of memory usage is an overkill in certain situations. If someone wants to use stack memory in an embedded application, then it is just a matter of grabbing an appropriated crate. +`ArrayVec` might be an overkill in certain situations. If someone wants to use stack memory in a specific application, then it is just a matter of grabbing the appropriated crate. # Prior art [prior-art]: #prior-art