String

String is a growable UTF-8 encoded string:

1. ```
   fn main() {
   ```
2. ```
       let mut s1 = String::new();
   ```
3. ```
       s1.push_str("Hello");
   ```
4. ```
       println!("s1: len = {}, capacity = {}", s1.len(), s1.capacity());
   ```

6. ```
       let mut s2 = String::with_capacity(s1.len() + 1);
   ```
7. ```
       s2.push_str(&s1);
   ```
8. ```
       s2.push('!');
   ```
9. ```
       println!("s2: len = {}, capacity = {}", s2.len(), s2.capacity());
   ```

11. ```
        let s3 = String::from("🇨🇭");
    ```
12. ```
        println!("s3: len = {}, number of chars = {}", s3.len(), s3.chars().count());
    ```
13. ```
    }
    ```

String implements Deref, which means that you can call all str methods on a String.

This slide should take about 5 minutes.

  • String::new returns a new empty string, use String::with_capacity when you know how much data you want to push to the string.
  • String::len returns the size of the String in bytes (which can be different from its length in characters).
  • String::chars returns an iterator over the actual characters. Note that a char can be different from what a human will consider a “character” due to grapheme clusters.
  • When people refer to strings they could either be talking about &str or String.
  • When a type implements Deref<Target = T>, the compiler will let you transparently call methods from T.
  • We haven’t discussed the Deref trait yet, so at this point this mostly explains the structure of the sidebar in the documentation.
  • String implements Deref<Target = str> which transparently gives it access to str‘s methods.
  • Write and compare let s3 = s1.deref(); and let s3 = &*s1;.
  • String is implemented as a wrapper around a vector of bytes, many of the operations you see supported on vectors are also supported on String, but with some extra guarantees.
  • Compare the different ways to index a String:
  • To a character by using s3.chars().nth(i).unwrap() where i is in-bound, out-of-bounds.
  • To a substring by using s3[0..4], where that slice is on character boundaries or not.
  • Many types can be converted to a string with the to_string method. This trait is automatically implemented for all types that implement Display, so anything that can be formatted can also be converted to a string.