Skip to content

Commit 5e2eea0

Browse files
committed
Add from_slice_const constructor for ArrayVec
We can't make these generic, not even where T: Copy, so they are just templated out with macros for the integer types, quite limited.
1 parent 024d213 commit 5e2eea0

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ name = "arraystring"
3535
harness = false
3636

3737
[features]
38-
default = ["std"]
38+
default = ["std", "u128", "floats"]
39+
# enable stdlib
3940
std = []
4041

42+
# enable i128, u128 specific impls
43+
u128 = []
44+
# enable f32, f64 specific impls
45+
floats = []
46+
4147
[profile.bench]
4248
debug = true
4349
[profile.release]

src/arrayvec.rs

+51
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,57 @@ impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
760760
}
761761
}
762762

763+
// Generic version of from_slice_const not possible at this time
764+
macro_rules! impl_from_const {
765+
($($t:ty)+) => {
766+
$(
767+
impl<const CAP: usize> ArrayVec<$t, CAP> {
768+
/// Create a new `ArrayVec` from a slice, suitable for const context
769+
///
770+
/// Capacity is inferred from the type parameter.
771+
///
772+
/// **Panics** or causes a **const error** if the backing array is not large enough to fit the
773+
/// slice.
774+
///
775+
/// ```
776+
/// use arrayvec::ArrayVec;
777+
///
778+
/// const V: ArrayVec<u8, 3> = ArrayVec::<u8, 3>::from_slice_const(&[1, 2, 3]);
779+
/// ```
780+
///
781+
/// A compile-time error will occur - in constants - if the input is too long:
782+
///
783+
/// ```compile_fail
784+
/// # use arrayvec::ArrayVec;
785+
/// const S1: ArrayVec<u8, 3> = ArrayVec::<u8, 3>::from_slice_const(&[1, 2, 3, 4]);
786+
/// ```
787+
pub const fn from_slice_const(values: &[$t]) -> Self {
788+
let len = values.len();
789+
assert_length_lt_capacity_const!(len, CAP);
790+
791+
let mut vec = Self::new_const();
792+
let mut i = 0;
793+
while i < len {
794+
vec.xs[i] = MaybeUninit::new(values[i]);
795+
i += 1;
796+
}
797+
798+
// Safety: we know len <= CAP and elements < len are initialized
799+
vec.len = len as u32;
800+
vec
801+
}
802+
}
803+
)+
804+
805+
};
806+
}
807+
808+
impl_from_const!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize char);
809+
#[cfg(feature = "floats")]
810+
impl_from_const!(f32 f64);
811+
#[cfg(feature = "u128")]
812+
impl_from_const!(u128 i128);
813+
763814

764815
/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to
765816
/// fit.

tests/tests.rs

+13
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,19 @@ fn test_arrayvec_const_constructible() {
773773
assert_eq!(var[..], [vec![3, 5, 8]]);
774774
}
775775

776+
#[test]
777+
fn test_arrayvec_from_slice_const() {
778+
const V: ArrayVec<u8, 10> = ArrayVec::<u8, 10>::from_slice_const(b"0123456789");
779+
780+
let mut var = V;
781+
assert_eq!(&*var, b"0123456789");
782+
assert!(var.try_push(0).is_err());
783+
var.clear();
784+
var.push(1);
785+
var.push(2);
786+
assert_eq!(&*var, &[1, 2]);
787+
}
788+
776789
#[test]
777790
fn test_arraystring_const_constructible() {
778791
const AS: ArrayString<10> = ArrayString::new_const();

0 commit comments

Comments
 (0)