48
48
//! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed
49
49
//! list of sizes.
50
50
//!
51
+ //! ### `const_new`
52
+ //!
53
+ //! **This feature requires Rust 1.51.**
54
+ //!
55
+ //! 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.
56
+ //! For details, see the
57
+ //! [Rust Reference](https://doc.rust-lang.org/reference/const_eval.html#const-functions).
58
+ //!
51
59
//! ### `specialization`
52
60
//!
53
61
//! **This feature is unstable and requires a nightly build of the Rust toolchain.**
69
77
//! Tracking issue: [rust-lang/rust#34761](https://github.com/rust-lang/rust/issues/34761)
70
78
71
79
#![ no_std]
80
+ #![ cfg_attr( docsrs, feature( doc_cfg) ) ]
72
81
#![ cfg_attr( feature = "specialization" , allow( incomplete_features) ) ]
73
82
#![ cfg_attr( feature = "specialization" , feature( specialization) ) ]
74
83
#![ cfg_attr( feature = "may_dangle" , feature( dropck_eyepatch) ) ]
@@ -170,6 +179,52 @@ macro_rules! smallvec {
170
179
} ) ;
171
180
}
172
181
182
+ /// Creates an inline [`SmallVec`] containing the arguments. This macro is enabled by the feature `const_new`.
183
+ ///
184
+ /// `smallvec_inline!` allows `SmallVec`s to be defined with the same syntax as array expressions in `const` contexts.
185
+ /// The inline storage `A` will always be an array of the size specified by the arguments.
186
+ /// There are two forms of this macro:
187
+ ///
188
+ /// - Create a [`SmallVec`] containing a given list of elements:
189
+ ///
190
+ /// ```
191
+ /// # #[macro_use] extern crate smallvec;
192
+ /// # use smallvec::SmallVec;
193
+ /// # fn main() {
194
+ /// const V: SmallVec<[i32; 3]> = smallvec_inline![1, 2, 3];
195
+ /// assert_eq!(V[0], 1);
196
+ /// assert_eq!(V[1], 2);
197
+ /// assert_eq!(V[2], 3);
198
+ /// # }
199
+ /// ```
200
+ ///
201
+ /// - Create a [`SmallVec`] from a given element and size:
202
+ ///
203
+ /// ```
204
+ /// # #[macro_use] extern crate smallvec;
205
+ /// # use smallvec::SmallVec;
206
+ /// # fn main() {
207
+ /// const V: SmallVec<[i32; 3]> = smallvec_inline![1; 3];
208
+ /// assert_eq!(V, SmallVec::from_buf([1, 1, 1]));
209
+ /// # }
210
+ /// ```
211
+ ///
212
+ /// Note that the behavior mimics that of array expressions, in contrast to [`smallvec`].
213
+ #[ cfg( feature = "const_new" ) ]
214
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_new" ) ) ) ]
215
+ #[ macro_export]
216
+ macro_rules! smallvec_inline {
217
+ // count helper: transform any expression into 1
218
+ ( @one $x: expr) => ( 1usize ) ;
219
+ ( $elem: expr; $n: expr) => ( {
220
+ $crate:: SmallVec :: <[ _; $n] >:: from_const( [ $elem; $n] )
221
+ } ) ;
222
+ ( $( $x: expr) ,+ $( , ) ?) => ( {
223
+ const N : usize = 0usize $( + $crate:: smallvec_inline!( @one $x) ) * ;
224
+ $crate:: SmallVec :: <[ _; N ] >:: from_const( [ $( $x, ) * ] )
225
+ } ) ;
226
+ }
227
+
173
228
/// `panic!()` in debug builds, optimization hint in release.
174
229
#[ cfg( not( feature = "union" ) ) ]
175
230
macro_rules! debug_unreachable {
@@ -353,6 +408,17 @@ union SmallVecData<A: Array> {
353
408
heap : ( * mut A :: Item , usize ) ,
354
409
}
355
410
411
+ #[ cfg( all( feature = "union" , feature = "const_new" ) ) ]
412
+ impl < T , const N : usize > SmallVecData < [ T ; N ] > {
413
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_new" ) ) ) ]
414
+ #[ inline]
415
+ const fn from_const ( inline : MaybeUninit < [ T ; N ] > ) -> Self {
416
+ SmallVecData {
417
+ inline : core:: mem:: ManuallyDrop :: new ( inline) ,
418
+ }
419
+ }
420
+ }
421
+
356
422
#[ cfg( feature = "union" ) ]
357
423
impl < A : Array > SmallVecData < A > {
358
424
#[ inline]
@@ -393,6 +459,15 @@ enum SmallVecData<A: Array> {
393
459
Heap ( ( * mut A :: Item , usize ) ) ,
394
460
}
395
461
462
+ #[ cfg( all( not( feature = "union" ) , feature = "const_new" ) ) ]
463
+ impl < T , const N : usize > SmallVecData < [ T ; N ] > {
464
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_new" ) ) ) ]
465
+ #[ inline]
466
+ const fn from_const ( inline : MaybeUninit < [ T ; N ] > ) -> Self {
467
+ SmallVecData :: Inline ( inline)
468
+ }
469
+ }
470
+
396
471
#[ cfg( not( feature = "union" ) ) ]
397
472
impl < A : Array > SmallVecData < A > {
398
473
#[ inline]
@@ -1487,6 +1562,7 @@ impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> {
1487
1562
}
1488
1563
1489
1564
#[ cfg( feature = "write" ) ]
1565
+ #[ cfg_attr( docsrs, doc( cfg( feature = "write" ) ) ) ]
1490
1566
impl < A : Array < Item = u8 > > io:: Write for SmallVec < A > {
1491
1567
#[ inline]
1492
1568
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
@@ -1507,6 +1583,7 @@ impl<A: Array<Item = u8>> io::Write for SmallVec<A> {
1507
1583
}
1508
1584
1509
1585
#[ cfg( feature = "serde" ) ]
1586
+ #[ cfg_attr( docsrs, doc( cfg( feature = "serde" ) ) ) ]
1510
1587
impl < A : Array > Serialize for SmallVec < A >
1511
1588
where
1512
1589
A :: Item : Serialize ,
@@ -1521,6 +1598,7 @@ where
1521
1598
}
1522
1599
1523
1600
#[ cfg( feature = "serde" ) ]
1601
+ #[ cfg_attr( docsrs, doc( cfg( feature = "serde" ) ) ) ]
1524
1602
impl < ' de , A : Array > Deserialize < ' de > for SmallVec < A >
1525
1603
where
1526
1604
A :: Item : Deserialize < ' de > ,
@@ -1950,15 +2028,43 @@ impl<'a> Drop for SetLenOnDrop<'a> {
1950
2028
}
1951
2029
}
1952
2030
1953
- #[ cfg( feature = "const_generics" ) ]
2031
+ #[ cfg( feature = "const_new" ) ]
2032
+ impl < T , const N : usize > SmallVec < [ T ; N ] > {
2033
+ /// Construct an empty vector.
2034
+ ///
2035
+ /// 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.
2036
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_new" ) ) ) ]
2037
+ #[ inline]
2038
+ pub const fn new_const ( ) -> Self {
2039
+ SmallVec {
2040
+ capacity : 0 ,
2041
+ data : SmallVecData :: from_const ( MaybeUninit :: uninit ( ) ) ,
2042
+ }
2043
+ }
2044
+
2045
+ /// The array passed as an argument is moved to be an inline version of `SmallVec`.
2046
+ ///
2047
+ /// 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.
2048
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_new" ) ) ) ]
2049
+ #[ inline]
2050
+ pub const fn from_const ( items : [ T ; N ] ) -> Self {
2051
+ SmallVec {
2052
+ capacity : N ,
2053
+ data : SmallVecData :: from_const ( MaybeUninit :: new ( items) ) ,
2054
+ }
2055
+ }
2056
+ }
2057
+
2058
+ #[ cfg( all( feature = "const_generics" , not( doc) ) ) ]
2059
+ #[ cfg_attr( docsrs, doc( cfg( feature = "const_generics" ) ) ) ]
1954
2060
unsafe impl < T , const N : usize > Array for [ T ; N ] {
1955
2061
type Item = T ;
1956
2062
fn size ( ) -> usize {
1957
2063
N
1958
2064
}
1959
2065
}
1960
2066
1961
- #[ cfg( not( feature = "const_generics" ) ) ]
2067
+ #[ cfg( any ( not( feature = "const_generics" ) , doc ) ) ]
1962
2068
macro_rules! impl_array(
1963
2069
( $( $size: expr) ,+) => {
1964
2070
$(
@@ -1970,7 +2076,7 @@ macro_rules! impl_array(
1970
2076
}
1971
2077
) ;
1972
2078
1973
- #[ cfg( not( feature = "const_generics" ) ) ]
2079
+ #[ cfg( any ( not( feature = "const_generics" ) , doc ) ) ]
1974
2080
impl_array ! (
1975
2081
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 ,
1976
2082
26 , 27 , 28 , 29 , 30 , 31 , 32 , 36 , 0x40 , 0x60 , 0x80 , 0x100 , 0x200 , 0x400 , 0x600 , 0x800 , 0x1000 ,
0 commit comments