diff --git a/Cargo.toml b/Cargo.toml index ea04113..1705f7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,15 @@ name = "arraystring" harness = false [features] -default = ["std"] +default = ["std", "u128", "floats"] +# enable stdlib std = [] +# enable i128, u128 specific impls +u128 = [] +# enable f32, f64 specific impls +floats = [] + [profile.bench] debug = true [profile.release] diff --git a/src/arrayvec.rs b/src/arrayvec.rs index e69e60c..37c8d10 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -760,6 +760,51 @@ impl From<[T; CAP]> for ArrayVec { } } +// Generic version of from_slice_const not possible at this time +macro_rules! impl_from_const { + ($($t:ty)+) => { +$( +impl ArrayVec<$t, CAP> { + /// Create a new `ArrayVec` from a slice, suitable for const context + /// + /// Capacity is inferred from the type parameter. + /// + /// **Panics** if the backing array is not large enough to fit the slice. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// const V: ArrayVec = ArrayVec::::from_slice_const(&[1, 2, 3]); + /// ``` + pub const fn from_slice_const(values: &[$t]) -> Self { + let len = values.len(); + if len > CAP { + panic!("ArrayVec::from_slice_const: insufficient capacity"); + } + + let mut vec = Self::new_const(); + let mut i = 0; + while i < len { + vec.xs[i] = MaybeUninit::new(values[i]); + i += 1; + } + + // Safety: we know len <= CAP and elements < len are initialized + vec.len = len as u32; + vec + } +} +)+ + + }; +} + +impl_from_const!(u8 u16 u32 u64 usize i8 i16 i32 i64 isize char); +#[cfg(feature = "floats")] +impl_from_const!(f32 f64); +#[cfg(feature = "u128")] +impl_from_const!(u128 i128); + /// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to /// fit. diff --git a/tests/tests.rs b/tests/tests.rs index 2f8a5ef..b1c5be3 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -773,6 +773,19 @@ fn test_arrayvec_const_constructible() { assert_eq!(var[..], [vec![3, 5, 8]]); } +#[test] +fn test_arrayvec_from_slice_const() { + const V: ArrayVec = ArrayVec::::from_slice_const(b"0123456789"); + + let mut var = V; + assert_eq!(&*var, b"0123456789"); + assert!(var.try_push(0).is_err()); + var.clear(); + var.push(1); + var.push(2); + assert_eq!(&*var, &[1, 2]); +} + #[test] fn test_arraystring_const_constructible() { const AS: ArrayString<10> = ArrayString::new_const(); @@ -784,10 +797,23 @@ fn test_arraystring_const_constructible() { assert_eq!(var, *"hello"); } +#[test] +fn test_arraystring_from_str_const() { + const AS: ArrayString<10> = ArrayString::from_str_const("0123456789"); + + let mut var = AS; + assert_eq!(&*var, "0123456789"); + assert!(var.try_push_str("1").is_err()); + + var.clear(); + var.push_str("9876543210"); + assert_eq!(&*var, "9876543210"); +} + #[test] fn test_arraystring_zero_filled_has_some_sanity_checks() { let string = ArrayString::<4>::zero_filled(); assert_eq!(string.as_str(), "\0\0\0\0"); assert_eq!(string.len(), 4); -} \ No newline at end of file +}