Skip to content

Commit d2ab6da

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 1d1adae commit d2ab6da

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
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

+45
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,51 @@ 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** if the backing array is not large enough to fit the slice.
773+
///
774+
/// ```
775+
/// use arrayvec::ArrayVec;
776+
///
777+
/// const V: ArrayVec<u8, 3> = ArrayVec::<u8, 3>::from_slice_const(&[1, 2, 3]);
778+
/// ```
779+
pub const fn from_slice_const(values: &[$t]) -> Self {
780+
let len = values.len();
781+
if len > CAP {
782+
panic!("ArrayVec::from_slice_const: insufficient capacity");
783+
}
784+
785+
let mut vec = Self::new_const();
786+
let mut i = 0;
787+
while i < len {
788+
vec.xs[i] = MaybeUninit::new(values[i]);
789+
i += 1;
790+
}
791+
792+
// Safety: we know len <= CAP and elements < len are initialized
793+
vec.len = len as u32;
794+
vec
795+
}
796+
}
797+
)+
798+
799+
};
800+
}
801+
802+
impl_from_const!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize char);
803+
#[cfg(feature = "floats")]
804+
impl_from_const!(f32 f64);
805+
#[cfg(feature = "u128")]
806+
impl_from_const!(u128 i128);
807+
763808

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

tests/tests.rs

+27-1
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();
@@ -784,10 +797,23 @@ fn test_arraystring_const_constructible() {
784797
assert_eq!(var, *"hello");
785798
}
786799

800+
#[test]
801+
fn test_arraystring_from_str_const() {
802+
const AS: ArrayString<10> = ArrayString::from_str_const("0123456789");
803+
804+
let mut var = AS;
805+
assert_eq!(&*var, "0123456789");
806+
assert!(var.try_push_str("1").is_err());
807+
808+
var.clear();
809+
var.push_str("9876543210");
810+
assert_eq!(&*var, "9876543210");
811+
}
812+
787813

788814
#[test]
789815
fn test_arraystring_zero_filled_has_some_sanity_checks() {
790816
let string = ArrayString::<4>::zero_filled();
791817
assert_eq!(string.as_str(), "\0\0\0\0");
792818
assert_eq!(string.len(), 4);
793-
}
819+
}

0 commit comments

Comments
 (0)