In Rust there's two kinds of strings: str
and String
. The former is a really lean construct and is passed around as a reference, like &str
. These cannot be modified.1 They also can't be copied, they're references, so they will always refer to the same value.
The reason they exist is because they are the "minimum viable string", they are the cheapest possible representation of textual data. This efficiency does have trade-offs.
A String
can be modified if it's mut
, and can also be copied, and later altered again. This makes them more suitable for properties that can and will change, or need to be computed at runtime.
Learning the difference here can be a bit bewildering if you're used to Python where strings are strings, but once you get a handle on it, you'll realize what's going on here.
"x"
is a &str
value, while String::from("x")
is a String
converted from that value. You can also do "x".into()
if the type is well understood by the compiler, such as for a function argument or struct property.
Strings are also such a common thing that there's to_string()
and to_owned()
, both of which effectively do the same thing here on &str
values.
If you want the best of both of these features, you can use Cow<str>
which can encapsulate either an &str
value, or a String
, and you can convert from the "borrowed" value (&str
) to an "owned" value via the to_owned()
function.
These are more exotic, though, so I'd recommend only using them when you know what you're doing and need the performance gains they can offer.
--
1 Treat these like const char*
in C++, versus std::string
. The former is compiled into non-modifiable data in the executable, while the other uses a buffer that can be dynamically allocated.