Given a fixed-length char
array such as:
let s: [char; 5] = ['h', 'e', 'l', 'l', 'o'];
How do I obtain a &str
?
Given a fixed-length char
array such as:
let s: [char; 5] = ['h', 'e', 'l', 'l', 'o'];
How do I obtain a &str
?
You can't without some allocation, which means you will end up with a String
.
let s2: String = s.iter().collect();
The problem is that strings in Rust are not collections of char
s, they are UTF-8, which is an encoding without a fixed size per character.
For example, the array in this case would take 5 x 32-bits for a total of 20 bytes. The data of the string would take 5 bytes total (although there's also 3 pointer-sized values, so the overall String
takes more memory in this case).
We start with the array and call []::iter
, which yields values of type &char
. We then use Iterator::collect
to convert the Iterator<Item = &char>
into a String
. This uses the iterator's size_hint
to pre-allocate space in the String
, reducing the need for extra allocations.
vec!
macro for String
? –
Confirmation String::from("foo")
or maybe "foo".to_string()
? In some contexts you can also use "foo".into()
. You don't really need a macro for anything; those are just function calls. I suppose you could create a method s
that calls one of them if they are too long... –
Modiste str!['h', 'e', 'y']
. –
Confirmation "hey"
? –
Modiste [c1, c2, c3]
. –
Confirmation Another quick one-liner I didn't see above:
let whatever_char_array = ['h', 'e', 'l', 'l', 'o'];
let string_from_char_array = String::from_iter(whatever_char_array);
Note:
This feature (iterating over an array
) was introduced recently. I tried looking for the exact rustc version, but could not...
std::array::IntoIter
was introduced in 1.51 while the impl<T, const N: usize> IntoIterator for [T; N]
was introduced in 1.53 –
Pontiff String::from_iter(&chars)
. But FromIterator
was only introduced to the prelude in 2021. –
Concentric Strings in rust are not stored as a sequence of char
values, they are stored as UTF-8.
So to convert an array of "chars" to an &str (string slice) you must copy the data. One option, as mentioned in the other answers, is to use a String, but that implies heap allocation you might want to avoid.
If you want to avoid heap allocation, an alternative approach is to use a fixed-size array as the result buffer. Each char takes up a maximum of 4 bytes in UTF-8, so we can size the array such that it will not overflow with any combination of characters.
let mut buf = [0u8; 20];
let mut p = 0;
for c in s {
p += c.encode_utf8(&mut buf[p..]).len();
}
let result = unsafe { std::str::from_utf8_unchecked(&buf[..p]) };
ArrayString
. –
Concentric © 2022 - 2024 — McMap. All rights reserved.
: [char; 5]
is redundant; the type can be inferred. – Modiste"hello"
is 1000% easier and more useful. – Nester[c1, c2, c3]
. – Confirmation