How do I convert a &str to a String in Rust?

This is the first in a whole series of blog posts to answer the simple
question "How do I X in Rust?" Many times as a user coming into the
Rust language there are growing pains and some things that seem
intuitive after using the language for a while aren't for a new user.
This is aimed at those new users, however even an experienced Rust user
might learn a new trick or two.

With that in mind let's jump right in!

What's the difference between &str and String?

Before we talk about conversion it'll help to know what
a &str and
a String are and why we'd want to convert from a &str to a String.
A &str is an immutable reference to a String. This means you can't change
the string at all or manipulate it in any way. However if you have
a String you have the option to do that as well as having some methods
that &str doesn't have to do text manipulation. You can look at the
methods available to the different data types that are linked above for
what you can do exactly with each type. Generally speaking:

  • You want &str if you don't want to change the string
  • You want String if you want to change the string or need ownership of
    the data

Sometimes you'll get a &str type from a method, but need a String. The
following methods we'll discuss will show you how to convert to a String
from an &str.

Thanks to @LeoUnglaub for suggesting to add this section

Converting a &str to a String

Surprisingly, there are quite a few ways to do this and depending on what
you're trying to do one of the methods laid out below will be more
appropriate.

to_string()

fn main() {
    let new_string = "Hello World!".to_string();
}

to_string() turns an &str into a String. Back before this pr in version
1.9
of the compiler this
was actually slower than the next method I'll be showing you. It went
through crazy amounts of machinery to turn it into a String whereas the
newer compiler version optimized this for &str -> String making it
equivalent to the next method speed wise. This machinery is all the code
that can parse the data type and turn it into a String. It should be
noted that this and the following methods are copying data under the
hood so that you can have ownership of the String. There is no speed
difference between to_string(), to_owned(), and String::from().

There was a question on the subreddit as to whether this means .to_owned() would be deprecated. /u/Roaneno answers it well here.

to_owned()

fn main() {
    let new_string = "Hello World!".to_owned();
}

Since the &str is an immutable reference to a String using to_owned()
turns it into a String you own and can do things with! This is now the
same as to_string(), but was the preferred way prior to 1.9 .to_owned()
is used for other data types to promote an immutable reference into a
data type you own.

String::from()

fn main() {
    let new_string = String::from("Hello World!");
}

When you are using to_string() in any compiler after 1.9 you're actually
using this method. to_string() ends up being syntactic sugar for it.
You hand an &str into the from method and from there it constructs
a String type for you to use.

String::push_str()

fn main() {
    let mut new_string = String::new(); //Create an empty string
    new_string.push_str("Hello");
    new_string.push_str(" World!");
    println!("{}", new_string); //Prints Hello World!
}

Since a String is a growable data type you can add to it by pushing &str
into it. While this is a bit verbose for the example I gave above you
could use it to concatenate a variety of &str into one String that you
can then manipulate to do other things.

format!()

fn main() {
    let world_var= "world";
    //Becomes "Hello World!"
    let new_string = format!("Hello {}!", world_var);
}

Thanks to /u/horsefactory for pointing out the typo that was here in a previous version

You can also use the format!() macro in order to do some more complex
formatting with &str as input. It's like println!() but instead of
outputting to stdout it instead returns a String. This is simpler to use
than .push_str() if you know what text you want in your string and don't
want lines of code just to set it up. Given the above example with
.push_str() it would be:

fn main() {
    let world_var = "world";
    let mut new_string = String::new();
    new_string.push_str("Hello ");
    new_string.push_str(world_var);
    new_string.push_str("!");
}

This is way more verbose than is needed. That's why a case like this is
more suited to format!() to have the code be more expressive and clean
looking. However, there is a cost. Remember that crazy machinery I was
talking about for .to_string()? That was using this under the hood and
as such was less efficient. Use this method with caution if speed is
a concern.

Tip courtesy of /u/MrJillHace

into()

fn main() {
    let new_string = "Hello world!".into();
}

This is a less well known way to do it, but since &str implements
Into it has this method available to it. Think of it as saying I'm
turning this into that. It's a trait for conversions which you can find
here in the docs if you want to read more about it. While it's a
little less clear as to what it's doing you have this method available
to you as well. It's not guaranteed to be fast according to the
definition of the trait, just that you are guaranteed the conversion
itself. String::from() implements the From trait which implements Into.
You're probably better off using that method rather than this, but
you're more than free to do so.

Tip courtesy of
@nj_snav_lin and /u/cramert

What's the idiomatic Rust way?

Most code you'll see will use .to_owned() or String::from() since that
was faster than .to_string(). Now though any of those 3 will be the most
common way to do conversions. This is one of those things that has so
many ways to do things that there's no one standard for the community.
I personally think .to_string() or String::from() are good choices since
they emphasize what they're doing more so than .to_owned() or any of the
other methods. Others might disagree, but at the end of the day it's
your code so choose the method that's best suited for what you're doing.

We have to go back Marty!

Sometimes you'll need to go back from a String to &str. All you'll have
to do is:

fn main() {
    let my_string = String::from("Hello World!");
    let my_immutable_string = &my_string; //This is a &String type
    let my_str: &str = &my_string; //This is an &str type
}

&String can be used anywhere there is a need for &str. It automatically
turns into it if the method calls for it.

Simple enough right? If you want to know why you can read about auto deref here.

Thanks to @k0pernicus for suggesting to add this to the post

Conclusion

Above are the various ways you can make a String from a &str and each
serves a different purpose:

  • .to_string() if you want a simple conversion and show you're making
    a String
  • .to_owned() if you want a simple conversion and to show you're taking
    ownership of it.
  • String::from() a more explicit way to say what you're doing
  • String::push_str() if you need to append to a String
  • format!() if you have predefined text that you wanted formatted in
    a specific way and don't care about the speed cost
  • .into() if you want a simple conversion and don't care about the
    ambiguity of it

You can also easily go from a String to a &str:

  • &String types turn into &str if the method call needs it
  • let my_str: &str = &my_string; if you want to explicitly specify
    a &str type

If you have a burning question that you want answered but just can't
seem to find the answer you need, shoot me an email at
mgattozzi@gmail.com and I'll write a post to answer your question! No
question is stupid. Chances are if you're having trouble with it so is
someone else so ask away!

If you're a more experienced Rust user and want to help with the wording
or give suggestions send me a PR or reach out to me and I'll include
changes if they're good. You'll also get credit for your
contributions of course!