-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
% The Strings Guide | ||
|
||
# Strings | ||
|
||
Strings are an important concept to master in any programming language. If you | ||
come from a managed language background, you may be surprised at the complexity | ||
of string handling in a systems programming language. Efficient access and | ||
allocation of memory for a dynamically sized structure involves a lot of | ||
details. Luckily, Rust has lots of tools to help us here. | ||
|
||
A **string** is a sequence of unicode scalar values encoded as a stream of | ||
UTF-8 bytes. All strings are guaranteed to be validly-encoded UTF-8 sequences. | ||
Additionally, strings are not null-terminated and can contain null bytes. | ||
|
||
Rust has two main types of strings: `&str` and `String`. | ||
|
||
## &str | ||
|
||
The first kind is a `&str`. This is pronounced a 'string slice.' String literals | ||
This comment has been minimized.
Sorry, something went wrong. |
||
are of the type `&str`: | ||
|
||
```{rust} | ||
let string = "Hello there."; | ||
``` | ||
|
||
Like any Rust type, string slices have an associated lifetime. A string literal | ||
is a `&'static str`. A string slice can be written without an explicit | ||
lifetime in many cases, such as in function arguments. In these cases the | ||
lifetime will be inferred: | ||
|
||
```{rust} | ||
fn takes_slice(slice: &str) { | ||
println!("Got: {}", slice); | ||
} | ||
``` | ||
|
||
Like vector slices, string slices are simply a pointer plus a length. This | ||
means that they're a 'view' into an already-allocated string, such as a | ||
`&'static str` or a `String`. | ||
|
||
## String | ||
|
||
A `String` is a heap-allocated string. This string is growable, and is also | ||
guaranteed to be UTF-8. | ||
|
||
```{rust} | ||
let mut s = "Hello".to_string(); | ||
println!("{}", s); | ||
s.push_str(", world."); | ||
println!("{}", s); | ||
``` | ||
|
||
You can coerce a `String` into a `&str` with the `as_slice()` method: | ||
|
||
```{rust} | ||
fn takes_slice(slice: &str) { | ||
println!("Got: {}", slice); | ||
} | ||
fn main() { | ||
let s = "Hello".to_string(); | ||
takes_slice(s.as_slice()); | ||
} | ||
``` | ||
|
||
You can also get a `&str` from a stack-allocated array of bytes: | ||
|
||
```{rust} | ||
use std::str; | ||
let x: &[u8] = &[b'a', b'b']; | ||
let stack_str: &str = str::from_utf8(x).unwrap(); | ||
``` | ||
|
||
## Best Practices | ||
|
||
### `String` vs. `&str` | ||
|
||
In general, you should prefer `String` when you need ownership, and `&str` when | ||
you just need to borrow a string. This is very similar to using `Vec<T>` vs. `&[T]`, | ||
and `T` vs `&T` in general. | ||
|
||
This means starting off with this: | ||
|
||
```{rust,ignore} | ||
fn foo(s: &str) { | ||
``` | ||
|
||
and only moving to this: | ||
|
||
```{rust,ignore} | ||
fn foo(s: String) { | ||
``` | ||
|
||
If you have good reason. It's not polite to hold on to ownership you don't | ||
need, and it can make your lifetimes more complex. Furthermore, you can pass | ||
either kind of string into `foo` by using `.as_slice()` on any `String` you | ||
need to pass in, so the `&str` version is more flexible. | ||
This comment has been minimized.
Sorry, something went wrong.
cburgdorf
Contributor
|
||
|
||
### Comparisons | ||
|
||
To compare a String to a constant string, prefer `as_slice()`... | ||
|
||
```{rust} | ||
fn compare(string: String) { | ||
if string.as_slice() == "Hello" { | ||
println!("yes"); | ||
} | ||
} | ||
``` | ||
|
||
... over `to_string()`: | ||
|
||
```{rust} | ||
fn compare(string: String) { | ||
if string == "Hello".to_string() { | ||
println!("yes"); | ||
} | ||
} | ||
``` | ||
|
||
Converting a `String` to a `&str` is cheap, but converting the `&str` to a | ||
`String` involves an allocation. | ||
This comment has been minimized.
Sorry, something went wrong.
cburgdorf
Contributor
|
||
|
||
## Other Documentation | ||
|
||
* [the `&str` API documentation](/std/str/index.html) | ||
* [the `String` API documentation](std/string/index.html) |
5 comments
on commit 226b7d1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
saw approval from kballard
at steveklabnik@226b7d1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merging steveklabnik/rust/string_guide = 226b7d1 into auto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all tests pass:
success: http://buildbot.rust-lang.org/builders/auto-mac-32-opt/builds/382
success: http://buildbot.rust-lang.org/builders/auto-mac-64-opt/builds/383
success: http://buildbot.rust-lang.org/builders/auto-mac-64-nopt-c/builds/382
success: http://buildbot.rust-lang.org/builders/auto-mac-64-nopt-t/builds/383
success: http://buildbot.rust-lang.org/builders/auto-linux-32-opt/builds/385
success: http://buildbot.rust-lang.org/builders/auto-linux-32-nopt-c/builds/386
success: http://buildbot.rust-lang.org/builders/auto-linux-32-nopt-t/builds/385
success: http://buildbot.rust-lang.org/builders/auto-linux-64-opt/builds/391
success: http://buildbot.rust-lang.org/builders/auto-linux-64-nopt-c/builds/386
success: http://buildbot.rust-lang.org/builders/auto-linux-64-nopt-t/builds/385
success: http://buildbot.rust-lang.org/builders/auto-linux-64-x-android-t/builds/388
success: http://buildbot.rust-lang.org/builders/auto-win-32-opt/builds/386
success: http://buildbot.rust-lang.org/builders/auto-win-32-nopt-t/builds/386
success: http://buildbot.rust-lang.org/builders/auto-win-32-nopt-c/builds/387
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fast-forwarding master to auto = cebed8a
Currently it reads to me:
There is A and B. The first is A.
which bears some obviousness/redundancy. Does that make sense?Maybe make it
The first kind &str is pronounced a 'string slice.
?