<buttonid="sidebar-toggle"class="icon-button"type="button"title="Toggle Table of Contents"aria-label="Toggle Table of Contents"aria-controls="sidebar">
<ahref="print.html"title="Print this book"aria-label="Print this book">
<iid="print-button"class="fa fa-print"></i>
</a>
</div>
</div>
<divid="search-wrapper"class="hidden">
<formid="searchbar-outer"class="searchbar-outer">
<inputtype="search"name="search"id="searchbar"name="searchbar"placeholder="Search this book ..."aria-controls="searchresults-outer"aria-describedby="searchresults-header">
<p>Now that you know a lot of Rust, you will be able to understand most things inside the standard library. The code inside it isn't so scary anymore. Let's take a look at some of the parts in it that we haven't learned yet. This tour will go over most parts of the standard library that you don't need to install Rust for. We will revisit a lot of items we already know so we can learn them with greater understanding.</p>
<p>One thing about arrays to note is that they don't implement <code>Iterator.</code>. That means that if you have an array, you can't use <code>for</code>. But you can use methods like <code>.iter()</code> on them. Or you can use <code>&</code> to get a slice. Actually, the compiler will tell you exactly that if you try to use <code>for</code>:</p>
<p>If you want to get variables from an array, you can put their names inside <code>[]</code> to destructure it. This is the same as using a tuple in <code>match</code> statements or to get variables from a struct.</p>
<p>This prints <code>\u{ccad} \u{cd98} \u{c608} \u{cc2c}</code>.</p>
<p>You can get a char from <code>u8</code> using the <code>From</code> trait, but for a <code>u32</code> you use <code>TryFrom</code> because it might not work. There are many more numbers in <code>u32</code> than characters in Unicode. We can see this with a simple demonstration.</p>
<pre><preclass="playground"><codeclass="language-rust">use std::convert::TryFrom; // You need to bring TryFrom in to use it
use rand::prelude::*; // We will use random numbers too
<p>So it's a good thing you need to use <code>TryFrom</code>.</p>
<p>Also, as of late August 2020 you can now get a <code>String</code> from a <code>char</code>. (<code>String</code> implements <code>From<char></code>) Just write <code>String::from()</code> and put a <code>char</code> inside.</p>
<p>There are a lot of math methods for these types, plus some others. Here are some of the most useful ones.</p>
<p><code>.checked_add()</code>, <code>.checked_sub()</code>, <code>.checked_mul()</code>, <code>.checked_div()</code>. These are good methods if you think you might get a number that won't fit into a type. They return an <code>Option</code> so you can safely check that your math works without making the program panic.</p>
<p>You'll notice that on the page for integers it says <code>rhs</code> a lot. This means "right hand side", which is the right hand side when you do some math. For example, in <code>5 + 6</code>, <code>5</code> is on the left and <code>6</code> is on the right, so it's the <code>rhs</code>. This is not a keyword, but you will see it a lot so it's good to know.</p>
<p>While we are on the subject, let's learn how to implement <code>Add</code>. After you implement <code>Add</code>, you can use <code>+</code> on a type that you create. You need to implement <code>Add</code> yourself because add can mean a lot of things. Here's the example in the standard library page:</p>
#[derive(Debug, Copy, Clone, PartialEq)] // PartialEq is probably the most important part here. You want to be able to compare numbers
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Self; // Remember, this is called an "associated type": a "type that goes together".
// In this case it's just another Point
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
<spanclass="boring">}
</span></code></pre></pre>
<p>Now let's implement <code>Add</code> for our own type. Let's imagine that we want to add two countries together so we can compare their economies. It looks like this:</p>
<pre><codeclass="language-text">In Nauru are 10670 people and a GDP of $160000000
In Nauru and Vanuatu are 318485 people and a GDP of $980000000
In Nauru and Vanuatu and Micronesia are 422953 people and a GDP of $1347000000
</code></pre>
<p>Later on in this code we could change <code>.fmt()</code> to display a number that is easier to read.</p>
<p>The three others are called <code>Sub</code>, <code>Mul</code>, and <code>Div</code>, and they are basically the same to implement. For <code>+=</code>, <code>-=</code>, <code>*=</code> and <code>/=</code>, just add <code>Assign</code>: <code>AddAssign</code>, <code>SubAssign</code>, <code>MulAssign</code>, and <code>DivAssign</code>. You can see the full list <ahref="https://doc.rust-lang.org/std/ops/index.html#structs">here</a>, because there are many more. <code>%</code> for example is called <code>Rem</code>, <code>-</code> is called <code>Neg</code>, and so on.</p>
<p><code>f32</code> and <code>f64</code> have a very large number of methods that you use when doing math. We won't look at those, but here are some methods that you might use. They are: <code>.floor()</code>, <code>.ceil()</code>, <code>.round()</code>, and <code>.trunc()</code>. All of these return an <code>f32</code> or <code>f64</code> that is like an integer, with only <code>0</code> after the period. They do this:</p>
<ul>
<li><code>.floor()</code>: gives you the next lowest integer.</li>
<li><code>.ceil()</code>: gives you the next highest integer.</li>
<li><code>.round()</code>: gives you a higher number if 0.5 or more, or the same number if less than 0.5. This is called rounding because it gives you a "round" number (a number that has a short, simple form).</li>
<li><code>.trunc()</code>: just cuts off the part after the period. Truncate means "to cut off".</li>
<pre><codeclass="language-text">For the number 9.1:
floor: 9
ceiling: 10
rounded: 9 // because less than 9.5
truncated: 9
For the number 100.7:
floor: 100
ceiling: 101
rounded: 101 // because more than 100.5
truncated: 100
For the number -1.1:
floor: -2
ceiling: -1
rounded: -1
truncated: -1
For the number -19.9:
floor: -20
ceiling: -19
rounded: -20
truncated: -19
</code></pre>
<p><code>f32</code> and <code>f64</code> have a method called <code>.max()</code> and <code>.min()</code> that gives you the higher or the lower of two numbers. (For other types you can just use <code>std::cmp::max</code> and <code>std::cmp::min</code>.) Here is a way to use this with <code>.fold()</code> to get the highest or lowest number. You can see again that <code>.fold()</code> isn't just for adding numbers.</p>
let maximum = my_vec.iter().fold(f64::MIN, |current_number, next_number| current_number.max(*next_number)); // Note: start with the lowest possible number for an f64.
let minimum = my_vec.iter().fold(f64::MAX, |current_number, next_number| current_number.min(*next_number)); // And here start with the highest possible number
<p>In Rust you can turn a <code>bool</code> into an integer if you want, because it's safe to do that. But you can't do it the other way around. As you can see, <code>true</code> turns to 1 and <code>false</code> turns to 0.</p>
<p>Vec has a lot of methods that we haven't looked at yet. Let's start with <code>.sort()</code>. <code>.sort()</code> is not surprising at all. It uses a <code>&mut self</code> to sort a vector.</p>
<p>This prints <code>[0, 0, 0, 0, 0, 80, 90, 100]</code>. But there is one more interesting way to sort called <code>.sort_unstable()</code>, and it is usually faster. It can be faster because it doesn't care about the order of numbers if they are the same number. In regular <code>.sort()</code>, you know that the last <code>0, 0, 0, 0, 0</code> will be in the same order after <code>.sort()</code>. But <code>.sort_unstable()</code> might move the last zero to index 0, then the third last zero to index 2, etc.</p>
<p><code>.dedup()</code> means "de-duplicate". It will remove items that are the same in a vector, but only if they are next to each other. This next code will not just print <code>"sun", "moon"</code>:</p>
<p>It only gets rid of "sun" next to the other "sun", then "moon" next to one "moon", and again with "moon" next to another "moon". The result is: <code>["sun", "moon", "sun", "moon"]</code>.</p>
<p>If you want to remove every duplicate, just <code>.sort()</code> first:</p>
<p>You will remember that a <code>String</code> is kind of like a <code>Vec</code>. It is so like a <code>Vec</code> that you can do a lot of the same methods. For example, you can start one with <code>String::with_capacity()</code>. You want that if you are always going to be pushing a <code>char</code> with <code>.push()</code> or pushing a <code>&str</code> with <code>.push_str()</code>. Here's an example of a <code>String</code> that has too many allocations.</p>
let mut capacity_counter = 0; // capacity starts at 0
for _ in 0..100_000 { // Do this 100,000 times
if push_string.capacity() != capacity_counter { // First check if capacity is different now
println!("{}", push_string.capacity()); // If it is, print it
capacity_counter = push_string.capacity(); // then update the counter
}
push_string.push_str("I'm getting pushed into the string!"); // and push this in every time
}
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">35
70
140
280
560
1120
2240
4480
8960
17920
35840
71680
143360
286720
573440
1146880
2293760
4587520
</code></pre>
<p>We had to reallocate (copy everything over) 18 times. But now we know the final capacity. So we'll give it the capacity right away, and we don't need to reallocate: just one <code>String</code> capacity is enough.</p>
let mut push_string = String::with_capacity(4587520); // We know the exact number. Some different big number could work too
let mut capacity_counter = 0;
for _ in 0..100_000 {
if push_string.capacity() != capacity_counter {
println!("{}", push_string.capacity());
capacity_counter = push_string.capacity();
}
push_string.push_str("I'm getting pushed into the string!");
}
}
</code></pre></pre>
<p>And this prints <code>4587520</code>. Perfect! We never had to allocate again.</p>
<p>Of course, the actual length is certainly smaller than this. If you try 100,001 times, 101,000 times, etc., it'll still say <code>4587520</code>. That's because each time the capacity is two times what it was before. We can shrink it though with <code>.shrink_to_fit()</code> (same as for a <code>Vec</code>). Our <code>String</code> is very large and we don't want to add anything more to it, so we can make it a bit smaller. But only do this if you are sure. Here is why:</p>
let mut push_string = String::with_capacity(4587520);
let mut capacity_counter = 0;
for _ in 0..100_000 {
if push_string.capacity() != capacity_counter {
println!("{}", push_string.capacity());
capacity_counter = push_string.capacity();
}
push_string.push_str("I'm getting pushed into the string!");
}
push_string.shrink_to_fit();
println!("{}", push_string.capacity());
push_string.push('a');
println!("{}", push_string.capacity());
push_string.shrink_to_fit();
println!("{}", push_string.capacity());
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">4587520
3500000
7000000
3500001
</code></pre>
<p>So first we had a size of <code>4587520</code>, but we weren't using it all. We used <code>.shrink_to_fit()</code> and got the size down to <code>3500000</code>. But then we forget that we needed to push an <code>a</code> on. When we did that, Rust saw that we needed more space and gave us double: now it's <code>7000000</code>. Whoops! So we did <code>.shrink_to_fit()</code> again and now it's back down to <code>3500001</code>.</p>
<p><code>.pop()</code> works for a <code>String</code>, just like for a <code>Vec</code>.</p>
<p>This prints <code>This string is a little bit hard to read.</code> because it starts from the last character.</p>
<p><code>.retain()</code> is a method that uses a closure, which is rare for <code>String</code>. It's just like <code>.filter()</code> for an iterator.</p>
<p><code>std::ffi</code> is the part of <code>std</code> that helps you use Rust with other languages or operating systems. It has types like <code>OsString</code> and <code>CString</code>, which are like <code>String</code> for the operating system or <code>String</code> for the language C. They each have their own <code>&str</code> type too: <code>OsStr</code> and <code>CStr</code>. <code>ffi</code> means "foreign function interface".</p>
<p>You can use <code>OsString</code> when you have to work with an operating system that doesn't have Unicode. All Rust strings are unicode, but not every operating system has it. Here is the simple English explanation from the standard library on why we have <code>OsString</code>:</p>
<p>So an <code>OsString</code> is made to be read by all of them.</p>
<p>You can do all the regular things with an <code>OsString</code> like <code>OsString::from("Write something here")</code>. It also has an interesting method called <code>.into_string()</code> that tries to make it into a regular <code>String</code>. It returns a <code>Result</code>, but the <code>Err</code> part is just the original <code>OsString</code>:</p>
<p>So if it doesn't work then you just get it back. You can't call <code>.unwrap()</code> because it will panic, but you can use <code>match</code> to get the <code>OsString</code> back. Let's test it out by calling methods that don't exist.</p>
<p><code>std::mem</code> has some pretty interesting methods. We saw some of them already, such as <code>.size_of()</code>, <code>.size_of_val()</code> and <code>.drop()</code>:</p>
let mut some_string = String::from("You can drop a String because it's on the heap");
mem::drop(some_string);
// some_string.clear(); If we did this it would panic
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">4
200
</code></pre>
<p>Here are some other methods in <code>mem</code>:</p>
<p><code>swap()</code>: with this you can change the values between two variables. You use a mutable reference for each to do it. This is helpful when you have two things you want to switch and Rust doesn't let you because of borrowing rules. Or just when you want to quickly switch two things.</p>
<p>So it just does a swap and then returns the other item. With this you replace the value with something else you put in. And since it returns the old value, so you should use it with <code>let</code>. Here's a quick example.</p>
<p>This prints <code>The city once called Constantinople is now called Istanbul.</code>.</p>
<p>One function called <code>.take()</code> is like <code>.replace()</code> but it leaves the default value in the item. You will remember that default values are usually things like 0, "", and so on. Here is the signature:</p>
<p>Of course, for your own type you can implement <code>Default</code> to whatever you want. Let's look at an example where we have a <code>Bank</code> and a <code>Robber</code>. Every time he robs the <code>Bank</code>, he gets the money at the desk. But the desk can take money from the back any time, so it always has 50. We will make our own type for this so it will always have 50. Here is how it works:</p>
<p>The standard library has a prelude too, which is why you don't have to write things like <code>use std::vec::Vec</code> to create a <code>Vec</code>. You can see all the items <ahref="https://doc.rust-lang.org/std/prelude/index.html#prelude-contents">here</a>, and will already know almost all of them:</p>
<ul>
<li><code>std::marker::{Copy, Send, Sized, Sync, Unpin}</code>. You haven't seen <code>Unpin</code> before, because it is used for almost every type (like <code>Sized</code>, which is also very common). To "pin" means to not let something move. In this case a <code>Pin</code> means that it can't move in memory, but most items have <code>Unpin</code> so you can. That's why functions like <code>std::mem::replace</code> work, because they aren't pinned.</li>
<li><code>std::borrow::ToOwned</code>. You saw this before a bit with <code>Cow</code>, which can take borrowed content and make it owned. It uses <code>.to_owned()</code> to do this. You can also use <code>.to_owned()</code> on a <code>&str</code> to get a <code>String</code>, and the same for other borrowed values.</li>
<li><code>std::iter::{Iterator, Extend, IntoIterator, DoubleEndedIterator, ExactSizeIterator}</code>. We used <code>.rev()</code> for an iterator before: this actually makes a <code>DoubleEndedIterator</code>. An <code>ExactSizeIterator</code> is just something like <code>0..10</code>: it already knows that it has a <code>.len()</code> of 10. Other iterators don't know their length for sure.</li>
<p>What if you don't want the prelude for some reason? Just add the attribute <code>#![no_implicit_prelude]</code>. Let's give it a try and watch the compiler complain:</p>
error[E0433]: failed to resolve: use of undeclared type or module `String`
--> src/main.rs:4:21
|
4 | let my_string = String::from("This won't work");
| ^^^^^^ use of undeclared type or module `String`
error: aborting due to 3 previous errors
</code></pre>
<p>So for this simple code you need to tell Rust to use the <code>extern</code> (external) crate called <code>std</code>, and then the items you want. Here is everything we have to do just to create a Vec and a String and print it:</p>
<p>And now it finally works, printing <code>[8, 9, 10], This won't work</code>. So you can see why Rust uses the prelude. But if you want, you don't need to use it. And you can even use <code>#![no_std]</code> (we saw this once) for when you can't even use something like stack memory. But most of the time you don't have to think about not using the prelude or <code>std</code> at all.</p>
<p>So why didn't we see the <code>extern</code> keyword before? It's because you don't need it that much anymore. Before, when bringing in an external crate you had to use it. So to use <code>rand</code> in the past, you had to write:</p>
<p>and then <code>use</code> statements for the mods, traits, etc. that you wanted to use. But the Rust compiler now doesn't need this help anymore - you can just use <code>use</code> and it knows where to find it. So you almost never need <code>extern crate</code> anymore, but in other people's Rust code you might still see it on the top.</p>
<p><code>std::time</code> is where you can get functions for time. (If you want even more functions, a crate like <code>chrono</code> can work.) The simplest function is just getting the system time with <code>Instant::now()</code>.</p>
<p>If you print it, you'll get something like this: <code>Instant { tv_sec: 2738771, tv_nsec: 685628140 }</code>. That's talking about seconds and nanoseconds, but it's not very useful. If you look at 2738771 seconds for example (written in August), it is 31.70 days. That doesn't have anything to do with the month or the day of the year. But the page on <code>Instant</code> tells us that it isn't supposed to be useful on its own. It says that it is "opaque and useful only with Duration." Opaque means "you can't figure it out", and duration means "how much time passed". So it's only useful when doing things like comparing times.</p>
<p>If you look at the traits on the left, one of them is <code>Sub<Instant></code>. That means we can use <code>-</code> to subtract one from another. And when we click on [src] to see what it does, it says:</p>
<p>So it takes an <code>Instant</code> and uses <code>.duration_since()</code> to give a <code>Duration</code>. Let's try printing that. We'll make two <code>Instant::now()</code>s right next to each other, then we'll make the program busy for a while. Then we'll make one more <code>Instant::now()</code>. Finally, we'll see how long it took.</p>
<p>So that's just over 1 microsecond vs. 683 microseconds. We can see that Rust did take some time to do it.</p>
<p>There is one fun thing we can do with just a single <code>Instant</code> though. We can turn it into a <code>String</code> with <code>format!("{:?}", Instant::now());</code>. It looks like this:</p>
<p>That prints something like <code>Instant { tv_sec: 2740773, tv_nsec: 632821036 }</code>. That's not useful, but if we use <code>.iter()</code> and <code>.rev()</code> and <code>.skip(2)</code>, we can skip the <code>}</code> and <code></code> at the end. We can use it to make a random number generator.</p>
<p>The function is called <code>bad_random_number</code> because it's not a very good random number generator. Rust has better crates that make random numbers with less code than <code>rand</code> like <code>fastrand</code>. But it's a good example of how you can use your imagination to do something with <code>Instant</code>.</p>
<p>When you have a thread, you can use <code>std::thread::sleep</code> to make it stop for a while. When you do this, you have to give it a duration. You don't have to make more than one thread to do this because every program is on at least one thread. <code>sleep</code> needs a <code>Duration</code> though, so it can know how long to sleep. You can pick the unit like this: <code>Duration::from_millis()</code>, <code>Duration::from_secs</code>, etc. Here's one example:</p>
<p>but the thread will do nothing for three seconds. You usually use <code>.sleep()</code> when you have many threads that need to try something a lot, like connecting. You don't want the thread to use your processor to try 100,000 times in a second when you just want it to check sometimes. So then you can set a <code>Duration</code>, and it will try to do its task every time it wakes up.</p>
<p>This macro is kind of like <code>todo!()</code> except it's for code that you will never do. Maybe you have a <code>match</code> in an enum that you know will never choose one of the arms, so the code can never be reached. If that's so, you can write <code>unreachable!()</code> so the compiler knows that it can ignore that part.</p>
<p>For example, let's say you have a program that writes something when you choose a place to live in. They are in Ukraine, and all of them are nice except Chernobyl. Your program doesn't let anyone choose Chernobyl, because it's not a good place to live right now. But the enum was made a long time ago in someone else's code, and you can't change it. So in the <code>match</code> arm you can use the macro here. It looks like this:</p>
Chernobyl, // Pretend we can't change the enum - Chernobyl will always be here
Odesa,
Dnipro,
}
fn choose_city(place: &UkrainePlaces) {
use UkrainePlaces::*;
match place {
Kiev => println!("You will live in Kiev"),
Kharkiv => println!("You will live in Kharkiv"),
Chernobyl => unreachable!(),
Odesa => println!("You will live in Odesa"),
Dnipro => println!("You will live in Dnipro"),
}
}
fn main() {
let user_input = UkrainePlaces::Kiev; // Pretend the user input is made from some other function. The user can't choose Chernobyl, no matter what
choose_city(&user_input);
}
</code></pre></pre>
<p>This will print <code>You will live in Kiev</code>.</p>
<p><code>unreachable!()</code> is also nice for you to read because it reminds you that some part of the code is unreachable. You have to be sure that the code is actually unreachable though. If the compiler ever calls <code>unreachable!()</code>, the program will panic.</p>
<p>Also, if you ever have unreachable code that the compiler knows about, it will tell you. Here is a quick example:</p>
<p>These four macros are kind of like <code>dbg!()</code> because you just put them in to give you debug information. But they don't take any variables - you just use them with the brackets and nothing else. They are easy to learn together:</p>
<ul>
<li><code>column!()</code> gives you the column where you wrote it,</li>
<li><code>line!()</code> gives you the line where you wrote it, and</li>
<li><code>module_path!()</code> gives you the module where it is.</li>
</ul>
<p>The next code shows all three in a simple example. We will pretend there is a lot more code (mods inside mods), because that is why we would want to use these macros. You can imagine a big Rust program over many mods and files.</p>
<pre><preclass="playground"><codeclass="language-rust">pub mod something {
<pre><codeclass="language-text">On line 20 we got the country Finland
The next country is Czechia on line 29 and column 9.
The last country is Portugal inside the module rust_book::something::third_mod
</code></pre>
<p><code>cfg!</code></p>
<p>We know that you can use attributes like <code>#[cfg(test)]</code> and <code>#[cfg(windows)]</code> to tell the compiler what to do in certain cases. When you have <code>test</code>, it will run the code when you run Rust under testing mode (if it's on your computer you type <code>cargo test</code>). And when you use <code>windows</code>, it will run the code if the user is using Windows. But maybe you just want to change one tiny bit of code depending on the operating system, etc. That's when this macro is useful. It returns a <code>bool</code>.</p>
<p>Now it will run differently depending on the configuration. If you just run the program, it will give you this:</p>
<pre><codeclass="language-text">Returning 5. This is not a test
This shouldn't run, returning 0.
</code></pre>
<p>But if you run it in test mode (<code>cargo test</code> for Rust on your computer), it will actually run the test. And because the test always returns 5 in this case, it will pass.</p>
<pre><codeclass="language-text">running 1 test
test testing::check_if_five ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out