Merge pull request #60 from Nemo157/macro-🚫type

Allow inferring array type for macro constructors
This commit is contained in:
Lokathor
2020-01-29 18:51:56 -07:00
committed by GitHub
5 changed files with 106 additions and 16 deletions
+8
View File
@@ -40,6 +40,14 @@ all-features = true
[workspace]
members = ["fuzz"]
[dev-dependencies]
criterion = "0.3.0"
[[test]]
name = "tinyvec"
required-features = ["alloc"]
[[bench]]
name = "macros"
harness = false
required-features = ["alloc"]
+48
View File
@@ -0,0 +1,48 @@
use criterion::{criterion_group, criterion_main, Criterion};
use tinyvec::tiny_vec;
fn bench_tinyvec_macro(c: &mut Criterion) {
let mut g = c.benchmark_group("tinyvec_macro");
g.bench_function("0 of 32", |b| {
b.iter(|| tiny_vec!([u8; 32]));
});
g.bench_function("16 of 32", |b| {
b.iter(||
tiny_vec!([u8; 32],
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
));
});
g.bench_function("32 of 32", |b| {
b.iter(||
tiny_vec!([u8; 32],
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
));
});
g.bench_function("33 of 32", |b| {
b.iter(||
tiny_vec!([u8; 32],
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33,
));
});
g.bench_function("64 of 32", |b| {
b.iter(||
tiny_vec!([u8; 32],
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
));
});
}
criterion_group!(benches, bench_tinyvec_macro);
criterion_main!(benches);
+14 -4
View File
@@ -11,25 +11,35 @@ use super::*;
/// ```rust
/// use tinyvec::*;
///
/// // The backing array type can be specified in the macro call
/// let empty_av = array_vec!([u8; 16]);
///
/// let some_ints = array_vec!([i32; 4], 1, 2, 3);
///
/// // Or left to inference
/// let empty_av: ArrayVec<[u8; 10]> = array_vec!();
/// let some_ints: ArrayVec<[u8; 10]> = array_vec!(5, 6, 7, 8);
/// ```
#[macro_export]
macro_rules! array_vec {
($array_type:ty) => {
{
let av: ArrayVec<$array_type> = Default::default();
let av: $crate::ArrayVec<$array_type> = Default::default();
av
}
};
($array_type:ty, $($elem:expr),*) => {
{
let mut av: ArrayVec<$array_type> = Default::default();
let mut av: $crate::ArrayVec<$array_type> = Default::default();
$( av.push($elem); )*
av
}
};
() => {
array_vec!(_)
};
($($elem:expr),*) => {
array_vec!(_, $($elem),*)
};
}
/// An array-backed, vector-like data structure.
@@ -251,7 +261,7 @@ impl<A: Array> ArrayVec<A> {
}
/// Clone each element of the slice into this `ArrayVec`.
///
///
/// ## Panics
/// * If the `ArrayVec` would overflow, this will panic.
#[inline]
+2 -1
View File
@@ -75,7 +75,8 @@ use core::{
};
#[cfg(feature = "alloc")]
extern crate alloc;
#[doc(hidden)] // re-export for macros
pub extern crate alloc;
mod array;
pub use array::*;
+34 -11
View File
@@ -15,21 +15,25 @@ use alloc::vec::Vec;
/// ```rust
/// use tinyvec::*;
///
/// // The backing array type can be specified in the macro call
/// let empty_tv = tiny_vec!([u8; 16]);
///
/// let some_ints = tiny_vec!([i32; 4], 1, 2, 3);
///
/// let many_ints = tiny_vec!([i32; 4], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
///
/// // Or left to inference
/// let empty_tv: TinyVec<[u8; 16]> = tiny_vec!();
/// let some_ints: TinyVec<[i32; 4]> = tiny_vec!(1, 2, 3);
/// let many_ints: TinyVec<[i32; 4]> = tiny_vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
/// ```
#[macro_export]
macro_rules! tiny_vec {
($array_type:ty) => {
{
let mut tv: TinyVec<$array_type> = Default::default();
let mut tv: $crate::TinyVec<$array_type> = Default::default();
tv
}
};
($array_type:ty, $($elem:expr),*) => {
($array_type:ty, $($elem:expr),* $(,)?) => {
{
// Note(Lokathor): This goofy looking thing will count the number of
// `$elem` entries we were given. We can't spit out the "+1"s on their
@@ -42,14 +46,19 @@ macro_rules! tiny_vec {
const INVOKED_ELEM_COUNT: usize = 0 $( + { let _ = stringify!($elem); 1 })*;
// If we have more `$elem` than the `CAPACITY` we will simply go directly
// to constructing on the heap.
let av: TinyVec<$array_type> = if INVOKED_ELEM_COUNT <= <$array_type as Array>::CAPACITY {
TinyVec::<$array_type>::Inline(array_vec!($array_type, $($elem),*))
} else {
TinyVec::<$array_type>::Heap(vec!($($elem),*))
};
let av: $crate::TinyVec<$array_type> = $crate::TinyVec::from_either_with_capacity(
INVOKED_ELEM_COUNT,
#[inline(always)] || $crate::array_vec!($array_type, $($elem),*),
#[inline(always)] || vec!($($elem),*));
av
}
};
() => {
tiny_vec!(_)
};
($($elem:expr),*) => {
tiny_vec!(_, $($elem),*)
};
}
/// A vector that starts inline, but can automatically move to the heap.
@@ -65,9 +74,9 @@ macro_rules! tiny_vec {
///
/// Because it's an enum, you can construct a `TinyVec` simply by making an
/// `ArrayVec` or `Vec` and then putting it into the enum.
///
///
/// There is also a macro
///
///
/// ```rust
/// # use tinyvec::*;
/// let empty_tv = tiny_vec!([u8; 16]);
@@ -333,6 +342,20 @@ impl<A: Array> TinyVec<A> {
}
}
#[inline(always)]
#[doc(hidden)] // Internal implementation details of `tiny_vec!`
pub fn from_either_with_capacity(
cap: usize,
make_array: impl FnOnce() -> ArrayVec<A>,
make_vec: impl FnOnce() -> Vec<A::Item>,
) -> Self {
if cap <= A::CAPACITY {
TinyVec::Inline(make_array())
} else {
TinyVec::Heap(make_vec())
}
}
/// Inserts an item at the position given, moving all following elements +1
/// index.
///