Reputation: 11
edit: I'm really dumb, I forgot that vectors need constant sized elements :)
I want to convert a Vec<&str>
to a single &str
.
As an example I want {"a","bc"} -> "abc"
I know you can use the join("")
method to accomplish this, but because the memory is already laid out correctly this feels redundant. I wanted to do this a different way.
I wrote a function to do this, but it uses unsafe
. Is there a better/cleaner way to do this?
fn vec_to_str(input: Vec<&str>) -> Option<&str> {
let last_elem = input.last()?;
unsafe {
let last = last_elem.as_bytes().as_ptr().add(last_elem.len());
let first = input.first()?.as_bytes().as_ptr();
let len = last.offset_from(first);
Some(str::from_utf8_unchecked(from_raw_parts(first, len.try_into().unwrap())))
}
}
Upvotes: 0
Views: 100
Reputation: 59862
You cannot get a combined &str
from an arbitrary Vec<&str>
without creating a separate allocation. You are correct that Vec
stores its elements contiguously, but those elements are &str
which are references. The references are stored contiguously, but that means nothing in regard to how the referenced data is organized. The memory structure of input
would look akin to this:
+----------+ +----------+ +----------+
| ptr |----->| [0].ptr |----->| "a" |
+----------+ +----------+ +----------+
| size | | [0].size |
+----------+ +----------+ +----------+
| capacity | | [1].ptr |----->| "bc" |
+----------+ +----------+ +----------+
| [1].size |
+----------+
So you should simply create a new String
using .join("")
.
Upvotes: 4