From 1943bfc8835d98cd202b78ef7f7c3316fde0eb64 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sun, 7 Nov 2021 11:49:38 +0100 Subject: [PATCH 1/2] Add from_str_const constructor for ArrayString --- src/array_string.rs | 37 ++++++++++++++++++++++++++++++++++++- src/lib.rs | 8 ++++++++ tests/tests.rs | 13 +++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/array_string.rs b/src/array_string.rs index 227e01db..4d360c40 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -21,7 +21,6 @@ use crate::utils::MakeMaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; - /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track @@ -111,6 +110,42 @@ impl ArrayString Ok(arraystr) } + /// Create a new `ArrayString` from a `str`, suitable for const context + /// + /// Capacity is inferred from the type parameter. + /// + /// **Panics** or causes a **const error** if the backing array is not large enough to fit the + /// string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// const S: ArrayString<3> = ArrayString::from_str_const(""); + /// ``` + /// + /// A compile-time error will occur - in constants - if the input is too long: + /// + /// ```compile_fail + /// # use arrayvec::ArrayString; + /// const S1: ArrayString<3> = ArrayString::from_str_const("too long for the capacity"); + /// ``` + pub const fn from_str_const(s: &str) -> Self { + let bytes = s.as_bytes(); + let len = bytes.len(); + assert_length_lt_capacity_const!(len, CAP); + + let mut vec = Self::new_const(); + let mut i = 0; + while i < len { + vec.xs[i] = MaybeUninit::new(bytes[i]); + i += 1; + } + + // Safety: we know len <= CAP and elements < len are initialized + vec.len = len as u32; + vec + } + /// Create a new `ArrayString` from a byte string literal. /// /// **Errors** if the byte string literal is not valid UTF-8. diff --git a/src/lib.rs b/src/lib.rs index 5c4bcee0..80d26654 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,14 @@ macro_rules! assert_capacity_limit_const { } } +macro_rules! assert_length_lt_capacity_const { + ($len:expr, $cap:expr) => { + if $len > 0 { + let _len_check = [(); $cap /*ArrayVec/ArrayString: insufficient capacity */][$len - 1]; + } + } +} + mod arrayvec_impl; mod arrayvec; mod array_string; diff --git a/tests/tests.rs b/tests/tests.rs index 309ceb8b..4835b5b5 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -814,6 +814,19 @@ 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() { From 0082edac907492ad66b26a1634b41a37a3541d18 Mon Sep 17 00:00:00 2001 From: Ad1n0d1n Date: Mon, 5 Oct 2026 12:07:07 +0400 Subject: [PATCH 2/2] array_string: use LenUint instead of hardcoded u32 in from_str_const Co-authored-by: Cursor --- src/array_string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/array_string.rs b/src/array_string.rs index 4d360c40..4a24b2d1 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -142,7 +142,7 @@ impl ArrayString } // Safety: we know len <= CAP and elements < len are initialized - vec.len = len as u32; + vec.len = len as LenUint; vec }