mirror of
https://github.com/openharmony/third_party_rust_rust-smallvec.git
synced 2026-07-21 01:55:25 -04:00
Added feature const_new which enables SmallVec::new_const() (#265)
This commit is contained in:
@@ -13,6 +13,7 @@ documentation = "https://docs.rs/smallvec/"
|
||||
|
||||
[features]
|
||||
const_generics = []
|
||||
const_new = ["const_generics"]
|
||||
write = []
|
||||
union = []
|
||||
specialization = []
|
||||
@@ -23,3 +24,7 @@ serde = { version = "1", optional = true, default-features = false }
|
||||
|
||||
[dev_dependencies]
|
||||
bincode = "1.0.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
+109
-3
@@ -48,6 +48,14 @@
|
||||
//! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed
|
||||
//! list of sizes.
|
||||
//!
|
||||
//! ### `const_new`
|
||||
//!
|
||||
//! **This feature requires Rust 1.51.**
|
||||
//!
|
||||
//! This feature exposes the functions [`SmallVec::new_const`], [`SmallVec::from_const`], and [`smallvec_inline`] which enables the `SmallVec` to be initialized from a const context.
|
||||
//! For details, see the
|
||||
//! [Rust Reference](https://doc.rust-lang.org/reference/const_eval.html#const-functions).
|
||||
//!
|
||||
//! ### `specialization`
|
||||
//!
|
||||
//! **This feature is unstable and requires a nightly build of the Rust toolchain.**
|
||||
@@ -69,6 +77,7 @@
|
||||
//! Tracking issue: [rust-lang/rust#34761](https://github.com/rust-lang/rust/issues/34761)
|
||||
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![cfg_attr(feature = "specialization", allow(incomplete_features))]
|
||||
#![cfg_attr(feature = "specialization", feature(specialization))]
|
||||
#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))]
|
||||
@@ -170,6 +179,52 @@ macro_rules! smallvec {
|
||||
});
|
||||
}
|
||||
|
||||
/// Creates an inline [`SmallVec`] containing the arguments. This macro is enabled by the feature `const_new`.
|
||||
///
|
||||
/// `smallvec_inline!` allows `SmallVec`s to be defined with the same syntax as array expressions in `const` contexts.
|
||||
/// The inline storage `A` will always be an array of the size specified by the arguments.
|
||||
/// There are two forms of this macro:
|
||||
///
|
||||
/// - Create a [`SmallVec`] containing a given list of elements:
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate smallvec;
|
||||
/// # use smallvec::SmallVec;
|
||||
/// # fn main() {
|
||||
/// const V: SmallVec<[i32; 3]> = smallvec_inline![1, 2, 3];
|
||||
/// assert_eq!(V[0], 1);
|
||||
/// assert_eq!(V[1], 2);
|
||||
/// assert_eq!(V[2], 3);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// - Create a [`SmallVec`] from a given element and size:
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate smallvec;
|
||||
/// # use smallvec::SmallVec;
|
||||
/// # fn main() {
|
||||
/// const V: SmallVec<[i32; 3]> = smallvec_inline![1; 3];
|
||||
/// assert_eq!(V, SmallVec::from_buf([1, 1, 1]));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Note that the behavior mimics that of array expressions, in contrast to [`smallvec`].
|
||||
#[cfg(feature = "const_new")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
|
||||
#[macro_export]
|
||||
macro_rules! smallvec_inline {
|
||||
// count helper: transform any expression into 1
|
||||
(@one $x:expr) => (1usize);
|
||||
($elem:expr; $n:expr) => ({
|
||||
$crate::SmallVec::<[_; $n]>::from_const([$elem; $n])
|
||||
});
|
||||
($($x:expr),+ $(,)?) => ({
|
||||
const N: usize = 0usize $(+ $crate::smallvec_inline!(@one $x))*;
|
||||
$crate::SmallVec::<[_; N]>::from_const([$($x,)*])
|
||||
});
|
||||
}
|
||||
|
||||
/// `panic!()` in debug builds, optimization hint in release.
|
||||
#[cfg(not(feature = "union"))]
|
||||
macro_rules! debug_unreachable {
|
||||
@@ -353,6 +408,17 @@ union SmallVecData<A: Array> {
|
||||
heap: (*mut A::Item, usize),
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "union", feature = "const_new"))]
|
||||
impl<T, const N: usize> SmallVecData<[T; N]> {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
|
||||
#[inline]
|
||||
const fn from_const(inline: MaybeUninit<[T; N]>) -> Self {
|
||||
SmallVecData {
|
||||
inline: core::mem::ManuallyDrop::new(inline),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "union")]
|
||||
impl<A: Array> SmallVecData<A> {
|
||||
#[inline]
|
||||
@@ -393,6 +459,15 @@ enum SmallVecData<A: Array> {
|
||||
Heap((*mut A::Item, usize)),
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "union"), feature = "const_new"))]
|
||||
impl<T, const N: usize> SmallVecData<[T; N]> {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
|
||||
#[inline]
|
||||
const fn from_const(inline: MaybeUninit<[T; N]>) -> Self {
|
||||
SmallVecData::Inline(inline)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "union"))]
|
||||
impl<A: Array> SmallVecData<A> {
|
||||
#[inline]
|
||||
@@ -1487,6 +1562,7 @@ impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "write")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "write")))]
|
||||
impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
@@ -1507,6 +1583,7 @@ impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||
impl<A: Array> Serialize for SmallVec<A>
|
||||
where
|
||||
A::Item: Serialize,
|
||||
@@ -1521,6 +1598,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||
impl<'de, A: Array> Deserialize<'de> for SmallVec<A>
|
||||
where
|
||||
A::Item: Deserialize<'de>,
|
||||
@@ -1950,7 +2028,35 @@ impl<'a> Drop for SetLenOnDrop<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "const_generics")]
|
||||
#[cfg(feature = "const_new")]
|
||||
impl<T, const N: usize> SmallVec<[T; N]> {
|
||||
/// Construct an empty vector.
|
||||
///
|
||||
/// This is a `const` version of [`SmallVec::new`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
|
||||
#[inline]
|
||||
pub const fn new_const() -> Self {
|
||||
SmallVec {
|
||||
capacity: 0,
|
||||
data: SmallVecData::from_const(MaybeUninit::uninit()),
|
||||
}
|
||||
}
|
||||
|
||||
/// The array passed as an argument is moved to be an inline version of `SmallVec`.
|
||||
///
|
||||
/// This is a `const` version of [`SmallVec::from_buf`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))]
|
||||
#[inline]
|
||||
pub const fn from_const(items: [T; N]) -> Self {
|
||||
SmallVec {
|
||||
capacity: N,
|
||||
data: SmallVecData::from_const(MaybeUninit::new(items)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "const_generics", not(doc)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "const_generics")))]
|
||||
unsafe impl<T, const N: usize> Array for [T; N] {
|
||||
type Item = T;
|
||||
fn size() -> usize {
|
||||
@@ -1958,7 +2064,7 @@ unsafe impl<T, const N: usize> Array for [T; N] {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "const_generics"))]
|
||||
#[cfg(any(not(feature = "const_generics"), doc))]
|
||||
macro_rules! impl_array(
|
||||
($($size:expr),+) => {
|
||||
$(
|
||||
@@ -1970,7 +2076,7 @@ macro_rules! impl_array(
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "const_generics"))]
|
||||
#[cfg(any(not(feature = "const_generics"), doc))]
|
||||
impl_array!(
|
||||
0, 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, 36, 0x40, 0x60, 0x80, 0x100, 0x200, 0x400, 0x600, 0x800, 0x1000,
|
||||
|
||||
@@ -903,6 +903,35 @@ fn const_generics() {
|
||||
let _v = SmallVec::<[i32; 987]>::default();
|
||||
}
|
||||
|
||||
#[cfg(feature = "const_new")]
|
||||
#[test]
|
||||
fn const_new() {
|
||||
let v = const_new_inner();
|
||||
assert_eq!(v.capacity(), 4);
|
||||
assert_eq!(v.len(), 0);
|
||||
let v = const_new_inline_sized();
|
||||
assert_eq!(v.capacity(), 4);
|
||||
assert_eq!(v.len(), 4);
|
||||
assert_eq!(v[0], 1);
|
||||
let v = const_new_inline_args();
|
||||
assert_eq!(v.capacity(), 2);
|
||||
assert_eq!(v.len(), 2);
|
||||
assert_eq!(v[0], 1);
|
||||
assert_eq!(v[1], 4);
|
||||
}
|
||||
#[cfg(feature = "const_new")]
|
||||
const fn const_new_inner() -> SmallVec<[i32; 4]> {
|
||||
SmallVec::<[i32; 4]>::new_const()
|
||||
}
|
||||
#[cfg(feature = "const_new")]
|
||||
const fn const_new_inline_sized() -> SmallVec<[i32; 4]> {
|
||||
crate::smallvec_inline![1; 4]
|
||||
}
|
||||
#[cfg(feature = "const_new")]
|
||||
const fn const_new_inline_args() -> SmallVec<[i32; 2]> {
|
||||
crate::smallvec_inline![1, 4]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_macro() {
|
||||
let _v: SmallVec<[u8; 1]> = smallvec![];
|
||||
|
||||
Reference in New Issue
Block a user