Skip to content

Commit 024d213

Browse files
committed
Add from_str_const constructor for ArrayString
1 parent 67ec907 commit 024d213

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

src/array_string.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::utils::MakeMaybeUninit;
1919
#[cfg(feature="serde")]
2020
use serde::{Serialize, Deserialize, Serializer, Deserializer};
2121

22-
2322
/// A string with a fixed capacity.
2423
///
2524
/// The `ArrayString` is a string backed by a fixed size array. It keeps track
@@ -108,6 +107,42 @@ impl<const CAP: usize> ArrayString<CAP>
108107
Ok(arraystr)
109108
}
110109

110+
/// Create a new `ArrayString` from a `str`, suitable for const context
111+
///
112+
/// Capacity is inferred from the type parameter.
113+
///
114+
/// **Panics** or causes a **const error** if the backing array is not large enough to fit the
115+
/// string.
116+
///
117+
/// ```
118+
/// use arrayvec::ArrayString;
119+
///
120+
/// const S: ArrayString<3> = ArrayString::from_str_const("");
121+
/// ```
122+
///
123+
/// A compile-time error will occur - in constants - if the input is too long:
124+
///
125+
/// ```compile_fail
126+
/// # use arrayvec::ArrayString;
127+
/// const S1: ArrayString<3> = ArrayString::from_str_const("too long for the capacity");
128+
/// ```
129+
pub const fn from_str_const(s: &str) -> Self {
130+
let bytes = s.as_bytes();
131+
let len = bytes.len();
132+
assert_length_lt_capacity_const!(len, CAP);
133+
134+
let mut vec = Self::new_const();
135+
let mut i = 0;
136+
while i < len {
137+
vec.xs[i] = MaybeUninit::new(bytes[i]);
138+
i += 1;
139+
}
140+
141+
// Safety: we know len <= CAP and elements < len are initialized
142+
vec.len = len as u32;
143+
vec
144+
}
145+
111146
/// Create a new `ArrayString` from a byte string literal.
112147
///
113148
/// **Errors** if the byte string literal is not valid UTF-8.

src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ macro_rules! assert_capacity_limit_const {
4646
}
4747
}
4848

49+
macro_rules! assert_length_lt_capacity_const {
50+
($len:expr, $cap:expr) => {
51+
if $len > 0 {
52+
let _len_check = [(); $cap /*ArrayVec/ArrayString: insufficient capacity */][$len - 1];
53+
}
54+
}
55+
}
56+
4957
mod arrayvec_impl;
5058
mod arrayvec;
5159
mod array_string;

tests/tests.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -784,10 +784,23 @@ fn test_arraystring_const_constructible() {
784784
assert_eq!(var, *"hello");
785785
}
786786

787+
#[test]
788+
fn test_arraystring_from_str_const() {
789+
const AS: ArrayString<10> = ArrayString::from_str_const("0123456789");
790+
791+
let mut var = AS;
792+
assert_eq!(&*var, "0123456789");
793+
assert!(var.try_push_str("1").is_err());
794+
795+
var.clear();
796+
var.push_str("9876543210");
797+
assert_eq!(&*var, "9876543210");
798+
}
799+
787800

788801
#[test]
789802
fn test_arraystring_zero_filled_has_some_sanity_checks() {
790803
let string = ArrayString::<4>::zero_filled();
791804
assert_eq!(string.as_str(), "\0\0\0\0");
792805
assert_eq!(string.len(), 4);
793-
}
806+
}

0 commit comments

Comments
 (0)