From f4cc7610578cd78af35ba8d9f08bc49e17d5da68 Mon Sep 17 00:00:00 2001 From: Soveu Date: Sun, 9 Aug 2020 18:52:06 +0200 Subject: [PATCH] Make code DRYer (#107) * make code dryer * arrayset definition caused cargo fmt to fail --- Cargo.toml | 4 +- src/lib.rs | 5 - src/tinyvec.rs | 390 ++++++++++++++++++++----------------------------- 3 files changed, 162 insertions(+), 237 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fcc6171..026f4a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,13 +10,13 @@ categories = ["data-structures", "no-std"] repository = "https://github.com/Lokathor/tinyvec" [dependencies] -# not even std! +tinyvec_macros = { version = "0.1", optional = true } [features] default = [] # Provide things that utilize the `alloc` crate, namely `TinyVec`. -alloc = [] +alloc = ["tinyvec_macros"] # (not part of Vec!) Extra methods to let you grab the slice of memory after the # "active" portion of an `ArrayVec` or `SliceVec`. diff --git a/src/lib.rs b/src/lib.rs index e886578..b51b4f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,11 +84,6 @@ pub extern crate alloc; mod array; pub use array::*; -#[cfg(feature = "experimental_array_set")] -mod arrayset; -#[cfg(feature = "experimental_array_set")] -pub use arrayset::*; - mod arrayvec; pub use arrayvec::*; diff --git a/src/tinyvec.rs b/src/tinyvec.rs index 5de4827..8585a82 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -3,6 +3,7 @@ use super::*; use alloc::vec::{self, Vec}; +use tinyvec_macros::impl_mirrored; /// Helper to make a `TinyVec`. /// @@ -100,24 +101,21 @@ impl Default for TinyVec { impl Deref for TinyVec { type Target = [A::Item]; - #[inline(always)] - #[must_use] - fn deref(&self) -> &Self::Target { - match self { - TinyVec::Inline(a) => a.deref(), - TinyVec::Heap(v) => v.deref(), - } + + impl_mirrored! { + type Mirror = TinyVec; + #[inline(always)] + #[must_use] + fn deref(self: &Self) -> &Self::Target; } } impl DerefMut for TinyVec { - #[inline(always)] - #[must_use] - fn deref_mut(&mut self) -> &mut Self::Target { - match self { - TinyVec::Inline(a) => a.deref_mut(), - TinyVec::Heap(v) => v.deref_mut(), - } + impl_mirrored! { + type Mirror = TinyVec; + #[inline(always)] + #[must_use] + fn deref_mut(self: &mut Self) -> &mut Self::Target; } } @@ -336,62 +334,125 @@ impl TinyVec { } } - /// A mutable pointer to the backing array. + impl_mirrored! { + type Mirror = TinyVec; + + /// Remove an element, swapping the end of the vec into its place. + /// + /// ## Panics + /// * If the index is out of bounds. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([&str; 4] => "foo", "bar", "quack", "zap"); + /// + /// assert_eq!(tv.swap_remove(1), "bar"); + /// assert_eq!(tv.as_slice(), &["foo", "zap", "quack"][..]); + /// + /// assert_eq!(tv.swap_remove(0), "foo"); + /// assert_eq!(tv.as_slice(), &["quack", "zap"][..]); + /// ``` + #[inline] + pub fn swap_remove(self: &mut Self, index: usize) -> A::Item; + + /// Remove and return the last element of the vec, if there is one. + /// + /// ## Failure + /// * If the vec is empty you get `None`. + #[inline] + pub fn pop(self: &mut Self) -> Option; + + /// Removes the item at `index`, shifting all others down by one index. + /// + /// Returns the removed element. + /// + /// ## Panics + /// + /// If the index is out of bounds. + /// + /// ## Example + /// + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// assert_eq!(tv.remove(1), 2); + /// assert_eq!(tv.as_slice(), &[1, 3][..]); + /// ``` + #[inline] + pub fn remove(self: &mut Self, index: usize) -> A::Item; + + /// The length of the vec (in elements). + #[inline(always)] + #[must_use] + pub fn len(self: &Self) -> usize; + + /// The capacity of the `TinyVec`. + /// + /// When not heap allocated this is fixed based on the array type. + /// Otherwise its the result of the underlying Vec::capacity. + #[inline(always)] + #[must_use] + pub fn capacity(self: &Self) -> usize; + + /// Reduces the vec's length to the given value. + /// + /// If the vec is already shorter than the input, nothing happens. + #[inline] + pub fn truncate(self: &mut Self, new_len: usize); + + /// A mutable pointer to the backing array. + /// + /// ## Safety + /// + /// This pointer has provenance over the _entire_ backing array/buffer. + #[inline(always)] + #[must_use] + pub fn as_mut_ptr(self: &mut Self) -> *mut A::Item; + + /// A const pointer to the backing array. + /// + /// ## Safety + /// + /// This pointer has provenance over the _entire_ backing array/buffer. + #[inline(always)] + #[must_use] + pub fn as_ptr(self: &Self) -> *const A::Item; + } + + /// Walk the vec and keep only the elements that pass the predicate given. /// - /// ## Safety + /// ## Example /// - /// This pointer has provenance over the _entire_ backing array/buffer. - #[inline(always)] - #[must_use] - pub fn as_mut_ptr(&mut self) -> *mut A::Item { + /// ```rust + /// use tinyvec::*; + /// + /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3, 4); + /// tv.retain(|&x| x % 2 == 0); + /// assert_eq!(tv.as_slice(), &[2, 4][..]); + /// ``` + #[inline] + pub fn retain bool>(self: &mut Self, acceptable: F) { match self { - TinyVec::Inline(a) => a.as_mut_ptr(), - TinyVec::Heap(v) => v.as_mut_ptr(), + TinyVec::Inline(i) => i.retain(acceptable), + TinyVec::Heap(h) => h.retain(acceptable), } } /// Helper for getting the mut slice. #[inline(always)] #[must_use] - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + pub fn as_mut_slice(self: &mut Self) -> &mut [A::Item] { self.deref_mut() } - /// A const pointer to the backing array. - /// - /// ## Safety - /// - /// This pointer has provenance over the _entire_ backing array/buffer. - #[inline(always)] - #[must_use] - pub fn as_ptr(&self) -> *const A::Item { - match self { - TinyVec::Inline(a) => a.as_ptr(), - TinyVec::Heap(v) => v.as_ptr(), - } - } - /// Helper for getting the shared slice. #[inline(always)] #[must_use] - pub fn as_slice(&self) -> &[A::Item] { + pub fn as_slice(self: &Self) -> &[A::Item] { self.deref() } - /// The capacity of the `TinyVec`. - /// - /// When not heap allocated this is fixed based on the array type. - /// Otherwise its the result of the underlying Vec::capacity. - #[inline(always)] - #[must_use] - pub fn capacity(&self) -> usize { - match self { - // Note: this shouldn't use A::CAPACITY. See ArrayVec::capacity(). - TinyVec::Inline(v) => v.capacity(), - TinyVec::Heap(v) => v.capacity(), - } - } - /// Removes all elements from the vec. #[inline(always)] pub fn clear(&mut self) { @@ -565,16 +626,6 @@ impl TinyVec { self.len() == 0 } - /// The length of the vec (in elements). - #[inline(always)] - #[must_use] - pub fn len(&self) -> usize { - match self { - TinyVec::Inline(a) => a.len(), - TinyVec::Heap(v) => v.len(), - } - } - /// Makes a new, empty vec. #[inline(always)] #[must_use] @@ -585,18 +636,6 @@ impl TinyVec { Self::default() } - /// Remove and return the last element of the vec, if there is one. - /// - /// ## Failure - /// * If the vec is empty you get `None`. - #[inline] - pub fn pop(&mut self) -> Option { - match self { - TinyVec::Inline(a) => a.pop(), - TinyVec::Heap(v) => v.pop(), - } - } - /// Place an element onto the end of the vec. /// ## Panics /// * If the length of the vec would overflow the capacity. @@ -621,30 +660,6 @@ impl TinyVec { } } - /// Removes the item at `index`, shifting all others down by one index. - /// - /// Returns the removed element. - /// - /// ## Panics - /// - /// If the index is out of bounds. - /// - /// ## Example - /// - /// ```rust - /// use tinyvec::*; - /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); - /// assert_eq!(tv.remove(1), 2); - /// assert_eq!(tv.as_slice(), &[1, 3][..]); - /// ``` - #[inline] - pub fn remove(&mut self, index: usize) -> A::Item { - match self { - TinyVec::Inline(a) => a.remove(index), - TinyVec::Heap(v) => v.remove(index), - } - } - /// Resize the vec to the new length. /// /// If it needs to be longer, it's filled with clones of the provided value. @@ -706,25 +721,6 @@ impl TinyVec { } } - /// Walk the vec and keep only the elements that pass the predicate given. - /// - /// ## Example - /// - /// ```rust - /// use tinyvec::*; - /// - /// let mut tv = tiny_vec!([i32; 10] => 1, 2, 3, 4); - /// tv.retain(|&x| x % 2 == 0); - /// assert_eq!(tv.as_slice(), &[2, 4][..]); - /// ``` - #[inline] - pub fn retain bool>(&mut self, acceptable: F) { - match self { - TinyVec::Inline(a) => a.retain(acceptable), - TinyVec::Heap(v) => v.retain(acceptable), - } - } - /// Splits the collection at the point given. /// /// * `[0, at)` stays in this vec @@ -818,41 +814,6 @@ impl TinyVec { } } - /// Remove an element, swapping the end of the vec into its place. - /// - /// ## Panics - /// * If the index is out of bounds. - /// - /// ## Example - /// ```rust - /// use tinyvec::*; - /// let mut tv = tiny_vec!([&str; 4] => "foo", "bar", "quack", "zap"); - /// - /// assert_eq!(tv.swap_remove(1), "bar"); - /// assert_eq!(tv.as_slice(), &["foo", "zap", "quack"][..]); - /// - /// assert_eq!(tv.swap_remove(0), "foo"); - /// assert_eq!(tv.as_slice(), &["quack", "zap"][..]); - /// ``` - #[inline] - pub fn swap_remove(&mut self, index: usize) -> A::Item { - match self { - TinyVec::Inline(a) => a.swap_remove(index), - TinyVec::Heap(v) => v.swap_remove(index), - } - } - - /// Reduces the vec's length to the given value. - /// - /// If the vec is already shorter than the input, nothing happens. - #[inline] - pub fn truncate(&mut self, new_len: usize) { - match self { - TinyVec::Inline(a) => a.truncate(new_len), - TinyVec::Heap(v) => v.truncate(new_len), - } - } - /// Wraps an array, using the given length as the starting length. /// /// If you want to use the whole length of the array, you can just use the @@ -882,28 +843,19 @@ pub enum TinyVecDrain<'p, A: Array> { impl<'p, A: Array> Iterator for TinyVecDrain<'p, A> { type Item = A::Item; - #[inline] - fn next(&mut self) -> Option { - match self { - TinyVecDrain::Inline(i) => i.next(), - TinyVecDrain::Heap(h) => h.next(), - } - } + impl_mirrored! { + type Mirror = TinyVecDrain; - #[inline] - fn nth(&mut self, n: usize) -> Option { - match self { - TinyVecDrain::Inline(i) => i.nth(n), - TinyVecDrain::Heap(h) => h.nth(n), - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - match self { - TinyVecDrain::Inline(i) => i.size_hint(), - TinyVecDrain::Heap(h) => h.size_hint(), - } + #[inline] + fn next(self: &mut Self) -> Option; + #[inline] + fn nth(self: &mut Self, n: usize) -> Option; + #[inline] + fn size_hint(self: &Self) -> (usize, Option); + #[inline] + fn last(self: Self) -> Option; + #[inline] + fn count(self: Self) -> usize; } #[inline] @@ -916,21 +868,15 @@ impl<'p, A: Array> Iterator for TinyVecDrain<'p, A> { } impl<'p, A: Array> DoubleEndedIterator for TinyVecDrain<'p, A> { - #[inline] - fn next_back(&mut self) -> Option { - match self { - TinyVecDrain::Inline(i) => i.next_back(), - TinyVecDrain::Heap(h) => h.next_back(), - } - } + impl_mirrored! { + type Mirror = TinyVecDrain; - #[cfg(feature = "rustc_1_40")] - #[inline] - fn nth_back(&mut self, n: usize) -> Option { - match self { - TinyVecDrain::Inline(i) => i.nth_back(n), - TinyVecDrain::Heap(h) => h.nth_back(n), - } + #[inline] + fn next_back(self: &mut Self) -> Option; + + #[cfg(feature = "rustc_1_40")] + #[inline] + fn nth_back(self: &mut Self, n: usize) -> Option; } } @@ -1166,54 +1112,38 @@ pub enum TinyVecIterator { } impl TinyVecIterator { - /// Returns the remaining items of this iterator as a slice. - #[inline] - #[must_use] - pub fn as_slice(&self) -> &[A::Item] { - match self { - TinyVecIterator::Inline(a) => a.as_slice(), - TinyVecIterator::Heap(v) => v.as_slice(), - } + impl_mirrored! { + type Mirror = TinyVecIterator; + /// Returns the remaining items of this iterator as a slice. + #[inline] + #[must_use] + pub fn as_slice(self: &Self) -> &[A::Item]; } } + impl FusedIterator for TinyVecIterator {} + impl Iterator for TinyVecIterator { type Item = A::Item; - #[inline] - fn next(&mut self) -> Option { - match self { - TinyVecIterator::Inline(a) => a.next(), - TinyVecIterator::Heap(v) => v.next(), - } - } - #[inline(always)] - #[must_use] - fn size_hint(&self) -> (usize, Option) { - match self { - TinyVecIterator::Inline(a) => a.size_hint(), - TinyVecIterator::Heap(v) => v.size_hint(), - } - } - #[inline(always)] - fn count(self) -> usize { - match self { - TinyVecIterator::Inline(a) => a.count(), - TinyVecIterator::Heap(v) => v.count(), - } - } - #[inline] - fn last(self) -> Option { - match self { - TinyVecIterator::Inline(a) => a.last(), - TinyVecIterator::Heap(v) => v.last(), - } - } - #[inline] - fn nth(&mut self, n: usize) -> Option { - match self { - TinyVecIterator::Inline(a) => a.nth(n), - TinyVecIterator::Heap(v) => v.nth(n), - } + + impl_mirrored! { + type Mirror = TinyVecIterator; + + #[inline] + fn next(self: &mut Self) -> Option; + + #[inline(always)] + #[must_use] + fn size_hint(self: &Self) -> (usize, Option); + + #[inline(always)] + fn count(self: Self) -> usize; + + #[inline] + fn last(self: Self) -> Option; + + #[inline] + fn nth(self: &mut Self, n: usize) -> Option; } }