The Rust Programming Language › Paths for Referring to an Item in the Module Tree › Starting Relative Paths with `super`

We can construct relative paths that begin in the parent module, rather than
the current module or the crate root, by using `super` at the start of the
path. This is like starting a filesystem path with the `..` syntax that means
to go to the parent directory. Using `super` allows us to reference an item
that we know is in the parent module, which can make rearranging the module
tree easier when the module is closely related to the parent but the parent
might be moved elsewhere in the module tree someday.
Consider the code in Listing 7-8 that models the situation in which a chef
fixes an incorrect order and personally brings it out to the customer. The
function `fix_incorrect_order` defined in the `back_of_house` module calls the
function `deliver_order` defined in the parent module by specifying the path to
`deliver_order`, starting with `super`.
Listing 7-8: Calling a function using a relative path starting with `super` (src/lib.rs)
```rust,noplayground,test_harness
fn deliver_order() {}

mod back_of_house {
    fn fix_incorrect_order() {
        cook_order();
        super::deliver_order();
    }

    fn cook_order() {}
}
```
The `fix_incorrect_order` function is in the `back_of_house` module, so we can
use `super` to go to the parent module of `back_of_house`, which in this case
is `crate`, the root. From there, we look for `deliver_order` and find it.
Success! We think the `back_of_house` module and the `deliver_order` function
are likely to stay in the same relationship to each other and get moved
together should we decide to reorganize the crate’s module tree. Therefore, we
used `super` so that we’ll have fewer places to update code in the future if
this code gets moved to a different module.


The Rust Programming Language › Paths for Referring to an Item in the Module Tree › Making Structs and Enums Public

We can also use `pub` to designate structs and enums as public, but there are a
few extra details to the usage of `pub` with structs and enums. If we use `pub`
before a struct definition, we make the struct public, but the struct’s fields
will still be private. We can make each field public or not on a case-by-case
basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct
with a public `toast` field but a private `seasonal_fruit` field. This models
the case in a restaurant where the customer can pick the type of bread that
comes with a meal, but the chef decides which fruit accompanies the meal based
on what’s in season and in stock. The available fruit changes quickly, so
customers can’t choose the fruit or even see which fruit they’ll get.
Listing 7-9: A struct with some public fields and some private fields (src/lib.rs)


The Rust Programming Language › Paths for Referring to an Item in the Module Tree › Making Structs and Enums Public

```rust,noplayground
mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String,
    }

    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                seasonal_fruit: String::from("peaches"),
            }
        }
    }
}

pub fn eat_at_restaurant() {
    // Order a breakfast in the summer with Rye toast.
    let mut meal = back_of_house::Breakfast::summer("Rye");
    // Change our mind about what bread we'd like.
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);

    // The next line won't compile if we uncomment it; we're not allowed
    // to see or modify the seasonal fruit that comes with the meal.
    // meal.seasonal_fruit = String::from("blueberries");
}
```
Because the `toast` field in the `back_of_house::Breakfast` struct is public,
in `eat_at_restaurant` we can write and read to the `toast` field using dot
notation. Notice that we can’t use the `seasonal_fruit` field in
`eat_at_restaurant`, because `seasonal_fruit` is private. Try uncommenting the
line modifying the `seasonal_fruit` field value to see what error you get!
Also, note that because `back_of_house::Breakfast` has a private field, the
struct needs to provide a public associated function that constructs an
instance of `Breakfast` (we’ve named it `summer` here). If `Breakfast` didn’t
have such a function, we couldn’t create an instance of `Breakfast` in
`eat_at_restaurant`, because we couldn’t set the value of the private
`seasonal_fruit` field in `eat_at_restaurant`.


The Rust Programming Language › Paths for Referring to an Item in the Module Tree › Making Structs and Enums Public

In contrast, if we make an enum public, all of its variants are then public. We
only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
Listing 7-10: Designating an enum as public makes all its variants public. (src/lib.rs)
```rust,noplayground
mod back_of_house {
    pub enum Appetizer {
        Soup,
        Salad,
    }
}

pub fn eat_at_restaurant() {
    let order1 = back_of_house::Appetizer::Soup;
    let order2 = back_of_house::Appetizer::Salad;
}
```
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
variants in `eat_at_restaurant`.
Enums aren’t very useful unless their variants are public; it would be annoying
to have to annotate all enum variants with `pub` in every case, so the default
for enum variants is to be public. Structs are often useful without their
fields being public, so struct fields follow the general rule of everything
being private by default unless annotated with `pub`.
There’s one more situation involving `pub` that we haven’t covered, and that is
our last module system feature: the `use` keyword. We’ll cover `use` by itself
first, and then we’ll show how to combine `pub` and `use`.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword

Having to write out the paths to call functions can feel inconvenient and
repetitive. In Listing 7-7, whether we chose the absolute or relative path to
the `add_to_waitlist` function, every time we wanted to call `add_to_waitlist`
we had to specify `front_of_house` and `hosting` too. Fortunately, there’s a
way to simplify this process: We can create a shortcut to a path with the `use`
keyword once and then use the shorter name everywhere else in the scope.
In Listing 7-11, we bring the `crate::front_of_house::hosting` module into the
scope of the `eat_at_restaurant` function so that we only have to specify
`hosting::add_to_waitlist` to call the `add_to_waitlist` function in
`eat_at_restaurant`.
Listing 7-11: Bringing a module into scope with `use` (src/lib.rs)
```rust,noplayground,test_harness
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}
```
Adding `use` and a path in a scope is similar to creating a symbolic link in
the filesystem. By adding `use crate::front_of_house::hosting` in the crate
root, `hosting` is now a valid name in that scope, just as though the `hosting`
module had been defined in the crate root. Paths brought into scope with `use`
also check privacy, like any other paths.

Bringing Paths Into Scope with the `use` Keyword


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword

Note that `use` only creates the shortcut for the particular scope in which the
`use` occurs. Listing 7-12 moves the `eat_at_restaurant` function into a new
child module named `customer`, which is then a different scope than the `use`
statement, so the function body won’t compile.
Listing 7-12: A `use` statement only applies in the scope it’s in. (src/lib.rs)
```rust,noplayground,test_harness,does_not_compile,ignore
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

mod customer {
    pub fn eat_at_restaurant() {
        hosting::add_to_waitlist();
    }
}
```
The compiler error shows that the shortcut no longer applies within the
`customer` module:


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword

```console
$ cargo build
   Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0433]: cannot find module or crate `hosting` in this scope
  --> src/lib.rs:11:9
   |
11 |         hosting::add_to_waitlist();
   |         ^^^^^^^ use of unresolved module or unlinked crate `hosting`
   |
   = help: if you wanted to use a crate named `hosting`, use `cargo add hosting` to add it to your `Cargo.toml`
help: consider importing this module through its public re-export
   |
10 +     use crate::hosting;
   |

warning: unused import: `crate::front_of_house::hosting`
 --> src/lib.rs:7:5
  |
7 | use crate::front_of_house::hosting;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted
```
Notice there’s also a warning that the `use` is no longer used in its scope! To
fix this problem, move the `use` within the `customer` module too, or reference
the shortcut in the parent module with `super::hosting` within the child
`customer` module.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Creating Idiomatic `use` Paths

In Listing 7-11, you might have wondered why we specified `use
crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
`eat_at_restaurant`, rather than specifying the `use` path all the way out to
the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
Listing 7-13: Bringing the `add_to_waitlist` function into scope with `use`, which is unidiomatic (src/lib.rs)
```rust,noplayground,test_harness
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}
```
Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
the function’s parent module into scope with `use` means we have to specify the
parent module when calling the function. Specifying the parent module when
calling the function makes it clear that the function isn’t locally defined
while still minimizing repetition of the full path. The code in Listing 7-13 is
unclear as to where `add_to_waitlist` is defined.
On the other hand, when bringing in structs, enums, and other items with `use`,
it’s idiomatic to specify the full path. Listing 7-14 shows the idiomatic way
to bring the standard library’s `HashMap` struct into the scope of a binary
crate.
Listing 7-14: Bringing `HashMap` into scope in an idiomatic way (src/main.rs)


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Creating Idiomatic `use` Paths

```rust
use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert(1, 2);
}
```
There’s no strong reason behind this idiom: It’s just the convention that has
emerged, and folks have gotten used to reading and writing Rust code this way.
The exception to this idiom is if we’re bringing two items with the same name
into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15
shows how to bring two `Result` types into scope that have the same name but
different parent modules, and how to refer to them.
Listing 7-15: Bringing two types with the same name into the same scope requires using their parent modules. (src/lib.rs)
```rust,noplayground
use std::fmt;
use std::io;

fn function1() -> fmt::Result {
    // --snip--
}

fn function2() -> io::Result<()> {
    // --snip--
}
```
As you can see, using the parent modules distinguishes the two `Result` types.
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
have two `Result` types in the same scope, and Rust wouldn’t know which one we
meant when we used `Result`.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Providing New Names with the `as` Keyword

There’s another solution to the problem of bringing two types of the same name
into the same scope with `use`: After the path, we can specify `as` and a new
local name, or _alias_, for the type. Listing 7-16 shows another way to write
the code in Listing 7-15 by renaming one of the two `Result` types using `as`.
Listing 7-16: Renaming a type when it’s brought into scope with the `as` keyword (src/lib.rs)
```rust,noplayground
use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --snip--
}

fn function2() -> IoResult<()> {
    // --snip--
}
```
In the second `use` statement, we chose the new name `IoResult` for the
`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are
considered idiomatic, so the choice is up to you!


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Re-exporting Names with `pub use`

When we bring a name into scope with the `use` keyword, the name is private to
the scope into which we imported it. To enable code outside that scope to refer
to that name as if it had been defined in that scope, we can combine `pub` and
`use`. This technique is called _re-exporting_ because we’re bringing an item
into scope but also making that item available for others to bring into their
scope.
Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
changed to `pub use`.
Listing 7-17: Making a name available for any code to use from a new scope with `pub use` (src/lib.rs)
```rust,noplayground,test_harness
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}
```
Before this change, external code would have to call the `add_to_waitlist`
function by using the path
`restaurant::front_of_house::hosting::add_to_waitlist()`, which also would have
required the `front_of_house` module to be marked as `pub`. Now that this `pub
use` has re-exported the `hosting` module from the root module, external code
can use the path `restaurant::hosting::add_to_waitlist()` instead.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Re-exporting Names with `pub use`

Re-exporting is useful when the internal structure of your code is different
from how programmers calling your code would think about the domain. For
example, in this restaurant metaphor, the people running the restaurant think
about “front of house” and “back of house.” But customers visiting a restaurant
probably won’t think about the parts of the restaurant in those terms. With `pub
use`, we can write our code with one structure but expose a different structure.
Doing so makes our library well organized for programmers working on the library
and programmers calling the library. We’ll look at another example of `pub use`
and how it affects your crate’s documentation in “Exporting a Convenient Public
API” in Chapter 14.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Using External Packages

In Chapter 2, we programmed a guessing game project that used an external
package called `rand` to get random numbers. To use `rand` in our project, we
added this line to _Cargo.toml_:
Listing (Cargo.toml)
```toml
rand = "0.10.1"
```
Adding `rand` as a dependency in _Cargo.toml_ tells Cargo to download the
`rand` package and any dependencies from crates.io and
make `rand` available to our project.
Then, to bring `rand` definitions into the scope of our package, we added a
`use` line starting with the name of the crate, `rand`, and listed the items we
wanted to bring into scope. Recall that in “Generating a Random
Number” in Chapter 2, we brought items in the
`rand::prelude` module into scope and called the `rand::rng` function:
```rust,ignore
use rand::prelude::*;

fn main() {
    let secret_number = rand::rng().random_range(1..=100);
}
```
Members of the Rust community have made many packages available at
crates.io, and pulling any of them into your package
involves these same steps: listing them in your package’s _Cargo.toml_ file and
using `use` to bring items from their crates into scope.
Note that the standard `std` library is also a crate that’s external to our
package. Because the standard library is shipped with the Rust language, we
don’t need to change _Cargo.toml_ to include `std`. But we do need to refer to
it with `use` to bring items from there into our package’s scope. For example,
with `HashMap` we would use this line:
```rust
use std::collections::HashMap;
```


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Using External Packages

This is an absolute path starting with `std`, the name of the standard library
crate.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Using Nested Paths to Clean Up `use` Lists

If we’re using multiple items defined in the same crate or same module, listing
each item on its own line can take up a lot of vertical space in our files. For
example, these two `use` statements we had in the guessing game in Listing 2-4
bring items from `std` into scope:
Listing (src/main.rs)
```rust,ignore
// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--
```
Instead, we can use nested paths to bring the same items into scope in one
line. We do this by specifying the common part of the path, followed by two
colons, and then curly brackets around a list of the parts of the paths that
differ, as shown in Listing 7-18.
Listing 7-18: Specifying a nested path to bring multiple items with the same prefix into scope (src/main.rs)
```rust,ignore
// --snip--
use std::{cmp::Ordering, io};
// --snip--
```
In bigger programs, bringing many items into scope from the same crate or
module using nested paths can reduce the number of separate `use` statements
needed by a lot!
We can use a nested path at any level in a path, which is useful when combining
two `use` statements that share a subpath. For example, Listing 7-19 shows two
`use` statements: one that brings `std::io` into scope and one that brings
`std::io::Write` into scope.
Listing 7-19: Two `use` statements where one is a subpath of the other (src/lib.rs)
```rust,noplayground
use std::io;
use std::io::Write;
```


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Using Nested Paths to Clean Up `use` Lists

The common part of these two paths is `std::io`, and that’s the complete first
path. To merge these two paths into one `use` statement, we can use `self` in
the nested path, as shown in Listing 7-20.
Listing 7-20: Combining the paths in Listing 7-19 into one `use` statement (src/lib.rs)
```rust,noplayground
use std::io::{self, Write};
```
This line brings `std::io` and `std::io::Write` into scope.


The Rust Programming Language › Bringing Paths into Scope with the `use` Keyword › Importing Items with the Glob Operator

If we want to bring _all_ public items defined in a path into scope, we can
specify that path followed by the `*` glob operator:
```rust
use std::collections::*;
```
This `use` statement brings all public items defined in `std::collections` into
the current scope. Be careful when using the glob operator! Glob can make it
harder to tell what names are in scope and where a name used in your program
was defined. Additionally, if the dependency changes its definitions, what
you’ve imported changes as well, which may lead to compiler errors when you
upgrade the dependency if the dependency adds a definition with the same name
as a definition of yours in the same scope, for example.
The glob operator is often used when testing to bring everything under test into
the `tests` module; we’ll talk about that in “How to Write
Tests” in Chapter 11. The glob operator is also
sometimes used as part of the prelude pattern: See the standard library
documentation for more
information on that pattern.


The Rust Programming Language › Separating Modules into Different Files

So far, all the examples in this chapter defined multiple modules in one file.
When modules get large, you might want to move their definitions to a separate
file to make the code easier to navigate.
For example, let’s start from the code in Listing 7-17 that had multiple
restaurant modules. We’ll extract modules into files instead of having all the
modules defined in the crate root file. In this case, the crate root file is
_src/lib.rs_, but this procedure also works with binary crates whose crate root
file is _src/main.rs_.
First, we’ll extract the `front_of_house` module to its own file. Remove the
code inside the curly brackets for the `front_of_house` module, leaving only
the `mod front_of_house;` declaration, so that _src/lib.rs_ contains the code
shown in Listing 7-21. Note that this won’t compile until we create the
_src/front_of_house.rs_ file in Listing 7-22.
Listing 7-21: Declaring the `front_of_house` module whose body will be in *src/front_of_house.rs* (src/lib.rs)
```rust,ignore,does_not_compile
mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}
```
Next, place the code that was in the curly brackets into a new file named
_src/front_of_house.rs_, as shown in Listing 7-22. The compiler knows to look
in this file because it came across the module declaration in the crate root
with the name `front_of_house`.
Listing 7-22: Definitions inside the `front_of_house` module in *src/front_of_house.rs* (src/front_of_house.rs)
```rust,ignore
pub mod hosting {
    pub fn add_to_waitlist() {}
}
```


The Rust Programming Language › Separating Modules into Different Files

Note that you only need to load a file using a `mod` declaration _once_ in your
module tree. Once the compiler knows the file is part of the project (and knows
where in the module tree the code resides because of where you’ve put the `mod`
statement), other files in your project should refer to the loaded file’s code
using a path to where it was declared, as covered in the “Paths for Referring
to an Item in the Module Tree” section. In other words,
`mod` is _not_ an “include” operation that you may have seen in other
programming languages.
Next, we’ll extract the `hosting` module to its own file. The process is a bit
different because `hosting` is a child module of `front_of_house`, not of the
root module. We’ll place the file for `hosting` in a new directory that will be
named for its ancestors in the module tree, in this case _src/front_of_house_.
To start moving `hosting`, we change _src/front_of_house.rs_ to contain only
the declaration of the `hosting` module:
Listing (src/front_of_house.rs)
```rust,ignore
pub mod hosting;
```
Then, we create a _src/front_of_house_ directory and a _hosting.rs_ file to
contain the definitions made in the `hosting` module:
Listing (src/front_of_house/hosting.rs)
```rust,ignore
pub fn add_to_waitlist() {}
```
If we instead put _hosting.rs_ in the _src_ directory, the compiler would
expect the _hosting.rs_ code to be in a `hosting` module declared in the crate
root and not declared as a child of the `front_of_house` module. The
compiler’s rules for which files to check for which modules’ code mean the
directories and files more closely match the module tree.


The Rust Programming Language › Separating Modules into Different Files › Alternate File Paths

So far we’ve covered the most idiomatic file paths the Rust compiler uses,
but Rust also supports an older style of file path. For a module named
`front_of_house` declared in the crate root, the compiler will look for the
module’s code in:
- _src/front_of_house.rs_ (what we covered)
- _src/front_of_house/mod.rs_ (older style, still supported path)
For a module named `hosting` that is a submodule of `front_of_house`, the
compiler will look for the module’s code in:
- _src/front_of_house/hosting.rs_ (what we covered)
- _src/front_of_house/hosting/mod.rs_ (older style, still supported path)
If you use both styles for the same module, you’ll get a compiler error.
Using a mix of both styles for different modules in the same project is
allowed but might be confusing for people navigating your project.
The main downside to the style that uses files named _mod.rs_ is that your
project can end up with many files named _mod.rs_, which can get confusing
when you have them open in your editor at the same time.
We’ve moved each module’s code to a separate file, and the module tree remains
the same. The function calls in `eat_at_restaurant` will work without any
modification, even though the definitions live in different files. This
technique lets you move modules to new files as they grow in size.
Note that the `pub use crate::front_of_house::hosting` statement in
_src/lib.rs_ also hasn’t changed, nor does `use` have any impact on what files
are compiled as part of the crate. The `mod` keyword declares modules, and Rust
looks in a file with the same name as the module for the code that goes into
that module.

Separating Modules into Different Files
Alternate File Paths


The Rust Programming Language › Summary

Rust lets you split a package into multiple crates and a crate into modules so
that you can refer to items defined in one module from another module. You can
do this by specifying absolute or relative paths. These paths can be brought
into scope with a `use` statement so that you can use a shorter path for
multiple uses of the item in that scope. Module code is private by default, but
you can make definitions public by adding the `pub` keyword.
In the next chapter, we’ll look at some collection data structures in the
standard library that you can use in your neatly organized code.


The Rust Programming Language › Common Collections

Rust’s standard library includes a number of very useful data structures called
_collections_. Most other data types represent one specific value, but
collections can contain multiple values. Unlike the built-in array and tuple
types, the data that these collections point to is stored on the heap, which
means the amount of data does not need to be known at compile time and can grow
or shrink as the program runs. Each kind of collection has different
capabilities and costs, and choosing an appropriate one for your current
situation is a skill you’ll develop over time. In this chapter, we’ll discuss
three collections that are used very often in Rust programs:
- A _vector_ allows you to store a variable number of values next to each other.
- A _string_ is a collection of characters. We’ve mentioned the `String` type
  previously, but in this chapter, we’ll talk about it in depth.
- A _hash map_ allows you to associate a value with a specific key. It’s a
  particular implementation of the more general data structure called a _map_.
To learn about the other kinds of collections provided by the standard library,
see the documentation.
We’ll discuss how to create and update vectors, strings, and hash maps, as well
as what makes each special.


The Rust Programming Language › Storing Lists of Values with Vectors

The first collection type we’ll look at is `Vec<T>`, also known as a vector.
Vectors allow you to store more than one value in a single data structure that
puts all the values next to each other in memory. Vectors can only store values
of the same type. They are useful when you have a list of items, such as the
lines of text in a file or the prices of items in a shopping cart.


The Rust Programming Language › Storing Lists of Values with Vectors › Creating a New Vector

To create a new, empty vector, we call the `Vec::new` function, as shown in
Listing 8-1.
Listing 8-1: Creating a new, empty vector to hold values of type `i32`
```rust
    let v: Vec<i32> = Vec::new();
```
Note that we added a type annotation here. Because we aren’t inserting any
values into this vector, Rust doesn’t know what kind of elements we intend to
store. This is an important point. Vectors are implemented using generics;
we’ll cover how to use generics with your own types in Chapter 10. For now,
know that the `Vec<T>` type provided by the standard library can hold any type.
When we create a vector to hold a specific type, we can specify the type within
angle brackets. In Listing 8-1, we’ve told Rust that the `Vec<T>` in `v` will
hold elements of the `i32` type.
More often, you’ll create a `Vec<T>` with initial values, and Rust will infer
the type of value you want to store, so you rarely need to do this type
annotation. Rust conveniently provides the `vec!` macro, which will create a
new vector that holds the values you give it. Listing 8-2 creates a new
`Vec<i32>` that holds the values `1`, `2`, and `3`. The integer type is `i32`
because that’s the default integer type, as we discussed in the “Data
Types” section of Chapter 3.
Listing 8-2: Creating a new vector containing values
```rust
    let v = vec![1, 2, 3];
```

Storing Lists of Values with Vectors
Creating a New Vector


The Rust Programming Language › Storing Lists of Values with Vectors › Creating a New Vector

Because we’ve given initial `i32` values, Rust can infer that the type of `v`
is `Vec<i32>`, and the type annotation isn’t necessary. Next, we’ll look at how
to modify a vector.


The Rust Programming Language › Storing Lists of Values with Vectors › Updating a Vector

To create a vector and then add elements to it, we can use the `push` method,
as shown in Listing 8-3.
Listing 8-3: Using the `push` method to add values to a vector
```rust
    let mut v = Vec::new();

    v.push(5);
    v.push(6);
    v.push(7);
    v.push(8);
```
As with any variable, if we want to be able to change its value, we need to
make it mutable using the `mut` keyword, as discussed in Chapter 3. The numbers
we place inside are all of type `i32`, and Rust infers this from the data, so
we don’t need the `Vec<i32>` annotation.

Storing Lists of Values with Vectors
Updating a Vector


The Rust Programming Language › Storing Lists of Values with Vectors › Reading Elements of Vectors

There are two ways to reference a value stored in a vector: via indexing or by
using the `get` method. In the following examples, we’ve annotated the types of
the values that are returned from these functions for extra clarity.
Listing 8-4 shows both methods of accessing a value in a vector, with indexing
syntax and the `get` method.
Listing 8-4: Using indexing syntax and using the `get` method to access an item in a vector
```rust
    let v = vec![1, 2, 3, 4, 5];

    let third: &i32 = &v[2];
    println!("The third element is {third}");

    let third: Option<&i32> = v.get(2);
    match third {
        Some(third) => println!("The third element is {third}"),
        None => println!("There is no third element."),
    }
```
Note a few details here. We use the index value of `2` to get the third element
because vectors are indexed by number, starting at zero. Using `&` and `[]`
gives us a reference to the element at the index value. When we use the `get`
method with the index passed as an argument, we get an `Option<&T>` that we can
use with `match`.
Rust provides these two ways to reference an element so that you can choose how
the program behaves when you try to use an index value outside the range of
existing elements. As an example, let’s see what happens when we have a vector
of five elements and then we try to access an element at index 100 with each
technique, as shown in Listing 8-5.
Listing 8-5: Attempting to access the element at index 100 in a vector containing five elements

Storing Lists of Values with Vectors
Reading Elements of Vectors


The Rust Programming Language › Storing Lists of Values with Vectors › Reading Elements of Vectors

```rust,should_panic,panics
    let v = vec![1, 2, 3, 4, 5];

    let does_not_exist = &v[100];
    let does_not_exist = v.get(100);
```
When we run this code, the first `[]` method will cause the program to panic
because it references a nonexistent element. This method is best used when you
want your program to crash if there’s an attempt to access an element past the
end of the vector.
When the `get` method is passed an index that is outside the vector, it returns
`None` without panicking. You would use this method if accessing an element
beyond the range of the vector may happen occasionally under normal
circumstances. Your code will then have logic to handle having either
`Some(&element)` or `None`, as discussed in Chapter 6. For example, the index
could be coming from a person entering a number. If they accidentally enter a
number that’s too large and the program gets a `None` value, you could tell the
user how many items are in the current vector and give them another chance to
enter a valid value. That would be more user-friendly than crashing the program
due to a typo!
When the program has a valid reference, the borrow checker enforces the
ownership and borrowing rules (covered in Chapter 4) to ensure that this
reference and any other references to the contents of the vector remain valid.
Recall the rule that states you can’t have mutable and immutable references in
the same scope. That rule applies in Listing 8-6, where we hold an immutable
reference to the first element in a vector and try to add an element to the
end. This program won’t work if we also try to refer to that element later in
the function.
Listing 8-6: Attempting to add an element to a vector while holding a reference to an item


The Rust Programming Language › Storing Lists of Values with Vectors › Reading Elements of Vectors

```rust,ignore,does_not_compile
    let mut v = vec![1, 2, 3, 4, 5];

    let first = &v[0];

    v.push(6);

    println!("The first element is: {first}");
```
Compiling this code will result in this error:
```console
$ cargo run
   Compiling collections v0.1.0 (file:///projects/collections)
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
 --> src/main.rs:6:5
  |
4 |     let first = &v[0];
  |                  - immutable borrow occurs here
5 |
6 |     v.push(6);
  |     ^^^^^^^^^ mutable borrow occurs here
7 |
8 |     println!("The first element is: {first}");
  |                                      ----- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `collections` (bin "collections") due to 1 previous error
```
The code in Listing 8-6 might look like it should work: Why should a reference
to the first element care about changes at the end of the vector? This error is
due to the way vectors work: Because vectors put the values next to each other
in memory, adding a new element onto the end of the vector might require
allocating new memory and copying the old elements to the new space, if there
isn’t enough room to put all the elements next to each other where the vector
is currently stored. In that case, the reference to the first element would be
pointing to deallocated memory. The borrowing rules prevent programs from
ending up in that situation.
Note: For more on the implementation details of the `Vec<T>` type, see “The
Rustonomicon”.


The Rust Programming Language › Storing Lists of Values with Vectors › Iterating Over the Values in a Vector

To access each element in a vector in turn, we would iterate through all of the
elements rather than use indices to access one at a time. Listing 8-7 shows how
to use a `for` loop to get immutable references to each element in a vector of
`i32` values and print them.
Listing 8-7: Printing each element in a vector by iterating over the elements using a `for` loop
```rust
    let v = vec![100, 32, 57];
    for i in &v {
        println!("{i}");
    }
```
We can also iterate over mutable references to each element in a mutable vector
in order to make changes to all the elements. The `for` loop in Listing 8-8
will add `50` to each element.
Listing 8-8: Iterating over mutable references to elements in a vector
```rust
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    }
```
To change the value that the mutable reference refers to, we have to use the
`*` dereference operator to get to the value in `i` before we can use the `+=`
operator. We’ll talk more about the dereference operator in the “Following the
Reference to the Value” section of Chapter 15.
Iterating over a vector, whether immutably or mutably, is safe because of the
borrow checker’s rules. If we attempted to insert or remove items in the `for`
loop bodies in Listing 8-7 and Listing 8-8, we would get a compiler error
similar to the one we got with the code in Listing 8-6. The reference to the
vector that the `for` loop holds prevents simultaneous modification of the
whole vector.

Storing Lists of Values with Vectors
Iterating Over the Values in a Vector


The Rust Programming Language › Storing Lists of Values with Vectors › Using an Enum to Store Multiple Types

Vectors can only store values that are of the same type. This can be
inconvenient; there are definitely use cases for needing to store a list of
items of different types. Fortunately, the variants of an enum are defined
under the same enum type, so when we need one type to represent elements of
different types, we can define and use an enum!
For example, say we want to get values from a row in a spreadsheet in which
some of the columns in the row contain integers, some floating-point numbers,
and some strings. We can define an enum whose variants will hold the different
value types, and all the enum variants will be considered the same type: that
of the enum. Then, we can create a vector to hold that enum and so, ultimately,
hold different types. We’ve demonstrated this in Listing 8-9.
Listing 8-9: Defining an enum to store values of different types in one vector
```rust
    enum SpreadsheetCell {
        Int(i32),
        Float(f64),
        Text(String),
    }

    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
```
Rust needs to know what types will be in the vector at compile time so that it
knows exactly how much memory on the heap will be needed to store each element.
We must also be explicit about what types are allowed in this vector. If Rust
allowed a vector to hold any type, there would be a chance that one or more of
the types would cause errors with the operations performed on the elements of
the vector. Using an enum plus a `match` expression means that Rust will ensure
at compile time that every possible case is handled, as discussed in Chapter 6.

Storing Lists of Values with Vectors
Using an Enum to Store Multiple Types


The Rust Programming Language › Storing Lists of Values with Vectors › Using an Enum to Store Multiple Types

If you don’t know the exhaustive set of types a program will get at runtime to
store in a vector, the enum technique won’t work. Instead, you can use a trait
object, which we’ll cover in Chapter 18.
Now that we’ve discussed some of the most common ways to use vectors, be sure
to review the API documentation for all of the many
useful methods defined on `Vec<T>` by the standard library. For example, in
addition to `push`, a `pop` method removes and returns the last element.


The Rust Programming Language › Storing Lists of Values with Vectors › Dropping a Vector Drops Its Elements

Like any other `struct`, a vector is freed when it goes out of scope, as
annotated in Listing 8-10.
Listing 8-10: Showing where the vector and its elements are dropped
```rust
    {
        let v = vec![1, 2, 3, 4];

        // do stuff with v
    } // <- v goes out of scope and is freed here
```
When the vector gets dropped, all of its contents are also dropped, meaning the
integers it holds will be cleaned up. The borrow checker ensures that any
references to contents of a vector are only used while the vector itself is
valid.
Let’s move on to the next collection type: `String`!

Storing Lists of Values with Vectors
Dropping a Vector Drops Its Elements


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings

We talked about strings in Chapter 4, but we’ll look at them in more depth now.
New Rustaceans commonly get stuck on strings for a combination of three
reasons: Rust’s propensity for exposing possible errors, strings being a more
complicated data structure than many programmers give them credit for, and
UTF-8. These factors combine in a way that can seem difficult when you’re
coming from other programming languages.
We discuss strings in the context of collections because strings are
implemented as a collection of bytes, plus some methods to provide useful
functionality when those bytes are interpreted as text. In this section, we’ll
talk about the operations on `String` that every collection type has, such as
creating, updating, and reading. We’ll also discuss the ways in which `String`
is different from the other collections, namely, how indexing into a `String` is
complicated by the differences between how people and computers interpret
`String` data.


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Defining Strings

We’ll first define what we mean by the term _string_. Rust has only one string
type in the core language, which is the string slice `str` that is usually seen
in its borrowed form, `&str`. In Chapter 4, we talked about string slices,
which are references to some UTF-8 encoded string data stored elsewhere. String
literals, for example, are stored in the program’s binary and are therefore
string slices.
The `String` type, which is provided by Rust’s standard library rather than
coded into the core language, is a growable, mutable, owned, UTF-8 encoded
string type. When Rustaceans refer to “strings” in Rust, they might be
referring to either the `String` or the string slice `&str` types, not just one
of those types. Although this section is largely about `String`, both types are
used heavily in Rust’s standard library, and both `String` and string slices
are UTF-8 encoded.

Storing UTF-8 Encoded Text with Strings
Defining Strings


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Creating a New String

Many of the same operations available with `Vec<T>` are available with `String`
as well because `String` is actually implemented as a wrapper around a vector
of bytes with some extra guarantees, restrictions, and capabilities. An example
of a function that works the same way with `Vec<T>` and `String` is the `new`
function to create an instance, shown in Listing 8-11.
Listing 8-11: Creating a new, empty `String`
```rust
    let mut s = String::new();
```
This line creates a new, empty string called `s`, into which we can then load
data. Often, we’ll have some initial data with which we want to start the
string. For that, we use the `to_string` method, which is available on any type
that implements the `Display` trait, as string literals do. Listing 8-12 shows
two examples.
Listing 8-12: Using the `to_string` method to create a `String` from a string literal
```rust
    let data = "initial contents";

    let s = data.to_string();

    // The method also works on a literal directly:
    let s = "initial contents".to_string();
```
This code creates a string containing `initial contents`.
We can also use the function `String::from` to create a `String` from a string
literal. The code in Listing 8-13 is equivalent to the code in Listing 8-12
that uses `to_string`.
Listing 8-13: Using the `String::from` function to create a `String` from a string literal
```rust
    let s = String::from("initial contents");
```

Storing UTF-8 Encoded Text with Strings
Creating a New String


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Creating a New String

Because strings are used for so many things, we can use many different generic
APIs for strings, providing us with a lot of options. Some of them can seem
redundant, but they all have their place! In this case, `String::from` and
`to_string` do the same thing, so which one you choose is a matter of style and
readability.
Remember that strings are UTF-8 encoded, so we can include any properly encoded
data in them, as shown in Listing 8-14.
Listing 8-14: Storing greetings in different languages in strings
```rust
    let hello = String::from("السلام عليكم");
    let hello = String::from("Dobrý den");
    let hello = String::from("Hello");
    let hello = String::from("שלום");
    let hello = String::from("नमस्ते");
    let hello = String::from("こんにちは");
    let hello = String::from("안녕하세요");
    let hello = String::from("你好");
    let hello = String::from("Olá");
    let hello = String::from("Здравствуйте");
    let hello = String::from("Hola");
```
All of these are valid `String` values.


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Updating a String › Concatenating with `+` or `format!`

A `String` can grow in size and its contents can change, just like the contents
of a `Vec<T>`, if you push more data into it. In addition, you can conveniently
use the `+` operator or the `format!` macro to concatenate `String` values.
We can grow a `String` by using the `push_str` method to append a string slice,
as shown in Listing 8-15.
Listing 8-15: Appending a string slice to a `String` using the `push_str` method
```rust
    let mut s = String::from("foo");
    s.push_str("bar");
```
After these two lines, `s` will contain `foobar`. The `push_str` method takes a
string slice because we don’t necessarily want to take ownership of the
parameter. For example, in the code in Listing 8-16, we want to be able to use
`s2` after appending its contents to `s1`.
Listing 8-16: Using a string slice after appending its contents to a `String`
```rust
    let mut s1 = String::from("foo");
    let s2 = "bar";
    s1.push_str(s2);
    println!("s2 is {s2}");
```
If the `push_str` method took ownership of `s2`, we wouldn’t be able to print
its value on the last line. However, this code works as we’d expect!
The `push` method takes a single character as a parameter and adds it to the
`String`. Listing 8-17 adds the letter _l_ to a `String` using the `push`
method.
Listing 8-17: Adding one character to a `String` value using `push`
```rust
    let mut s = String::from("lo");
    s.push('l');
```
As a result, `s` will contain `lol`.

Storing UTF-8 Encoded Text with Strings
Updating a String
Concatenating with `+` or `format!`


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Updating a String › Concatenating with `+` or `format!`

Often, you’ll want to combine two existing strings. One way to do so is to use
the `+` operator, as shown in Listing 8-18.
Listing 8-18: Using the `+` operator to combine two `String` values into a new `String` value
```rust
    let s1 = String::from("Hello, ");
    let s2 = String::from("world!");
    let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
```
The string `s3` will contain `Hello, world!`. The reason `s1` is no longer
valid after the addition, and the reason we used a reference to `s2`, has to do
with the signature of the method that’s called when we use the `+` operator.
The `+` operator uses the `add` method, whose signature looks something like
this:
```rust,ignore
fn add(self, s: &str) -> String {
```
In the standard library, you’ll see `add` defined using generics and associated
types. Here, we’ve substituted in concrete types, which is what happens when we
call this method with `String` values. We’ll discuss generics in Chapter 10.
This signature gives us the clues we need in order to understand the tricky
bits of the `+` operator.
First, `s2` has an `&`, meaning that we’re adding a reference of the second
string to the first string. This is because of the `s` parameter in the `add`
function: We can only add a string slice to a `String`; we can’t add two
`String` values together. But wait—the type of `&s2` is `&String`, not `&str`,
as specified in the second parameter to `add`. So, why does Listing 8-18
compile?


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Updating a String › Concatenating with `+` or `format!`

The reason we’re able to use `&s2` in the call to `add` is that the compiler
can coerce the `&String` argument into a `&str`. When we call the `add` method,
Rust uses a deref coercion, which here turns `&s2` into `&s2[..]`. We’ll
discuss deref coercion in more depth in Chapter 15. Because `add` does not take
ownership of the `s` parameter, `s2` will still be a valid `String` after this
operation.
Second, we can see in the signature that `add` takes ownership of `self`
because `self` does _not_ have an `&`. This means `s1` in Listing 8-18 will be
moved into the `add` call and will no longer be valid after that. So, although
`let s3 = s1 + &s2;` looks like it will copy both strings and create a new one,
this statement actually takes ownership of `s1`, appends a copy of the contents
of `s2`, and then returns ownership of the result. In other words, it looks
like it’s making a lot of copies, but it isn’t; the implementation is more
efficient than copying.
If we need to concatenate multiple strings, the behavior of the `+` operator
gets unwieldy:
```rust
    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");

    let s = s1 + "-" + &s2 + "-" + &s3;
```


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Updating a String › Concatenating with `+` or `format!`

At this point, `s` will be `tic-tac-toe`. With all of the `+` and `"`
characters, it’s difficult to see what’s going on. For combining strings in
more complicated ways, we can instead use the `format!` macro:
```rust
    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");

    let s = format!("{s1}-{s2}-{s3}");
```
This code also sets `s` to `tic-tac-toe`. The `format!` macro works like
`println!`, but instead of printing the output to the screen, it returns a
`String` with the contents. The version of the code using `format!` is much
easier to read, and the code generated by the `format!` macro uses references
so that this call doesn’t take ownership of any of its parameters.


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Indexing into Strings

In many other programming languages, accessing individual characters in a
string by referencing them by index is a valid and common operation. However,
if you try to access parts of a `String` using indexing syntax in Rust, you’ll
get an error. Consider the invalid code in Listing 8-19.
Listing 8-19: Attempting to use indexing syntax with a `String`
```rust,ignore,does_not_compile
    let s1 = String::from("hi");
    let h = s1[0];
```
This code will result in the following error:

Storing UTF-8 Encoded Text with Strings
Indexing into Strings


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Indexing into Strings › Internal Representation

```console
$ cargo run
   Compiling collections v0.1.0 (file:///projects/collections)
error[E0277]: the type `str` cannot be indexed by `{integer}`
 --> src/main.rs:3:16
  |
3 |     let h = s1[0];
  |                ^ string indices are ranges of `usize`
  |
  = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
  = note: you can use `.chars().nth()` or `.bytes().nth()`
          for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
help: `usize` implements trait `SliceIndex<T>`
 --> /rustc/2d8144b7880597b6e6d3dfd63a9a9efae3f533d3/library/core/src/slice/index.rs:214:0
  |
  = note: `SliceIndex<[T]>`
 --> /rustc/2d8144b7880597b6e6d3dfd63a9a9efae3f533d3/library/core/src/bstr/traits.rs:197:0
  |
  = note: `SliceIndex<ByteStr>`
  = note: required for `String` to implement `Index<{integer}>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `collections` (bin "collections") due to 1 previous error
```
The error tells the story: Rust strings don’t support indexing. But why not? To
answer that question, we need to discuss how Rust stores strings in memory.

Storing UTF-8 Encoded Text with Strings
Indexing into Strings
Internal Representation


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Indexing into Strings › Internal Representation

A `String` is a wrapper over a `Vec<u8>`. Let’s look at some of our properly
encoded UTF-8 example strings from Listing 8-14. First, this one:
```rust
    let hello = String::from("Hola");
```
In this case, `len` will be `4`, which means the vector storing the string
`"Hola"` is 4 bytes long. Each of these letters takes 1 byte when encoded in
UTF-8. The following line, however, may surprise you (note that this string
begins with the capital Cyrillic letter _Ze_, not the number 3):
```rust
    let hello = String::from("Здравствуйте");
```
If you were asked how long the string is, you might say 12. In fact, Rust’s
answer is 24: That’s the number of bytes it takes to encode “Здравствуйте” in
UTF-8, because each Unicode scalar value in that string takes 2 bytes of
storage. Therefore, an index into the string’s bytes will not always correlate
to a valid Unicode scalar value. To demonstrate, consider this invalid Rust
code:
```rust,ignore,does_not_compile
let hello = "Здравствуйте";
let answer = &hello[0];
```


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Indexing into Strings › Bytes, Scalar Values, and Grapheme Clusters

You already know that `answer` will not be `З`, the first letter. When encoded
in UTF-8, the first byte of `З` is `208` and the second is `151`, so it would
seem that `answer` should in fact be `208`, but `208` is not a valid character
on its own. Returning `208` is likely not what a user would want if they asked
for the first letter of this string; however, that’s the only data that Rust
has at byte index 0. Users generally don’t want the byte value returned, even
if the string contains only Latin letters: If `&"hi"[0]` were valid code that
returned the byte value, it would return `104`, not `h`.
The answer, then, is that to avoid returning an unexpected value and causing
bugs that might not be discovered immediately, Rust doesn’t compile this code
at all and prevents misunderstandings early in the development process.
Another point about UTF-8 is that there are actually three relevant ways to
look at strings from Rust’s perspective: as bytes, scalar values, and grapheme
clusters (the closest thing to what we would call _letters_).
If we look at the Hindi word “नमस्ते” written in the Devanagari script, it is
stored as a vector of `u8` values that looks like this:
```text
[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164,
224, 165, 135]
```


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Indexing into Strings › Bytes, Scalar Values, and Grapheme Clusters

That’s 18 bytes and is how computers ultimately store this data. If we look at
them as Unicode scalar values, which are what Rust’s `char` type is, those
bytes look like this:
```text
['न', 'म', 'स', '्', 'त', 'े']
```
There are six `char` values here, but the fourth and sixth are not letters:
They’re diacritics that don’t make sense on their own. Finally, if we look at
them as grapheme clusters, we’d get what a person would call the four letters
that make up the Hindi word:
```text
["न", "म", "स्", "ते"]
```
Rust provides different ways of interpreting the raw string data that computers
store so that each program can choose the interpretation it needs, no matter
what human language the data is in.
A final reason Rust doesn’t allow us to index into a `String` to get a
character is that indexing operations are expected to always take constant time
(O(1)). But it isn’t possible to guarantee that performance with a `String`,
because Rust would have to walk through the contents from the beginning to the
index to determine how many valid characters there were.


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Slicing Strings

Indexing into a string is often a bad idea because it’s not clear what the
return type of the string-indexing operation should be: a byte value, a
character, a grapheme cluster, or a string slice. If you really need to use
indices to create string slices, therefore, Rust asks you to be more specific.
Rather than indexing using `[]` with a single number, you can use `[]` with a
range to create a string slice containing particular bytes:
```rust
let hello = "Здравствуйте";

let s = &hello[0..4];
```
Here, `s` will be a `&str` that contains the first 4 bytes of the string.
Earlier, we mentioned that each of these characters was 2 bytes, which means
`s` will be `Зд`.
If we were to try to slice only part of a character’s bytes with something like
`&hello[0..1]`, Rust would panic at runtime in the same way as if an invalid
index were accessed in a vector:
```console
$ cargo run
   Compiling collections v0.1.0 (file:///projects/collections)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
     Running `target/debug/collections`

thread 'main' (6017738) panicked at src/main.rs:4:19:
end byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2 of string)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
You should use caution when creating string slices with ranges, because doing
so can crash your program.

Storing UTF-8 Encoded Text with Strings
Slicing Strings


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Iterating Over Strings

The best way to operate on pieces of strings is to be explicit about whether
you want characters or bytes. For individual Unicode scalar values, use the
`chars` method. Calling `chars` on “Зд” separates out and returns two values of
type `char`, and you can iterate over the result to access each element:
```rust
for c in "Зд".chars() {
    println!("{c}");
}
```
This code will print the following:
```text
З
д
```
Alternatively, the `bytes` method returns each raw byte, which might be
appropriate for your domain:
```rust
for b in "Зд".bytes() {
    println!("{b}");
}
```
This code will print the 4 bytes that make up this string:
```text
208
151
208
180
```
But be sure to remember that valid Unicode scalar values may be made up of more
than 1 byte.
Getting grapheme clusters from strings, as with the Devanagari script, is
complex, so this functionality is not provided by the standard library. Crates
are available on crates.io if this is the
functionality you need.

Storing UTF-8 Encoded Text with Strings
Iterating Over Strings


The Rust Programming Language › Storing UTF-8 Encoded Text with Strings › Handling the Complexities of Strings

To summarize, strings are complicated. Different programming languages make
different choices about how to present this complexity to the programmer. Rust
has chosen to make the correct handling of `String` data the default behavior
for all Rust programs, which means programmers have to put more thought into
handling UTF-8 data up front. This trade-off exposes more of the complexity of
strings than is apparent in other programming languages, but it prevents you
from having to handle errors involving non-ASCII characters later in your
development life cycle.
The good news is that the standard library offers a lot of functionality built
off the `String` and `&str` types to help handle these complex situations
correctly. Be sure to check out the documentation for useful methods like
`contains` for searching in a string and `replace` for substituting parts of a
string with another string.
Let’s switch to something a bit less complex: hash maps!

Storing UTF-8 Encoded Text with Strings
Handling the Complexities of Strings


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps

The last of our common collections is the hash map. The type `HashMap<K, V>`
stores a mapping of keys of type `K` to values of type `V` using a _hashing
function_, which determines how it places these keys and values into memory.
Many programming languages support this kind of data structure, but they often
use a different name, such as _hash_, _map_, _object_, _hash table_,
_dictionary_, or _associative array_, just to name a few.
Hash maps are useful when you want to look up data not by using an index, as
you can with vectors, but by using a key that can be of any type. For example,
in a game, you could keep track of each team’s score in a hash map in which
each key is a team’s name and the values are each team’s score. Given a team
name, you can retrieve its score.
We’ll go over the basic API of hash maps in this section, but many more goodies
are hiding in the functions defined on `HashMap<K, V>` by the standard library.
As always, check the standard library documentation for more information.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Creating a New Hash Map

One way to create an empty hash map is to use `new` and to add elements with
`insert`. In Listing 8-20, we’re keeping track of the scores of two teams whose
names are _Blue_ and _Yellow_. The Blue team starts with 10 points, and the
Yellow team starts with 50.
Listing 8-20: Creating a new hash map and inserting some keys and values
```rust
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
```
Note that we need to first `use` the `HashMap` from the collections portion of
the standard library. Of our three common collections, this one is the least
often used, so it’s not included in the features brought into scope
automatically in the prelude. Hash maps also have less support from the
standard library; there’s no built-in macro to construct them, for example.
Just like vectors, hash maps store their data on the heap. This `HashMap` has
keys of type `String` and values of type `i32`. Like vectors, hash maps are
homogeneous: All of the keys must have the same type, and all of the values
must have the same type.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Accessing Values in a Hash Map

We can get a value out of the hash map by providing its key to the `get`
method, as shown in Listing 8-21.
Listing 8-21: Accessing the score for the Blue team stored in the hash map
```rust
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);
```
Here, `score` will have the value that’s associated with the Blue team, and the
result will be `10`. The `get` method returns an `Option<&V>`; if there’s no
value for that key in the hash map, `get` will return `None`. This program
handles the `Option` by calling `copied` to get an `Option<i32>` rather than an
`Option<&i32>`, then `unwrap_or` to set `score` to zero if `scores` doesn’t
have an entry for the key.
We can iterate over each key-value pair in a hash map in a similar manner as we
do with vectors, using a `for` loop:
```rust
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    for (key, value) in &scores {
        println!("{key}: {value}");
    }
```
This code will print each pair in an arbitrary order:
```text
Yellow: 50
Blue: 10
```


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Managing Ownership in Hash Maps

For types that implement the `Copy` trait, like `i32`, the values are copied
into the hash map. For owned values like `String`, the values will be moved and
the hash map will be the owner of those values, as demonstrated in Listing 8-22.
Listing 8-22: Showing that keys and values are owned by the hash map once they’re inserted
```rust
    use std::collections::HashMap;

    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    map.insert(field_name, field_value);
    // field_name and field_value are invalid at this point, try using them and
    // see what compiler error you get!
```
We aren’t able to use the variables `field_name` and `field_value` after
they’ve been moved into the hash map with the call to `insert`.
If we insert references to values into the hash map, the values won’t be moved
into the hash map. The values that the references point to must be valid for at
least as long as the hash map is valid. We’ll talk more about these issues in
“Validating References with
Lifetimes” in Chapter 10.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Updating a Hash Map › Adding a Key and Value Only If a Key Isn’t Present

Although the number of key and value pairs is growable, each unique key can
only have one value associated with it at a time (but not vice versa: For
example, both the Blue team and the Yellow team could have the value `10`
stored in the `scores` hash map).
When you want to change the data in a hash map, you have to decide how to
handle the case when a key already has a value assigned. You could replace the
old value with the new value, completely disregarding the old value. You could
keep the old value and ignore the new value, only adding the new value if the
key _doesn’t_ already have a value. Or you could combine the old value and the
new value. Let’s look at how to do each of these!
If we insert a key and a value into a hash map and then insert that same key
with a different value, the value associated with that key will be replaced.
Even though the code in Listing 8-23 calls `insert` twice, the hash map will
only contain one key-value pair because we’re inserting the value for the Blue
team’s key both times.
Listing 8-23: Replacing a value stored with a particular key
```rust
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 25);

    println!("{scores:?}");
```
This code will print `{"Blue": 25}`. The original value of `10` has been
overwritten.
It’s common to check whether a particular key already exists in the hash map
with a value and then to take the following actions: If the key does exist in
the hash map, the existing value should remain the way it is; if the key
doesn’t exist, insert it and a value for it.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Updating a Hash Map › Updating a Value Based on the Old Value

Hash maps have a special API for this called `entry` that takes the key you
want to check as a parameter. The return value of the `entry` method is an enum
called `Entry` that represents a value that might or might not exist. Let’s say
we want to check whether the key for the Yellow team has a value associated
with it. If it doesn’t, we want to insert the value `50`, and the same for the
Blue team. Using the `entry` API, the code looks like Listing 8-24.
Listing 8-24: Using the `entry` method to only insert if the key does not already have a value
```rust
    use std::collections::HashMap;

    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);

    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

    println!("{scores:?}");
```
The `or_insert` method on `Entry` is defined to return a mutable reference to
the value for the corresponding `Entry` key if that key exists, and if not, it
inserts the parameter as the new value for this key and returns a mutable
reference to the new value. This technique is much cleaner than writing the
logic ourselves and, in addition, plays more nicely with the borrow checker.
Running the code in Listing 8-24 will print `{"Yellow": 50, "Blue": 10}`. The
first call to `entry` will insert the key for the Yellow team with the value
`50` because the Yellow team doesn’t have a value already. The second call to
`entry` will not change the hash map, because the Blue team already has the
value `10`.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Updating a Hash Map › Updating a Value Based on the Old Value

Another common use case for hash maps is to look up a key’s value and then
update it based on the old value. For instance, Listing 8-25 shows code that
counts how many times each word appears in some text. We use a hash map with
the words as keys and increment the value to keep track of how many times we’ve
seen that word. If it’s the first time we’ve seen a word, we’ll first insert
the value `0`.
Listing 8-25: Counting occurrences of words using a hash map that stores words and counts
```rust
    use std::collections::HashMap;

    let text = "hello world wonderful world";

    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }

    println!("{map:?}");
```
This code will print `{"world": 2, "hello": 1, "wonderful": 1}`. You might see
the same key-value pairs printed in a different order: Recall from “Accessing
Values in a Hash Map” that iterating over a hash map
happens in an arbitrary order.
The `split_whitespace` method returns an iterator over subslices, separated by
whitespace, of the value in `text`. The `or_insert` method returns a mutable
reference (`&mut V`) to the value for the specified key. Here, we store that
mutable reference in the `count` variable, so in order to assign to that value,
we must first dereference `count` using the asterisk (`*`). The mutable
reference goes out of scope at the end of the `for` loop, so all of these
changes are safe and allowed by the borrowing rules.


The Rust Programming Language › Storing Keys with Associated Values in Hash Maps › Hashing Functions

By default, `HashMap` uses a hashing function called _SipHash_ that can provide
resistance to denial-of-service (DoS) attacks involving hash
tables[^siphash]. This is not the fastest hashing algorithm
available, but the trade-off for better security that comes with the drop in
performance is worth it. If you profile your code and find that the default
hash function is too slow for your purposes, you can switch to another function
by specifying a different hasher. A _hasher_ is a type that implements the
`BuildHasher` trait. We’ll talk about traits and how to implement them in
Chapter 10. You don’t necessarily have to implement
your own hasher from scratch; crates.io
has libraries shared by other Rust users that provide hashers implementing many
common hashing algorithms.
[^siphash]: https://en.wikipedia.org/wiki/SipHash


The Rust Programming Language › Summary

Vectors, strings, and hash maps will provide a large amount of functionality
necessary in programs when you need to store, access, and modify data. Here are
some exercises you should now be equipped to solve:
1. Given a list of integers, use a vector and return the median (when sorted,
   the value in the middle position) and mode (the value that occurs most
   often; a hash map will be helpful here) of the list.
1. Convert strings to Pig Latin. The first consonant of each word is moved to
   the end of the word and _ay_ is added, so _first_ becomes _irst-fay_. Words
   that start with a vowel have _hay_ added to the end instead (_apple_ becomes
   _apple-hay_). Keep in mind the details about UTF-8 encoding!
1. Using a hash map and vectors, create a text interface to allow a user to add
   employee names to a department in a company; for example, “Add Sally to
   Engineering” or “Add Amir to Sales.” Then, let the user retrieve a list of
   all people in a department or all people in the company by department, sorted
   alphabetically.
The standard library API documentation describes methods that vectors, strings,
and hash maps have that will be helpful for these exercises!
We’re getting into more complex programs in which operations can fail, so it’s
a perfect time to discuss error handling. We’ll do that next!


The Rust Programming Language › Error Handling

Errors are a fact of life in software, so Rust has a number of features for
handling situations in which something goes wrong. In many cases, Rust requires
you to acknowledge the possibility of an error and take some action before your
code will compile. This requirement makes your program more robust by ensuring
that you’ll discover errors and handle them appropriately before deploying your
code to production!
Rust groups errors into two major categories: recoverable and unrecoverable
errors. For a _recoverable error_, such as a _file not found_ error, we most
likely just want to report the problem to the user and retry the operation.
_Unrecoverable errors_ are always symptoms of bugs, such as trying to access a
location beyond the end of an array, and so we want to immediately stop the
program.
Most languages don’t distinguish between these two kinds of errors and handle
both in the same way, using mechanisms such as exceptions. Rust doesn’t have
exceptions. Instead, it has the type `Result<T, E>` for recoverable errors and
the `panic!` macro that stops execution when the program encounters an
unrecoverable error. This chapter covers calling `panic!` first and then talks
about returning `Result<T, E>` values. Additionally, we’ll explore
considerations when deciding whether to try to recover from an error or to stop
execution.


The Rust Programming Language › Unrecoverable Errors with `panic!`

Sometimes bad things happen in your code, and there’s nothing you can do about
it. In these cases, Rust has the `panic!` macro. There are two ways to cause a
panic in practice: by taking an action that causes our code to panic (such as
accessing an array past the end) or by explicitly calling the `panic!` macro.
In both cases, we cause a panic in our program. By default, these panics will
print a failure message, unwind, clean up the stack, and quit. Via an
environment variable, you can also have Rust display the call stack when a
panic occurs to make it easier to track down the source of the panic.


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

By default, when a panic occurs, the program starts _unwinding_, which means
Rust walks back up the stack and cleans up the data from each function it
encounters. However, walking back and cleaning up is a lot of work. Rust
therefore allows you to choose the alternative of immediately _aborting_,
which ends the program without cleaning up.
Memory that the program was using will then need to be cleaned up by the
operating system. If in your project you need to make the resultant binary as
small as possible, you can switch from unwinding to aborting upon a panic by
adding `panic = 'abort'` to the appropriate `[profile]` sections in your
_Cargo.toml_ file. For example, if you want to abort on panic in release mode,
add this:
```toml
[profile.release]
panic = 'abort'
```
Let’s try calling `panic!` in a simple program:
Listing (src/main.rs)
```rust,should_panic,panics
fn main() {
    panic!("crash and burn");
}
```
When you run the program, you’ll see something like this:
```console
$ cargo run
   Compiling panic v0.1.0 (file:///projects/panic)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
     Running `target/debug/panic`

thread 'main' (6018279) panicked at src/main.rs:2:5:
crash and burn
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
The call to `panic!` causes the error message contained in the last two lines.
The first line shows our panic message and the place in our source code where
the panic occurred: _src/main.rs:2:5_ indicates that it’s the second line,
fifth character of our _src/main.rs_ file.


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

In this case, the line indicated is part of our code, and if we go to that
line, we see the `panic!` macro call. In other cases, the `panic!` call might
be in code that our code calls, and the filename and line number reported by
the error message will be someone else’s code where the `panic!` macro is
called, not the line of our code that eventually led to the `panic!` call.
We can use the backtrace of the functions the `panic!` call came from to figure
out the part of our code that is causing the problem. To understand how to use
a `panic!` backtrace, let’s look at another example and see what it’s like when
a `panic!` call comes from a library because of a bug in our code instead of
from our code calling the macro directly. Listing 9-1 has some code that
attempts to access an index in a vector beyond the range of valid indexes.
Listing 9-1: Attempting to access an element beyond the end of a vector, which will cause a call to `panic!` (src/main.rs)
```rust,should_panic,panics
fn main() {
    let v = vec![1, 2, 3];

    v[99];
}
```
Here, we’re attempting to access the 100th element of our vector (which is at
index 99 because indexing starts at zero), but the vector has only three
elements. In this situation, Rust will panic. Using `[]` is supposed to return
an element, but if you pass an invalid index, there’s no element that Rust
could return here that would be correct.


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

In C, attempting to read beyond the end of a data structure is undefined
behavior. You might get whatever is at the location in memory that would
correspond to that element in the data structure, even though the memory
doesn’t belong to that structure. This is called a _buffer overread_ and can
lead to security vulnerabilities if an attacker is able to manipulate the index
in such a way as to read data they shouldn’t be allowed to that is stored after
the data structure.
To protect your program from this sort of vulnerability, if you try to read an
element at an index that doesn’t exist, Rust will stop execution and refuse to
continue. Let’s try it and see:
```console
$ cargo run
   Compiling panic v0.1.0 (file:///projects/panic)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s
     Running `target/debug/panic`

thread 'main' (6017887) panicked at src/main.rs:4:6:
index out of bounds: the len is 3 but the index is 99
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
This error points at line 4 of our _main.rs_ where we attempt to access index
99 of the vector in `v`.


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

The `note:` line tells us that we can set the `RUST_BACKTRACE` environment
variable to get a backtrace of exactly what happened to cause the error. A
_backtrace_ is a list of all the functions that have been called to get to this
point. Backtraces in Rust work as they do in other languages: The key to
reading the backtrace is to start from the top and read until you see files you
wrote. That’s the spot where the problem originated. The lines above that spot
are code that your code has called; the lines below are code that called your
code. These before-and-after lines might include core Rust code, standard
library code, or crates that you’re using. Let’s try to get a backtrace by
setting the `RUST_BACKTRACE` environment variable to any value except `0`.
Listing 9-2 shows output similar to what you’ll see.
Listing 9-2: The backtrace generated by a call to `panic!` displayed when the environment variable `RUST_BACKTRACE` is set


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

```console
$ RUST_BACKTRACE=1 cargo run
thread 'main' panicked at src/main.rs:4:6:
index out of bounds: the len is 3 but the index is 99
stack backtrace:
   0: rust_begin_unwind
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
   1: core::panicking::panic_fmt
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
   2: core::panicking::panic_bounds_check
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:273:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/core/src/slice/index.rs:274:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/core/src/slice/index.rs:16:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3361:9
   6: panic::main
             at ./src/main.rs:4:6
   7: core::ops::function::FnOnce::call_once
             at file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```


The Rust Programming Language › Unrecoverable Errors with `panic!` › Unwinding the Stack or Aborting in Response to a Panic

That’s a lot of output! The exact output you see might be different depending
on your operating system and Rust version. In order to get backtraces with this
information, debug symbols must be enabled. Debug symbols are enabled by
default when using `cargo build` or `cargo run` without the `--release` flag,
as we have here.
In the output in Listing 9-2, line 6 of the backtrace points to the line in our
project that’s causing the problem: line 4 of _src/main.rs_. If we don’t want
our program to panic, we should start our investigation at the location pointed
to by the first line mentioning a file we wrote. In Listing 9-1, where we
deliberately wrote code that would panic, the way to fix the panic is to not
request an element beyond the range of the vector indexes. When your code
panics in the future, you’ll need to figure out what action the code is taking
with what values to cause the panic and what the code should do instead.
We’ll come back to `panic!` and when we should and should not use `panic!` to
handle error conditions in the “To `panic!` or Not to
`panic!`” section later in this
chapter. Next, we’ll look at how to recover from an error using `Result`.


The Rust Programming Language › Recoverable Errors with `Result`

Most errors aren’t serious enough to require the program to stop entirely.
Sometimes when a function fails, it’s for a reason that you can easily interpret
and respond to. For example, if you try to open a file and that operation fails
because the file doesn’t exist, you might want to create the file instead of
terminating the process.
Recall from “Handling Potential Failure with `Result`”
 in Chapter 2 that the `Result` enum is defined as having two
variants, `Ok` and `Err`, as follows:
```rust
enum Result<T, E> {
    Ok(T),
    Err(E),
}
```
The `T` and `E` are generic type parameters: We’ll discuss generics in more
detail in Chapter 10. What you need to know right now is that `T` represents
the type of the value that will be returned in a success case within the `Ok`
variant, and `E` represents the type of the error that will be returned in a
failure case within the `Err` variant. Because `Result` has these generic type
parameters, we can use the `Result` type and the functions defined on it in
many different situations where the success value and error value we want to
return may differ.
Let’s call a function that returns a `Result` value because the function could
fail. In Listing 9-3, we try to open a file.
Listing 9-3: Opening a file (src/main.rs)
```rust
use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");
}
```


The Rust Programming Language › Recoverable Errors with `Result`

The return type of `File::open` is a `Result<T, E>`. The generic parameter `T`
has been filled in by the implementation of `File::open` with the type of the
success value, `std::fs::File`, which is a file handle. The type of `E` used in
the error value is `std::io::Error`. This return type means the call to
`File::open` might succeed and return a file handle that we can read from or
write to. The function call also might fail: For example, the file might not
exist, or we might not have permission to access the file. The `File::open`
function needs to have a way to tell us whether it succeeded or failed and at
the same time give us either the file handle or error information. This
information is exactly what the `Result` enum conveys.
In the case where `File::open` succeeds, the value in the variable
`greeting_file_result` will be an instance of `Ok` that contains a file handle.
In the case where it fails, the value in `greeting_file_result` will be an
instance of `Err` that contains more information about the kind of error that
occurred.
We need to add to the code in Listing 9-3 to take different actions depending
on the value `File::open` returns. Listing 9-4 shows one way to handle the
`Result` using a basic tool, the `match` expression that we discussed in
Chapter 6.
Listing 9-4: Using a `match` expression to handle the `Result` variants that might be returned (src/main.rs)


The Rust Programming Language › Recoverable Errors with `Result`

```rust,should_panic
use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {error:?}"),
    };
}
```
Note that, like the `Option` enum, the `Result` enum and its variants have been
brought into scope by the prelude, so we don’t need to specify `Result::`
before the `Ok` and `Err` variants in the `match` arms.
When the result is `Ok`, this code will return the inner `file` value out of
the `Ok` variant, and we then assign that file handle value to the variable
`greeting_file`. After the `match`, we can use the file handle for reading or
writing.
The other arm of the `match` handles the case where we get an `Err` value from
`File::open`. In this example, we’ve chosen to call the `panic!` macro. If
there’s no file named _hello.txt_ in our current directory and we run this
code, we’ll see the following output from the `panic!` macro:
```console
$ cargo run
   Compiling error-handling v0.1.0 (file:///projects/error-handling)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.73s
     Running `target/debug/error-handling`

thread 'main' (6018048) panicked at src/main.rs:8:23:
Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
As usual, this output tells us exactly what has gone wrong.


The Rust Programming Language › Recoverable Errors with `Result` › Matching on Different Errors

The code in Listing 9-4 will `panic!` no matter why `File::open` failed.
However, we want to take different actions for different failure reasons. If
`File::open` failed because the file doesn’t exist, we want to create the file
and return the handle to the new file. If `File::open` failed for any other
reason—for example, because we didn’t have permission to open the file—we still
want the code to `panic!` in the same way it did in Listing 9-4. For this, we
add an inner `match` expression, shown in Listing 9-5.
Listing 9-5: Handling different kinds of errors in different ways (src/main.rs)
```rust,ignore
use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {e:?}"),
            },
            _ => {
                panic!("Problem opening the file: {error:?}");
            }
        },
    };
}
```

Recoverable Errors with `Result`
Matching on Different Errors


The Rust Programming Language › Recoverable Errors with `Result` › Matching on Different Errors › Alternatives to Using `match` with `Result<T, E>`

The type of the value that `File::open` returns inside the `Err` variant is
`io::Error`, which is a struct provided by the standard library. This struct
has a method, `kind`, that we can call to get an `io::ErrorKind` value. The
enum `io::ErrorKind` is provided by the standard library and has variants
representing the different kinds of errors that might result from an `io`
operation. The variant we want to use is `ErrorKind::NotFound`, which indicates
the file we’re trying to open doesn’t exist yet. So, we match on
`greeting_file_result`, but we also have an inner match on `error.kind()`.
The condition we want to check in the inner match is whether the value returned
by `error.kind()` is the `NotFound` variant of the `ErrorKind` enum. If it is,
we try to create the file with `File::create`. However, because `File::create`
could also fail, we need a second arm in the inner `match` expression. When the
file can’t be created, a different error message is printed. The second arm of
the outer `match` stays the same, so the program panics on any error besides
the missing file error.
That’s a lot of `match`! The `match` expression is very useful but also very
much a primitive. In Chapter 13, you’ll learn about closures, which are used
with many of the methods defined on `Result<T, E>`. These methods can be more
concise than using `match` when handling `Result<T, E>` values in your code.
For example, here’s another way to write the same logic as shown in Listing
9-5, this time using closures and the `unwrap_or_else` method:


The Rust Programming Language › Recoverable Errors with `Result` › Matching on Different Errors › Shortcuts for Panic on Error

```rust,ignore
use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let greeting_file = File::open("hello.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {error:?}");
            })
        } else {
            panic!("Problem opening the file: {error:?}");
        }
    });
}
```
Although this code has the same behavior as Listing 9-5, it doesn’t contain
any `match` expressions and is cleaner to read. Come back to this example
after you’ve read Chapter 13 and look up the `unwrap_or_else` method in the
standard library documentation. Many more of these methods can clean up huge,
nested `match` expressions when you’re dealing with errors.
Using `match` works well enough, but it can be a bit verbose and doesn’t always
communicate intent well. The `Result<T, E>` type has many helper methods
defined on it to do various, more specific tasks. The `unwrap` method is a
shortcut method implemented just like the `match` expression we wrote in
Listing 9-4. If the `Result` value is the `Ok` variant, `unwrap` will return
the value inside the `Ok`. If the `Result` is the `Err` variant, `unwrap` will
call the `panic!` macro for us. Here is an example of `unwrap` in action:
Listing (src/main.rs)
```rust,should_panic
use std::fs::File;

fn main() {
    let greeting_file = File::open("hello.txt").unwrap();
}
```
If we run this code without a _hello.txt_ file, we’ll see an error message from
the `panic!` call that the `unwrap` method makes:

Recoverable Errors with `Result`
Matching on Different Errors
Shortcuts for Panic on Error


The Rust Programming Language › Recoverable Errors with `Result` › Matching on Different Errors › Shortcuts for Panic on Error

```text
thread 'main' panicked at src/main.rs:4:49:
called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }
```
Similarly, the `expect` method lets us also choose the `panic!` error message.
Using `expect` instead of `unwrap` and providing good error messages can convey
your intent and make tracking down the source of a panic easier. The syntax of
`expect` looks like this:
Listing (src/main.rs)
```rust,should_panic
use std::fs::File;

fn main() {
    let greeting_file = File::open("hello.txt")
        .expect("hello.txt should be included in this project");
}
```
We use `expect` in the same way as `unwrap`: to return the file handle or call
the `panic!` macro. The error message used by `expect` in its call to `panic!`
will be the parameter that we pass to `expect`, rather than the default
`panic!` message that `unwrap` uses. Here’s what it looks like:
```text
thread 'main' panicked at src/main.rs:5:10:
hello.txt should be included in this project: Os { code: 2, kind: NotFound, message: "No such file or directory" }
```
In production-quality code, most Rustaceans choose `expect` rather than
`unwrap` and give more context about why the operation is expected to always
succeed. That way, if your assumptions are ever proven wrong, you have more
information to use in debugging.


The Rust Programming Language › Recoverable Errors with `Result` › Propagating Errors

When a function’s implementation calls something that might fail, instead of
handling the error within the function itself, you can return the error to the
calling code so that it can decide what to do. This is known as _propagating_
the error and gives more control to the calling code, where there might be more
information or logic that dictates how the error should be handled than what
you have available in the context of your code.
For example, Listing 9-6 shows a function that reads a username from a file. If
the file doesn’t exist or can’t be read, this function will return those errors
to the code that called the function.
Listing 9-6: A function that returns errors to the calling code using `match` (src/main.rs)
```rust
use std::fs::File;
use std::io::{self, Read};

fn read_username_from_file() -> Result<String, io::Error> {
    let username_file_result = File::open("hello.txt");

    let mut username_file = match username_file_result {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut username = String::new();

    match username_file.read_to_string(&mut username) {
        Ok(_) => Ok(username),
        Err(e) => Err(e),
    }
}
```
This function can be written in a much shorter way, but we’re going to start by
doing a lot of it manually in order to explore error handling; at the end,
we’ll show the shorter way. Let’s look at the return type of the function
first: `Result<String, io::Error>`. This means the function is returning a
value of the type `Result<T, E>`, where the generic parameter `T` has been
filled in with the concrete type `String` and the generic type `E` has been
filled in with the concrete type `io::Error`.

Recoverable Errors with `Result`
Propagating Errors


The Rust Programming Language › Recoverable Errors with `Result` › Propagating Errors

If this function succeeds without any problems, the code that calls this
function will receive an `Ok` value that holds a `String`—the `username` that
this function read from the file. If this function encounters any problems, the
calling code will receive an `Err` value that holds an instance of `io::Error`
that contains more information about what the problems were. We chose
`io::Error` as the return type of this function because that happens to be the
type of the error value returned from both of the operations we’re calling in
this function’s body that might fail: the `File::open` function and the
`read_to_string` method.
The body of the function starts by calling the `File::open` function. Then, we
handle the `Result` value with a `match` similar to the `match` in Listing 9-4.
If `File::open` succeeds, the file handle in the pattern variable `file`
becomes the value in the mutable variable `username_file` and the function
continues. In the `Err` case, instead of calling `panic!`, we use the `return`
keyword to return early out of the function entirely and pass the error value
from `File::open`, now in the pattern variable `e`, back to the calling code as
this function’s error value.


The Rust Programming Language › Recoverable Errors with `Result` › Propagating Errors › The `?` Operator Shortcut

So, if we have a file handle in `username_file`, the function then creates a
new `String` in variable `username` and calls the `read_to_string` method on
the file handle in `username_file` to read the contents of the file into
`username`. The `read_to_string` method also returns a `Result` because it
might fail, even though `File::open` succeeded. So, we need another `match` to
handle that `Result`: If `read_to_string` succeeds, then our function has
succeeded, and we return the username from the file that’s now in `username`
wrapped in an `Ok`. If `read_to_string` fails, we return the error value in the
same way that we returned the error value in the `match` that handled the
return value of `File::open`. However, we don’t need to explicitly say
`return`, because this is the last expression in the function.
The code that calls this code will then handle getting either an `Ok` value
that contains a username or an `Err` value that contains an `io::Error`. It’s
up to the calling code to decide what to do with those values. If the calling
code gets an `Err` value, it could call `panic!` and crash the program, use a
default username, or look up the username from somewhere other than a file, for
example. We don’t have enough information on what the calling code is actually
trying to do, so we propagate all the success or error information upward for
it to handle appropriately.
This pattern of propagating errors is so common in Rust that Rust provides the
question mark operator `?` to make this easier.
Listing 9-7 shows an implementation of `read_username_from_file` that has the
same functionality as in Listing 9-6, but this implementation uses the `?`
operator.

Recoverable Errors with `Result`
Propagating Errors
The `?` Operator Shortcut