Finnamon
Finnamon

Reputation: 11

Rust convert a Vec<&str> to a single &str

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

Answers (1)

kmdreko
kmdreko

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

Related Questions