rebuild GitHub Pages from generated-book

This commit is contained in:
Chris Krycho
2024-10-09 13:39:21 -06:00
parent a92b897ca0
commit de2ee83df0
37 changed files with 1292 additions and 1008 deletions

View File

@@ -211,7 +211,7 @@ it cant provide appropriate default behavior for you.</p>
libraries can implement <code>derive</code> for their own traits, making the list of
traits you can use <code>derive</code> with truly open-ended. Implementing <code>derive</code>
involves using a procedural macro, which is covered in the
<a href="ch20-06-macros.html#macros">“Macros”</a><!-- ignore --> section of Chapter 19.</p>
<a href="ch20-06-macros.html#macros">“Macros”</a><!-- ignore --> section of Chapter 20.</p>
<h3 id="debug-for-programmer-output"><a class="header" href="#debug-for-programmer-output"><code>Debug</code> for Programmer Output</a></h3>
<p>The <code>Debug</code> trait enables debug formatting in format strings, which you
indicate by adding <code>:?</code> within <code>{}</code> placeholders.</p>

View File

@@ -295,15 +295,17 @@ functional programming languages. In Chapter 14, well examine Cargo in more
depth and talk about best practices for sharing your libraries with others.
Chapter 15 discusses smart pointers that the standard library provides and the
traits that enable their functionality.</p>
<p>In Chapter 16, well walk through different models of concurrent programming
and talk about how Rust helps you to program in multiple threads fearlessly.
Chapter 17 looks at how Rust idioms compare to object-oriented programming
<p>In Chapter 16, well walk through different models of concurrent programming and
talk about how Rust helps you to program in multiple threads fearlessly. In
Chapter 17, we will build on that by exploring Rusts async and await syntax and
the lightweight concurrency model they support.</p>
<p>Chapter 18 looks at how Rust idioms compare to object-oriented programming
principles you might be familiar with.</p>
<p>Chapter 18 is a reference on patterns and pattern matching, which are powerful
ways of expressing ideas throughout Rust programs. Chapter 19 contains a
<p>Chapter 19 is a reference on patterns and pattern matching, which are powerful
ways of expressing ideas throughout Rust programs. Chapter 20 contains a
smorgasbord of advanced topics of interest, including unsafe Rust, macros, and
more about lifetimes, traits, types, functions, and closures.</p>
<p>In Chapter 20, well complete a project in which well implement a low-level
<p>In Chapter 21, well complete a project in which well implement a low-level
multithreaded web server!</p>
<p>Finally, some appendices contain useful information about the language in a
more reference-like format. Appendix A covers Rusts keywords, Appendix B

View File

@@ -274,7 +274,7 @@ screen. There are four important details to notice here.</p>
<p>First, Rust style is to indent with four spaces, not a tab.</p>
<p>Second, <code>println!</code> calls a Rust macro. If it had called a function instead, it
would be entered as <code>println</code> (without the <code>!</code>). Well discuss Rust macros in
more detail in Chapter 19. For now, you just need to know that using a <code>!</code>
more detail in Chapter 20. For now, you just need to know that using a <code>!</code>
means that youre calling a macro instead of a normal function and that macros
dont always follow the same rules as functions.</p>
<p>Third, you see the <code>"Hello, world!"</code> string. We pass this string as an argument

View File

@@ -261,7 +261,7 @@ fn main() {
println!("You guessed: {}", guess);
}</code></pre>
<figcaption>Listing 2-1: Code that gets a guess from the user and prints it</figcaption>
</figure>
</figure>
<p>This code contains a lot of information, so lets go over it line by line. To
obtain user input and then print the result as output, we need to bring the
<code>io</code> input/output library into scope. The <code>io</code> library comes from the standard
@@ -824,7 +824,7 @@ fits that arms pattern. Rust takes the value given to <code>match</code> and
through each arms pattern in turn. Patterns and the <code>match</code> construct are
powerful Rust features: they let you express a variety of situations your code
might encounter and they make sure you handle them all. These features will be
covered in detail in Chapter 6 and Chapter 18, respectively.</p>
covered in detail in Chapter 6 and Chapter 19, respectively.</p>
<p>Lets walk through an example with the <code>match</code> expression we use here. Say that
the user has guessed 50 and the randomly generated secret number this time is
38.</p>

View File

@@ -442,7 +442,9 @@ example, a function that takes a parameter of type <code>Color</code> cannot tak
<code>Point</code> as an argument, even though both types are made up of three <code>i32</code>
values. Otherwise, tuple struct instances are similar to tuples in that you can
destructure them into their individual pieces, and you can use a <code>.</code> followed
by the index to access an individual value.</p>
by the index to access an individual value. Unlike tuples, tuple structs
require you to name the type of the struct when you destructure them. For
example, we would write <code>let Point(x, y, z) = point</code>.</p>
<h3 id="unit-like-structs-without-any-fields"><a class="header" href="#unit-like-structs-without-any-fields">Unit-Like Structs Without Any Fields</a></h3>
<p>You can also define structs that dont have any fields! These are called
<em>unit-like structs</em> because they behave similarly to <code>()</code>, the unit type that

View File

@@ -407,7 +407,7 @@ the vector. Using an enum plus a <code>match</code> expression means that Rust w
at compile time that every possible case is handled, as discussed in Chapter 6.</p>
<p>If you dont know the exhaustive set of types a program will get at runtime to
store in a vector, the enum technique wont work. Instead, you can use a trait
object, which well cover in Chapter 17.</p>
object, which well cover in Chapter 18.</p>
<p>Now that weve discussed some of the most common ways to use vectors, be sure
to review <a href="../std/vec/struct.Vec.html">the API documentation</a><!-- ignore --> for all of the many
useful methods defined on <code>Vec&lt;T&gt;</code> by the standard library. For example, in

View File

@@ -699,7 +699,7 @@ fn main() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
allows the use of the <code>?</code> operator on <code>Result</code> values.</span></p>
<p>The <code>Box&lt;dyn Error&gt;</code> type is a <em>trait object</em>, which well talk about in the
<a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects that Allow for Values of Different
Types”</a><!-- ignore --> section in Chapter 17. For now, you can
Types”</a><!-- ignore --> section in Chapter 18. For now, you can
read <code>Box&lt;dyn Error&gt;</code> to mean “any kind of error.” Using <code>?</code> on a <code>Result</code>
value in a <code>main</code> function with the error type <code>Box&lt;dyn Error&gt;</code> is allowed
because it allows any <code>Err</code> value to be returned early. Even though the body of

View File

@@ -252,7 +252,7 @@ format.</li>
rather than checking for the problem at every step.</li>
<li>Theres not a good way to encode this information in the types you use. Well
work through an example of what we mean in the <a href="ch18-03-oo-design-patterns.html#encoding-states-and-behavior-as-types">“Encoding States and Behavior
as Types”</a><!-- ignore --> section of Chapter 17.</li>
as Types”</a><!-- ignore --> section of Chapter 18.</li>
</ul>
<p>If someone calls your code and passes in values that dont make sense, its
best to return an error if you can so the user of the library can decide what

View File

@@ -660,7 +660,7 @@ around how the <code>impl Trait</code> syntax is implemented in the compiler. We
how to write a function with this behavior in the <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects That
Allow for Values of Different
Types”</a><!--
ignore --> section of Chapter 17.</p>
ignore --> section of Chapter 18.</p>
<h3 id="using-trait-bounds-to-conditionally-implement-methods"><a class="header" href="#using-trait-bounds-to-conditionally-implement-methods">Using Trait Bounds to Conditionally Implement Methods</a></h3>
<p>By using a trait bound with an <code>impl</code> block that uses generic type parameters,
we can implement methods conditionally for types that implement the specified

View File

@@ -886,7 +886,7 @@ behavior the code needs. You learned how to use lifetime annotations to ensure
that this flexible code wont have any dangling references. And all of this
analysis happens at compile time, which doesnt affect runtime performance!</p>
<p>Believe it or not, there is much more to learn on the topics we discussed in
this chapter: Chapter 17 discusses trait objects, which are another way to use
this chapter: Chapter 18 discusses trait objects, which are another way to use
traits. There are also more complex scenarios involving lifetime annotations
that you will only need in very advanced scenarios; for those, you should read
the <a href="../reference/index.html">Rust Reference</a>. But next, youll learn how to write tests in

View File

@@ -213,7 +213,7 @@ background knowledge you need to understand a real-world project such as
<li>Writing tests (<a href="ch11-00-testing.html">Chapter 11</a><!-- ignore -->)</li>
</ul>
<p>Well also briefly introduce closures, iterators, and trait objects, which
<a href="ch13-00-functional-features.html">Chapter 13</a><!-- ignore --> and <a href="ch18-00-oop.html">Chapter 17</a><!-- ignore --> will
<a href="ch13-00-functional-features.html">Chapter 13</a><!-- ignore --> and <a href="ch18-00-oop.html">Chapter 18</a><!-- ignore --> will
cover in detail.</p>
</main>

View File

@@ -779,7 +779,7 @@ returned the unit type, <code>()</code>, and we keep that as the value returned
<code>Ok</code> case.</p>
<p>For the error type, we used the <em>trait object</em> <code>Box&lt;dyn Error&gt;</code> (and weve
brought <code>std::error::Error</code> into scope with a <code>use</code> statement at the top).
Well cover trait objects in <a href="ch18-00-oop.html">Chapter 17</a><!-- ignore -->. For now, just
Well cover trait objects in <a href="ch18-00-oop.html">Chapter 18</a><!-- ignore -->. For now, just
know that <code>Box&lt;dyn Error&gt;</code> means the function will return a type that
implements the <code>Error</code> trait, but we dont have to specify what particular type
the return value will be. This gives us flexibility to return error values that

View File

@@ -245,7 +245,7 @@ standard library. The definition of the trait looks like this:</p>
<span class="boring">}</span></code></pre></pre>
<p>Notice this definition uses some new syntax: <code>type Item</code> and <code>Self::Item</code>,
which are defining an <em>associated type</em> with this trait. Well talk about
associated types in depth in Chapter 19. For now, all you need to know is that
associated types in depth in Chapter 20. For now, all you need to know is that
this code says implementing the <code>Iterator</code> trait requires that you also define
an <code>Item</code> type, and this <code>Item</code> type is used in the return type of the <code>next</code>
method. In other words, the <code>Item</code> type will be the type returned from the

View File

@@ -246,7 +246,7 @@ errors that might occur and what conditions might cause those errors to be
returned can be helpful to callers so they can write code to handle the
different kinds of errors in different ways.</li>
<li><strong>Safety</strong>: If the function is <code>unsafe</code> to call (we discuss unsafety in
Chapter 19), there should be a section explaining why the function is unsafe
Chapter 20), there should be a section explaining why the function is unsafe
and covering the invariants that the function expects callers to uphold.</li>
</ul>
<p>Most documentation comments dont need all of these sections, but this is a

View File

@@ -203,10 +203,10 @@ time because the data is copied around on the stack. To improve performance in
this situation, we can store the large amount of data on the heap in a box.
Then, only the small amount of pointer data is copied around on the stack,
while the data it references stays in one place on the heap. The third case is
known as a <em>trait object</em>, and Chapter 17 devotes an entire section, <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using
known as a <em>trait object</em>, and Chapter 18 devotes an entire section, <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using
Trait Objects That Allow for Values of Different Types,”</a><!--
ignore --> just to that topic. So what you learn here youll apply again in
Chapter 17!</p>
Chapter 18!</p>
<h3 id="using-a-boxt-to-store-data-on-the-heap"><a class="header" href="#using-a-boxt-to-store-data-on-the-heap">Using a <code>Box&lt;T&gt;</code> to Store Data on the Heap</a></h3>
<p>Before we discuss the heap storage use case for <code>Box&lt;T&gt;</code>, well cover the
syntax and how to interact with values stored within a <code>Box&lt;T&gt;</code>.</p>
@@ -418,7 +418,7 @@ other special capabilities, like those well see with the other smart pointer
types. They also dont have the performance overhead that these special
capabilities incur, so they can be useful in cases like the cons list where the
indirection is the only feature we need. Well look at more use cases for boxes
in Chapter 17, too.</p>
in Chapter 18, too.</p>
<p>The <code>Box&lt;T&gt;</code> type is a smart pointer because it implements the <code>Deref</code> trait,
which allows <code>Box&lt;T&gt;</code> values to be treated like references. When a <code>Box&lt;T&gt;</code>
value goes out of scope, the heap data that the box is pointing to is cleaned

View File

@@ -360,7 +360,7 @@ impl&lt;T&gt; Deref for MyBox&lt;T&gt; {
<p>The <code>type Target = T;</code> syntax defines an associated type for the <code>Deref</code>
trait to use. Associated types are a slightly different way of declaring a
generic parameter, but you dont need to worry about them for now; well cover
them in more detail in Chapter 19.</p>
them in more detail in Chapter 20.</p>
<p>We fill in the body of the <code>deref</code> method with <code>&amp;self.0</code> so <code>deref</code> returns a
reference to the value we want to access with the <code>*</code> operator; recall from the
<a href="ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types">“Using Tuple Structs without Named Fields to Create Different

View File

@@ -187,7 +187,7 @@ action is disallowed by the borrowing rules. To mutate data, the pattern uses
<code>unsafe</code> code inside a data structure to bend Rusts usual rules that govern
mutation and borrowing. Unsafe code indicates to the compiler that were
checking the rules manually instead of relying on the compiler to check them
for us; we will discuss unsafe code more in Chapter 19.</p>
for us; we will discuss unsafe code more in Chapter 20.</p>
<p>We can use types that use the interior mutability pattern only when we can
ensure that the borrowing rules will be followed at runtime, even though the
compiler cant guarantee that. The <code>unsafe</code> code involved is then wrapped in a

View File

@@ -230,7 +230,7 @@ receiver. The abbreviations <code>tx</code> and <code>rx</code> are traditionall
for <em>transmitter</em> and <em>receiver</em> respectively, so we name our variables as such
to indicate each end. Were using a <code>let</code> statement with a pattern that
destructures the tuples; well discuss the use of patterns in <code>let</code> statements
and destructuring in Chapter 18. For now, know that using a <code>let</code> statement
and destructuring in Chapter 19. For now, know that using a <code>let</code> statement
this way is a convenient approach to extract the pieces of the tuple returned
by <code>mpsc::channel</code>.</p>
<p>Lets move the transmitting end into a spawned thread and have it send one

View File

@@ -203,7 +203,7 @@ this in Listing 16-14, we got the error <code>the trait Send is not implemented
compiled.</p>
<p>Any type composed entirely of <code>Send</code> types is automatically marked as <code>Send</code> as
well. Almost all primitive types are <code>Send</code>, aside from raw pointers, which
well discuss in Chapter 19.</p>
well discuss in Chapter 20.</p>
<h3 id="allowing-access-from-multiple-threads-with-sync"><a class="header" href="#allowing-access-from-multiple-threads-with-sync">Allowing Access from Multiple Threads with <code>Sync</code></a></h3>
<p>The <code>Sync</code> marker trait indicates that it is safe for the type implementing
<code>Sync</code> to be referenced from multiple threads. In other words, any type <code>T</code> is
@@ -223,14 +223,14 @@ also <code>Send</code> and <code>Sync</code>, we dont have to implement those
marker traits, they dont even have any methods to implement. Theyre just
useful for enforcing invariants related to concurrency.</p>
<p>Manually implementing these traits involves implementing unsafe Rust code.
Well talk about using unsafe Rust code in Chapter 19; for now, the important
Well talk about using unsafe Rust code in Chapter 20; for now, the important
information is that building new concurrent types not made up of <code>Send</code> and
<code>Sync</code> parts requires careful thought to uphold the safety guarantees. <a href="../nomicon/index.html">“The
Rustonomicon”</a> has more information about these guarantees and how to
uphold them.</p>
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
<p>This isnt the last youll see of concurrency in this book: the whole next
chapter focuses on async programming, and the project in Chapter 20 will use the
chapter focuses on async programming, and the project in Chapter 21 will use the
concepts in this chapter in a more realistic situation than the smaller examples
discussed here.</p>
<p>As mentioned earlier, because very little of how Rust handles concurrency is

View File

@@ -217,21 +217,23 @@ can define a struct <code>AveragedCollection</code> that has a field containing
of <code>i32</code> values. The struct can also have a field that contains the average of
the values in the vector, meaning the average doesnt have to be computed
on demand whenever anyone needs it. In other words, <code>AveragedCollection</code> will
cache the calculated average for us. Listing 17-1 has the definition of the
cache the calculated average for us. Listing 18-1 has the definition of the
<code>AveragedCollection</code> struct:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub struct AveragedCollection {
list: Vec&lt;i32&gt;,
average: f64,
}</code></pre>
<p><span class="caption">Listing 17-1: An <code>AveragedCollection</code> struct that
maintains a list of integers and the average of the items in the
collection</span></p>
<figcaption>Listing 18-1: Listing 18-1: An <code>AveragedCollection</code> struct that maintains a list of integers and the average of the items in the collection</figcaption>
</figure>
<p>The struct is marked <code>pub</code> so that other code can use it, but the fields within
the struct remain private. This is important in this case because we want to
ensure that whenever a value is added or removed from the list, the average is
also updated. We do this by implementing <code>add</code>, <code>remove</code>, and <code>average</code> methods
on the struct, as shown in Listing 17-2:</p>
on the struct, as shown in Listing 18-2:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust noplayground"><span class="boring">pub struct AveragedCollection {
</span><span class="boring"> list: Vec&lt;i32&gt;,
@@ -264,8 +266,8 @@ on the struct, as shown in Listing 17-2:</p>
self.average = total as f64 / self.list.len() as f64;
}
}</code></pre>
<p><span class="caption">Listing 17-2: Implementations of the public methods
<code>add</code>, <code>remove</code>, and <code>average</code> on <code>AveragedCollection</code></span></p>
<figcaption>Listing 18-2: Listing 18-2: Implementations of the public methods <code>add</code>, <code>remove</code>, and <code>average</code> on <code>AveragedCollection</code></figcaption>
</figure>
<p>The public methods <code>add</code>, <code>remove</code>, and <code>average</code> are the only ways to access
or modify data in an instance of <code>AveragedCollection</code>. When an item is added
to <code>list</code> using the <code>add</code> method or removed using the <code>remove</code> method, the

View File

@@ -221,7 +221,7 @@ implementing our specified trait and a table used to look up trait methods on
that type at runtime. We create a trait object by specifying some sort of
pointer, such as a <code>&amp;</code> reference or a <code>Box&lt;T&gt;</code> smart pointer, then the <code>dyn</code>
keyword, and then specifying the relevant trait. (Well talk about the reason
trait objects must use a pointer in Chapter 19 in the section <a href="ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait">“Dynamically
trait objects must use a pointer in Chapter 20 in the section <a href="ch20-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait">“Dynamically
Sized Types and the <code>Sized</code> Trait.”</a><!-- ignore -->) We can
use trait objects in place of a generic or concrete type. Wherever we use a
trait object, Rusts type system will ensure at compile time that any value
@@ -237,19 +237,22 @@ But trait objects differ from traditional objects in that we cant add data to
a trait object. Trait objects arent as generally useful as objects in other
languages: their specific purpose is to allow abstraction across common
behavior.</p>
<p>Listing 17-3 shows how to define a trait named <code>Draw</code> with one method named
<p>Listing 18-3 shows how to define a trait named <code>Draw</code> with one method named
<code>draw</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub trait Draw {
fn draw(&amp;self);
}</code></pre>
<p><span class="caption">Listing 17-3: Definition of the <code>Draw</code> trait</span></p>
<figcaption>Listing 18-3: Definition of the <code>Draw</code> trait</figcaption>
</figure>
<p>This syntax should look familiar from our discussions on how to define traits
in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named
in Chapter 10. Next comes some new syntax: Listing 18-4 defines a struct named
<code>Screen</code> that holds a vector named <code>components</code>. This vector is of type
<code>Box&lt;dyn Draw&gt;</code>, which is a trait object; its a stand-in for any type inside
a <code>Box</code> that implements the <code>Draw</code> trait.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub trait Draw {
</span><span class="boring"> fn draw(&amp;self);
</span><span class="boring">}
@@ -257,12 +260,12 @@ a <code>Box</code> that implements the <code>Draw</code> trait.</p>
</span>pub struct Screen {
pub components: Vec&lt;Box&lt;dyn Draw&gt;&gt;,
}</code></pre>
<p><span class="caption">Listing 17-4: Definition of the <code>Screen</code> struct with a
<code>components</code> field holding a vector of trait objects that implement the <code>Draw</code>
trait</span></p>
<figcaption>Listing 18-4: Definition of the <code>Screen</code> struct with a <code>components</code> field holding a vector of trait objects that implement the <code>Draw</code> trait</figcaption>
</figure>
<p>On the <code>Screen</code> struct, well define a method named <code>run</code> that will call the
<code>draw</code> method on each of its <code>components</code>, as shown in Listing 17-5:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<code>draw</code> method on each of its <code>components</code>, as shown in Listing 18-5:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub trait Draw {
</span><span class="boring"> fn draw(&amp;self);
</span><span class="boring">}
@@ -278,15 +281,16 @@ trait</span></p>
}
}
}</code></pre>
<p><span class="caption">Listing 17-5: A <code>run</code> method on <code>Screen</code> that calls the
<code>draw</code> method on each component</span></p>
<figcaption>Listing 18-5: A <code>run</code> method on <code>Screen</code> that calls the <code>draw</code> method on each component</figcaption>
</figure>
<p>This works differently from defining a struct that uses a generic type
parameter with trait bounds. A generic type parameter can only be substituted
with one concrete type at a time, whereas trait objects allow for multiple
concrete types to fill in for the trait object at runtime. For example, we
could have defined the <code>Screen</code> struct using a generic type and a trait bound
as in Listing 17-6:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
as in Listing 18-6:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub trait Draw {
</span><span class="boring"> fn draw(&amp;self);
</span><span class="boring">}
@@ -305,8 +309,8 @@ where
}
}
}</code></pre>
<p><span class="caption">Listing 17-6: An alternate implementation of the <code>Screen</code>
struct and its <code>run</code> method using generics and trait bounds</span></p>
<figcaption>Listing 18-6: An alternate implementation of the <code>Screen</code> struct and its <code>run</code> method using generics and trait bounds</figcaption>
</figure>
<p>This restricts us to a <code>Screen</code> instance that has a list of components all of
type <code>Button</code> or all of type <code>TextField</code>. If youll only ever have homogeneous
collections, using generics and trait bounds is preferable because the
@@ -320,8 +324,9 @@ runtime performance implications.</p>
<code>Button</code> type. Again, actually implementing a GUI library is beyond the scope
of this book, so the <code>draw</code> method wont have any useful implementation in its
body. To imagine what the implementation might look like, a <code>Button</code> struct
might have fields for <code>width</code>, <code>height</code>, and <code>label</code>, as shown in Listing 17-7:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
might have fields for <code>width</code>, <code>height</code>, and <code>label</code>, as shown in Listing 18-7:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub trait Draw {
</span><span class="boring"> fn draw(&amp;self);
</span><span class="boring">}
@@ -349,8 +354,8 @@ impl Draw for Button {
// code to actually draw a button
}
}</code></pre>
<p><span class="caption">Listing 17-7: A <code>Button</code> struct that implements the
<code>Draw</code> trait</span></p>
<figcaption>Listing 18-7: A <code>Button</code> struct that implements the <code>Draw</code> trait</figcaption>
</figure>
<p>The <code>width</code>, <code>height</code>, and <code>label</code> fields on <code>Button</code> will differ from the
fields on other components; for example, a <code>TextField</code> type might have those
same fields plus a <code>placeholder</code> field. Each of the types we want to draw on
@@ -362,8 +367,9 @@ happens when a user clicks the button. These kinds of methods wont apply to
types like <code>TextField</code>.</p>
<p>If someone using our library decides to implement a <code>SelectBox</code> struct that has
<code>width</code>, <code>height</code>, and <code>options</code> fields, they implement the <code>Draw</code> trait on the
<code>SelectBox</code> type as well, as shown in Listing 17-8:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<code>SelectBox</code> type as well, as shown in Listing 18-8:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore">use gui::Draw;
struct SelectBox {
@@ -379,14 +385,15 @@ impl Draw for SelectBox {
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<p><span class="caption">Listing 17-8: Another crate using <code>gui</code> and implementing
the <code>Draw</code> trait on a <code>SelectBox</code> struct</span></p>
<figcaption>Listing 18-8: Another crate using <code>gui</code> and implementing the <code>Draw</code> trait on a <code>SelectBox</code> struct</figcaption>
</figure>
<p>Our librarys user can now write their <code>main</code> function to create a <code>Screen</code>
instance. To the <code>Screen</code> instance, they can add a <code>SelectBox</code> and a <code>Button</code>
by putting each in a <code>Box&lt;T&gt;</code> to become a trait object. They can then call the
<code>run</code> method on the <code>Screen</code> instance, which will call <code>draw</code> on each of the
components. Listing 17-9 shows this implementation:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
components. Listing 18-9 shows this implementation:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore"><span class="boring">use gui::Draw;
</span><span class="boring">
</span><span class="boring">struct SelectBox {
@@ -425,8 +432,8 @@ fn main() {
screen.run();
}</code></pre>
<p><span class="caption">Listing 17-9: Using trait objects to store values of
different types that implement the same trait</span></p>
<figcaption>Listing 18-9: Using trait objects to store values of different types that implement the same trait</figcaption>
</figure>
<p>When we wrote the library, we didnt know that someone might add the
<code>SelectBox</code> type, but our <code>Screen</code> implementation was able to operate on the
new type and draw it because <code>SelectBox</code> implements the <code>Draw</code> trait, which
@@ -435,7 +442,7 @@ means it implements the <code>draw</code> method.</p>
rather than the values concrete type—is similar to the concept of <em>duck
typing</em> in dynamically typed languages: if it walks like a duck and quacks
like a duck, then it must be a duck! In the implementation of <code>run</code> on <code>Screen</code>
in Listing 17-5, <code>run</code> doesnt need to know what the concrete type of each
in Listing 18-5, <code>run</code> doesnt need to know what the concrete type of each
component is. It doesnt check whether a component is an instance of a <code>Button</code>
or a <code>SelectBox</code>, it just calls the <code>draw</code> method on the component. By
specifying <code>Box&lt;dyn Draw&gt;</code> as the type of the values in the <code>components</code>
@@ -446,9 +453,10 @@ similar to code using duck typing is that we never have to check whether a
value implements a particular method at runtime or worry about getting errors
if a value doesnt implement a method but we call it anyway. Rust wont compile
our code if the values dont implement the traits that the trait objects need.</p>
<p>For example, Listing 17-10 shows what happens if we try to create a <code>Screen</code>
<p>For example, Listing 18-10 shows what happens if we try to create a <code>Screen</code>
with a <code>String</code> as a component:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">use gui::Screen;
fn main() {
@@ -458,8 +466,8 @@ fn main() {
screen.run();
}</code></pre>
<p><span class="caption">Listing 17-10: Attempting to use a type that doesnt
implement the trait objects trait</span></p>
<figcaption>Listing 18-10: Attempting to use a type that doesnt implement the trait objects trait</figcaption>
</figure>
<p>Well get this error because <code>String</code> doesnt implement the <code>Draw</code> trait:</p>
<pre><code class="language-console">$ cargo run
Compiling gui v0.1.0 (file:///projects/gui)
@@ -497,8 +505,8 @@ runtime, Rust uses the pointers inside the trait object to know which method to
call. This lookup incurs a runtime cost that doesnt occur with static
dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a
methods code, which in turn prevents some optimizations. However, we did get
extra flexibility in the code that we wrote in Listing 17-5 and were able to
support in Listing 17-9, so its a trade-off to consider.</p>
extra flexibility in the code that we wrote in Listing 18-5 and were able to
support in Listing 18-9, so its a trade-off to consider.</p>
</main>

View File

@@ -212,10 +212,11 @@ accidentally be published.</li>
<p>Any other changes attempted on a post should have no effect. For example, if we
try to approve a draft blog post before weve requested a review, the post
should remain an unpublished draft.</p>
<p>Listing 17-11 shows this workflow in code form: this is an example usage of the
<p>Listing 18-11 shows this workflow in code form: this is an example usage of the
API well implement in a library crate named <code>blog</code>. This wont compile yet
because we havent implemented the <code>blog</code> crate.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">use blog::Post;
fn main() {
@@ -230,8 +231,8 @@ fn main() {
post.approve();
assert_eq!("I ate a salad for lunch today", post.content());
}</code></pre>
<p><span class="caption">Listing 17-11: Code that demonstrates the desired
behavior we want our <code>blog</code> crate to have</span></p>
<figcaption>Listing 18-11: Code that demonstrates the desired behavior we want our <code>blog</code> crate to have</figcaption>
</figure>
<p>We want to allow the user to create a new draft blog post with <code>Post::new</code>. We
want to allow text to be added to the blog post. If we try to get the posts
content immediately, before approval, we shouldnt get any text because the
@@ -255,13 +256,14 @@ make a mistake with the states, like publishing a post before its reviewed.</
<p>Lets get started on the implementation of the library! We know we need a
public <code>Post</code> struct that holds some content, so well start with the
definition of the struct and an associated public <code>new</code> function to create an
instance of <code>Post</code>, as shown in Listing 17-12. Well also make a private
instance of <code>Post</code>, as shown in Listing 18-12. Well also make a private
<code>State</code> trait that will define the behavior that all state objects for a <code>Post</code>
must have.</p>
<p>Then <code>Post</code> will hold a trait object of <code>Box&lt;dyn State&gt;</code> inside an <code>Option&lt;T&gt;</code>
in a private field named <code>state</code> to hold the state object. Youll see why the
<code>Option&lt;T&gt;</code> is necessary in a bit.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub struct Post {
state: Option&lt;Box&lt;dyn State&gt;&gt;,
content: String,
@@ -281,9 +283,8 @@ trait State {}
struct Draft {}
impl State for Draft {}</code></pre>
<p><span class="caption">Listing 17-12: Definition of a <code>Post</code> struct and a <code>new</code>
function that creates a new <code>Post</code> instance, a <code>State</code> trait, and a <code>Draft</code>
struct</span></p>
<figcaption>Listing 18-12: Definition of a <code>Post</code> struct and a <code>new</code> function that creates a new <code>Post</code> instance, a <code>State</code> trait, and a <code>Draft</code> struct</figcaption>
</figure>
<p>The <code>State</code> trait defines the behavior shared by different post states. The
state objects are <code>Draft</code>, <code>PendingReview</code>, and <code>Published</code>, and they will all
implement the <code>State</code> trait. For now, the trait doesnt have any methods, and
@@ -296,13 +297,13 @@ a draft. Because the <code>state</code> field of <code>Post</code> is private, t
create a <code>Post</code> in any other state! In the <code>Post::new</code> function, we set the
<code>content</code> field to a new, empty <code>String</code>.</p>
<h3 id="storing-the-text-of-the-post-content"><a class="header" href="#storing-the-text-of-the-post-content">Storing the Text of the Post Content</a></h3>
<p>We saw in Listing 17-11 that we want to be able to call a method named
<p>We saw in Listing 18-11 that we want to be able to call a method named
<code>add_text</code> and pass it a <code>&amp;str</code> that is then added as the text content of the
blog post. We implement this as a method, rather than exposing the <code>content</code>
field as <code>pub</code>, so that later we can implement a method that will control how
the <code>content</code> fields data is read. The <code>add_text</code> method is pretty
straightforward, so lets add the implementation in Listing 17-13 to the <code>impl Post</code> block:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
straightforward, so lets add the implementation in Listing 18-13 to the <code>impl Post</code> block:</p>
<figure class="listing">
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -327,8 +328,8 @@ straightforward, so lets add the implementation in Listing 17-13 to the <code
</span><span class="boring">struct Draft {}
</span><span class="boring">
</span><span class="boring">impl State for Draft {}</span></code></pre>
<p><span class="caption">Listing 17-13: Implementing the <code>add_text</code> method to add
text to a posts <code>content</code></span></p>
<figcaption>Listing 18-13: Implementing the <code>add_text</code> method to add text to a posts <code>content</code></figcaption>
</figure>
<p>The <code>add_text</code> method takes a mutable reference to <code>self</code>, because were
changing the <code>Post</code> instance that were calling <code>add_text</code> on. We then call
<code>push_str</code> on the <code>String</code> in <code>content</code> and pass the <code>text</code> argument to add to
@@ -339,13 +340,14 @@ support.</p>
<h3 id="ensuring-the-content-of-a-draft-post-is-empty"><a class="header" href="#ensuring-the-content-of-a-draft-post-is-empty">Ensuring the Content of a Draft Post Is Empty</a></h3>
<p>Even after weve called <code>add_text</code> and added some content to our post, we still
want the <code>content</code> method to return an empty string slice because the post is
still in the draft state, as shown on line 7 of Listing 17-11. For now, lets
still in the draft state, as shown on line 7 of Listing 18-11. For now, lets
implement the <code>content</code> method with the simplest thing that will fulfill this
requirement: always returning an empty string slice. Well change this later
once we implement the ability to change a posts state so it can be published.
So far, posts can only be in the draft state, so the post content should always
be empty. Listing 17-14 shows this placeholder implementation:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
be empty. Listing 18-14 shows this placeholder implementation:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -374,14 +376,15 @@ be empty. Listing 17-14 shows this placeholder implementation:</p>
</span><span class="boring">struct Draft {}
</span><span class="boring">
</span><span class="boring">impl State for Draft {}</span></code></pre>
<p><span class="caption">Listing 17-14: Adding a placeholder implementation for
the <code>content</code> method on <code>Post</code> that always returns an empty string slice</span></p>
<p>With this added <code>content</code> method, everything in Listing 17-11 up to line 7
<figcaption>Listing 18-14: Adding a placeholder implementation for the <code>content</code> method on <code>Post</code> that always returns an empty string slice</figcaption>
</figure>
<p>With this added <code>content</code> method, everything in Listing 18-11 up to line 7
works as intended.</p>
<h3 id="requesting-a-review-of-the-post-changes-its-state"><a class="header" href="#requesting-a-review-of-the-post-changes-its-state">Requesting a Review of the Post Changes Its State</a></h3>
<p>Next, we need to add functionality to request a review of a post, which should
change its state from <code>Draft</code> to <code>PendingReview</code>. Listing 17-15 shows this code:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
change its state from <code>Draft</code> to <code>PendingReview</code>. Listing 18-15 shows this code:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -430,8 +433,8 @@ impl State for PendingReview {
self
}
}</code></pre>
<p><span class="caption">Listing 17-15: Implementing <code>request_review</code> methods on
<code>Post</code> and the <code>State</code> trait</span></p>
<figcaption>Listing 18-15: Implementing <code>request_review</code> methods on <code>Post</code> and the <code>State</code> trait</figcaption>
</figure>
<p>We give <code>Post</code> a public method named <code>request_review</code> that will take a mutable
reference to <code>self</code>. Then we call an internal <code>request_review</code> method on the
current state of <code>Post</code>, and this second <code>request_review</code> method consumes the
@@ -466,14 +469,15 @@ state is responsible for its own rules.</p>
<p>Well leave the <code>content</code> method on <code>Post</code> as is, returning an empty string
slice. We can now have a <code>Post</code> in the <code>PendingReview</code> state as well as in the
<code>Draft</code> state, but we want the same behavior in the <code>PendingReview</code> state.
Listing 17-11 now works up to line 10!</p>
Listing 18-11 now works up to line 10!</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="adding-the-approve-method-that-changes-the-behavior-of-content"></a></p>
<h3 id="adding-approve-to-change-the-behavior-of-content"><a class="header" href="#adding-approve-to-change-the-behavior-of-content">Adding <code>approve</code> to Change the Behavior of <code>content</code></a></h3>
<p>The <code>approve</code> method will be similar to the <code>request_review</code> method: it will
set <code>state</code> to the value that the current state says it should have when that
state is approved, as shown in Listing 17-16:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
state is approved, as shown in Listing 18-16:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -551,8 +555,8 @@ impl State for Published {
self
}
}</code></pre>
<p><span class="caption">Listing 17-16: Implementing the <code>approve</code> method on
<code>Post</code> and the <code>State</code> trait</span></p>
<figcaption>Listing 18-16: Implementing the <code>approve</code> method on <code>Post</code> and the <code>State</code> trait</figcaption>
</figure>
<p>We add the <code>approve</code> method to the <code>State</code> trait and add a new struct that
implements <code>State</code>, the <code>Published</code> state.</p>
<p>Similar to the way <code>request_review</code> on <code>PendingReview</code> works, if we call the
@@ -565,8 +569,9 @@ state in those cases.</p>
<p>Now we need to update the <code>content</code> method on <code>Post</code>. We want the value
returned from <code>content</code> to depend on the current state of the <code>Post</code>, so were
going to have the <code>Post</code> delegate to a <code>content</code> method defined on its <code>state</code>,
as shown in Listing 17-17:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
as shown in Listing 18-17:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -643,8 +648,8 @@ as shown in Listing 17-17:</p>
</span><span class="boring"> self
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 17-17: Updating the <code>content</code> method on <code>Post</code> to
delegate to a <code>content</code> method on <code>State</code></span></p>
<figcaption>Listing 18-17: Updating the <code>content</code> method on <code>Post</code> to delegate to a <code>content</code> method on <code>State</code></figcaption>
</figure>
<p>Because the goal is to keep all these rules inside the structs that implement
<code>State</code>, we call a <code>content</code> method on the value in <code>state</code> and pass the post
instance (that is, <code>self</code>) as an argument. Then we return the value thats
@@ -665,8 +670,9 @@ will take effect on the <code>&amp;</code> and the <code>Box</code> so the <code
ultimately be called on the type that implements the <code>State</code> trait. That means
we need to add <code>content</code> to the <code>State</code> trait definition, and that is where
well put the logic for what content to return depending on which state we
have, as shown in Listing 17-18:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
have, as shown in Listing 18-18:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> state: Option&lt;Box&lt;dyn State&gt;&gt;,
</span><span class="boring"> content: String,
@@ -753,8 +759,8 @@ impl State for Published {
&amp;post.content
}
}</code></pre>
<p><span class="caption">Listing 17-18: Adding the <code>content</code> method to the <code>State</code>
trait</span></p>
<figcaption>Listing 18-18: Adding the <code>content</code> method to the <code>State</code> trait</figcaption>
</figure>
<p>We add a default implementation for the <code>content</code> method that returns an empty
string slice. That means we dont need to implement <code>content</code> on the <code>Draft</code>
and <code>PendingReview</code> structs. The <code>Published</code> struct will override the <code>content</code>
@@ -763,7 +769,7 @@ method and return the value in <code>post.content</code>.</p>
Chapter 10. Were taking a reference to a <code>post</code> as an argument and returning a
reference to part of that <code>post</code>, so the lifetime of the returned reference is
related to the lifetime of the <code>post</code> argument.</p>
<p>And were done—all of Listing 17-11 now works! Weve implemented the state
<p>And were done—all of Listing 18-11 now works! Weve implemented the state
pattern with the rules of the blog post workflow. The logic related to the
rules lives in the state objects rather than being scattered throughout <code>Post</code>.</p>
<section class="note" aria-role="note">
@@ -821,7 +827,7 @@ and <code>approve</code> methods on <code>Post</code>. Both methods delegate to
the same method on the value in the <code>state</code> field of <code>Option</code> and set the new
value of the <code>state</code> field to the result. If we had a lot of methods on <code>Post</code>
that followed this pattern, we might consider defining a macro to eliminate the
repetition (see the <a href="ch20-06-macros.html#macros">“Macros”</a><!-- ignore --> section in Chapter 19).</p>
repetition (see the <a href="ch20-06-macros.html#macros">“Macros”</a><!-- ignore --> section in Chapter 20).</p>
<p>By implementing the state pattern exactly as its defined for object-oriented
languages, were not taking as full advantage of Rusts strengths as we could.
Lets look at some changes we can make to the <code>blog</code> crate that can make
@@ -832,8 +838,9 @@ trade-offs. Rather than encapsulating the states and transitions completely so
outside code has no knowledge of them, well encode the states into different
types. Consequently, Rusts type checking system will prevent attempts to use
draft posts where only published posts are allowed by issuing a compiler error.</p>
<p>Lets consider the first part of <code>main</code> in Listing 17-11:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<p>Lets consider the first part of <code>main</code> in Listing 18-11:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore"><span class="boring">use blog::Post;
</span><span class="boring">
</span>fn main() {
@@ -848,6 +855,7 @@ draft posts where only published posts are allowed by issuing a compiler error.<
</span><span class="boring"> post.approve();
</span><span class="boring"> assert_eq!("I ate a salad for lunch today", post.content());
</span>}</code></pre>
</figure>
<p>We still enable the creation of new posts in the draft state using <code>Post::new</code>
and the ability to add text to the posts content. But instead of having a
<code>content</code> method on a draft post that returns an empty string, well make it so
@@ -855,9 +863,10 @@ draft posts dont have the <code>content</code> method at all. That way, if we
a draft posts content, well get a compiler error telling us the method
doesnt exist. As a result, it will be impossible for us to accidentally
display draft post content in production, because that code wont even compile.
Listing 17-19 shows the definition of a <code>Post</code> struct and a <code>DraftPost</code> struct,
Listing 18-19 shows the definition of a <code>Post</code> struct and a <code>DraftPost</code> struct,
as well as methods on each:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub struct Post {
content: String,
}
@@ -883,8 +892,8 @@ impl DraftPost {
self.content.push_str(text);
}
}</code></pre>
<p><span class="caption">Listing 17-19: A <code>Post</code> with a <code>content</code> method and a
<code>DraftPost</code> without a <code>content</code> method</span></p>
<figcaption>Listing 18-19: A <code>Post</code> with a <code>content</code> method and <code>DraftPost</code> without a <code>content</code> method</figcaption>
</figure>
<p>Both the <code>Post</code> and <code>DraftPost</code> structs have a private <code>content</code> field that
stores the blog post text. The structs no longer have the <code>state</code> field because
were moving the encoding of the state to the types of the structs. The <code>Post</code>
@@ -906,8 +915,9 @@ pending review state should still not display any content. Lets implement
these constraints by adding another struct, <code>PendingReviewPost</code>, defining the
<code>request_review</code> method on <code>DraftPost</code> to return a <code>PendingReviewPost</code>, and
defining an <code>approve</code> method on <code>PendingReviewPost</code> to return a <code>Post</code>, as
shown in Listing 17-20:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
shown in Listing 18-20:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct Post {
</span><span class="boring"> content: String,
</span><span class="boring">}
@@ -952,9 +962,8 @@ impl PendingReviewPost {
}
}
}</code></pre>
<p><span class="caption">Listing 17-20: A <code>PendingReviewPost</code> that gets created by
calling <code>request_review</code> on <code>DraftPost</code> and an <code>approve</code> method that turns a
<code>PendingReviewPost</code> into a published <code>Post</code></span></p>
<figcaption>Listing 18-20: A <code>PendingReviewPost</code> that gets created by calling <code>request_review</code> on <code>DraftPost</code> and an <code>approve</code> method that turns a <code>PendingReviewPost</code> into a published <code>Post</code></figcaption>
</figure>
<p>The <code>request_review</code> and <code>approve</code> methods take ownership of <code>self</code>, thus
consuming the <code>DraftPost</code> and <code>PendingReviewPost</code> instances and transforming
them into a <code>PendingReviewPost</code> and a published <code>Post</code>, respectively. This way,
@@ -972,8 +981,9 @@ called on, so we need to add more <code>let post =</code> shadowing assignments
the returned instances. We also cant have the assertions about the draft and
pending review posts contents be empty strings, nor do we need them: we cant
compile code that tries to use the content of posts in those states any longer.
The updated code in <code>main</code> is shown in Listing 17-21:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
The updated code in <code>main</code> is shown in Listing 18-21:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore">use blog::Post;
fn main() {
@@ -987,8 +997,8 @@ fn main() {
assert_eq!("I ate a salad for lunch today", post.content());
}</code></pre>
<p><span class="caption">Listing 17-21: Modifications to <code>main</code> to use the new
implementation of the blog post workflow</span></p>
<figcaption>Listing 18-21: Modifications to <code>main</code> to use the new implementation of the blog post workflow</figcaption>
</figure>
<p>The changes we needed to make to <code>main</code> to reassign <code>post</code> mean that this
implementation doesnt quite follow the object-oriented state pattern anymore:
the transformations between the states are no longer encapsulated entirely
@@ -997,7 +1007,7 @@ now impossible because of the type system and the type checking that happens at
compile time! This ensures that certain bugs, such as display of the content of
an unpublished post, will be discovered before they make it to production.</p>
<p>Try the tasks suggested at the start of this section on the <code>blog</code> crate as it
is after Listing 17-21 to see what you think about the design of this version
is after Listing 18-21 to see what you think about the design of this version
of the code. Note that some of the tasks might be completed already in this
design.</p>
<p>Weve seen that even though Rust is capable of implementing object-oriented

View File

@@ -219,14 +219,15 @@ chapter.</p>
way to write the equivalent of a <code>match</code> that only matches one case.
Optionally, <code>if let</code> can have a corresponding <code>else</code> containing code to run if
the pattern in the <code>if let</code> doesnt match.</p>
<p>Listing 18-1 shows that its also possible to mix and match <code>if let</code>, <code>else if</code>, and <code>else if let</code> expressions. Doing so gives us more flexibility than a
<p>Listing 19-1 shows that its also possible to mix and match <code>if let</code>, <code>else if</code>, and <code>else if let</code> expressions. Doing so gives us more flexibility than a
<code>match</code> expression in which we can express only one value to compare with the
patterns. Also, Rust doesnt require that the conditions in a series of <code>if let</code>, <code>else if</code>, <code>else if let</code> arms relate to each other.</p>
<p>The code in Listing 18-1 determines what color to make your background based on
<p>The code in Listing 19-1 determines what color to make your background based on
a series of checks for several conditions. For this example, weve created
variables with hardcoded values that a real program might receive from user
input.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
let favorite_color: Option&lt;&amp;str&gt; = None;
let is_tuesday = false;
@@ -246,8 +247,8 @@ input.</p>
println!("Using blue as the background color");
}
}</code></pre></pre>
<p><span class="caption">Listing 18-1: Mixing <code>if let</code>, <code>else if</code>, <code>else if let</code>,
and <code>else</code></span></p>
<figcaption>Listing 19-1: Mixing <code>if let</code>, <code>else if</code>, <code>else if let</code>, and <code>else</code></figcaption>
</figure>
<p>If the user specifies a favorite color, that color is used as the background.
If no favorite color is specified and today is Tuesday, the background color is
green. Otherwise, if the user specifies their age as a string and we can parse
@@ -270,8 +271,9 @@ not alert us to the possible logic bug.</p>
<h3 id="while-let-conditional-loops"><a class="header" href="#while-let-conditional-loops"><code>while let</code> Conditional Loops</a></h3>
<p>Similar in construction to <code>if let</code>, the <code>while let</code> conditional loop allows a
<code>while</code> loop to run for as long as a pattern continues to match. In Listing
18-2 we code a <code>while let</code> loop that uses a vector as a stack and prints the
19-2 we code a <code>while let</code> loop that uses a vector as a stack and prints the
values in the vector in the opposite order in which they were pushed.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let mut stack = Vec::new();
@@ -283,8 +285,8 @@ values in the vector in the opposite order in which they were pushed.</p>
println!("{top}");
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-2: Using a <code>while let</code> loop to print values
for as long as <code>stack.pop()</code> returns <code>Some</code></span></p>
<figcaption>Listing 19-2: Using a <code>while let</code> loop to print values for as long as <code>stack.pop()</code> returns <code>Some</code></figcaption>
</figure>
<p>This example prints 3, 2, and then 1. The <code>pop</code> method takes the last element
out of the vector and returns <code>Some(value)</code>. If the vector is empty, <code>pop</code>
returns <code>None</code>. The <code>while</code> loop continues running the code in its block as
@@ -292,9 +294,10 @@ long as <code>pop</code> returns <code>Some</code>. When <code>pop</code> return
use <code>while let</code> to pop every element off our stack.</p>
<h3 id="for-loops"><a class="header" href="#for-loops"><code>for</code> Loops</a></h3>
<p>In a <code>for</code> loop, the value that directly follows the keyword <code>for</code> is a
pattern. For example, in <code>for x in y</code> the <code>x</code> is the pattern. Listing 18-3
pattern. For example, in <code>for x in y</code> the <code>x</code> is the pattern. Listing 19-3
demonstrates how to use a pattern in a <code>for</code> loop to destructure, or break
apart, a tuple as part of the <code>for</code> loop.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let v = vec!['a', 'b', 'c'];
@@ -302,9 +305,9 @@ apart, a tuple as part of the <code>for</code> loop.</p>
println!("{value} is at index {index}");
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-3: Using a pattern in a <code>for</code> loop to
destructure a tuple</span></p>
<p>The code in Listing 18-3 will print the following:</p>
<figcaption>Listing 19-3: Using a pattern in a <code>for</code> loop to destructure a tuple</figcaption>
</figure>
<p>The code in Listing 19-3 will print the following:</p>
<pre><code class="language-console">$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
@@ -339,25 +342,27 @@ the expression against the pattern and assigns any names it finds. So in the
the variable <code>x</code>.” Because the name <code>x</code> is the whole pattern, this pattern
effectively means “bind everything to the variable <code>x</code>, whatever the value is.”</p>
<p>To see the pattern matching aspect of <code>let</code> more clearly, consider Listing
18-4, which uses a pattern with <code>let</code> to destructure a tuple.</p>
19-4, which uses a pattern with <code>let</code> to destructure a tuple.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let (x, y, z) = (1, 2, 3);
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-4: Using a pattern to destructure a tuple and
create three variables at once</span></p>
<figcaption>Listing 19-4: Using a pattern to destructure a tuple and create three variables at once</figcaption>
</figure>
<p>Here, we match a tuple against a pattern. Rust compares the value <code>(1, 2, 3)</code>
to the pattern <code>(x, y, z)</code> and sees that the value matches the pattern, so Rust
binds <code>1</code> to <code>x</code>, <code>2</code> to <code>y</code>, and <code>3</code> to <code>z</code>. You can think of this tuple
pattern as nesting three individual variable patterns inside it.</p>
<p>If the number of elements in the pattern doesnt match the number of elements
in the tuple, the overall type wont match and well get a compiler error. For
example, Listing 18-5 shows an attempt to destructure a tuple with three
example, Listing 19-5 shows an attempt to destructure a tuple with three
elements into two variables, which wont work.</p>
<figure class="listing">
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span> let (x, y) = (1, 2, 3);
<span class="boring">}</span></code></pre>
<p><span class="caption">Listing 18-5: Incorrectly constructing a pattern whose
variables dont match the number of elements in the tuple</span></p>
<figcaption>Listing 19-5: Incorrectly constructing a pattern whose variables dont match the number of elements in the tuple</figcaption>
</figure>
<p>Attempting to compile this code results in this type error:</p>
<pre><code class="language-console">$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
@@ -382,20 +387,22 @@ is that we have too many variables in the pattern, the solution is to make the
types match by removing variables so the number of variables equals the number
of elements in the tuple.</p>
<h3 id="function-parameters"><a class="header" href="#function-parameters">Function Parameters</a></h3>
<p>Function parameters can also be patterns. The code in Listing 18-6, which
<p>Function parameters can also be patterns. The code in Listing 19-6, which
declares a function named <code>foo</code> that takes one parameter named <code>x</code> of type
<code>i32</code>, should by now look familiar.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021">fn foo(x: i32) {
// code goes here
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre></pre>
<p><span class="caption">Listing 18-6: A function signature uses patterns in the
parameters</span></p>
<figcaption>Listing 19-6: A function signature uses patterns in the parameters</figcaption>
</figure>
<p>The <code>x</code> part is a pattern! As we did with <code>let</code>, we could match a tuple in a
functions arguments to the pattern. Listing 18-7 splits the values in a tuple
functions arguments to the pattern. Listing 19-7 splits the values in a tuple
as we pass it to a function.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn print_coordinates(&amp;(x, y): &amp;(i32, i32)) {
println!("Current location: ({x}, {y})");
}
@@ -404,8 +411,8 @@ fn main() {
let point = (3, 5);
print_coordinates(&amp;point);
}</code></pre></pre>
<p><span class="caption">Listing 18-7: A function with parameters that destructure
a tuple</span></p>
<figcaption>Listing 19-7: A function with parameters that destructure a tuple</figcaption>
</figure>
<p>This code prints <code>Current location: (3, 5)</code>. The values <code>&amp;(3, 5)</code> match the
pattern <code>&amp;(x, y)</code>, so <code>x</code> is the value <code>3</code> and <code>y</code> is the value <code>5</code>.</p>
<p>We can also use patterns in closure parameter lists in the same way as in

View File

@@ -200,15 +200,16 @@ of refutability so you can respond when you see it in an error message. In
those cases, youll need to change either the pattern or the construct youre
using the pattern with, depending on the intended behavior of the code.</p>
<p>Lets look at an example of what happens when we try to use a refutable pattern
where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a
where Rust requires an irrefutable pattern and vice versa. Listing 19-8 shows a
<code>let</code> statement, but for the pattern weve specified <code>Some(x)</code>, a refutable
pattern. As you might expect, this code will not compile.</p>
<figure class="listing">
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span><span class="boring"> let some_option_value: Option&lt;i32&gt; = None;
</span> let Some(x) = some_option_value;
<span class="boring">}</span></code></pre>
<p><span class="caption">Listing 18-8: Attempting to use a refutable pattern with
<code>let</code></span></p>
<figcaption>Listing 19-8: Attempting to use a refutable pattern with <code>let</code></figcaption>
</figure>
<p>If <code>some_option_value</code> was a <code>None</code> value, it would fail to match the pattern
<code>Some(x)</code>, meaning the pattern is refutable. However, the <code>let</code> statement can
only accept an irrefutable pattern because there is nothing valid the code can
@@ -223,7 +224,7 @@ error[E0005]: refutable pattern in local binding
| ^^^^^^^ pattern `None` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
= note: the matched value is of type `Option&lt;i32&gt;`
help: you might want to use `let else` to handle the variant that isn't matched
|
@@ -239,26 +240,28 @@ pattern <code>Some(x)</code>, Rust rightfully produces a compiler error.</p>
fix it by changing the code that uses the pattern: instead of using <code>let</code>, we
can use <code>if let</code>. Then if the pattern doesnt match, the code will just skip
the code in the curly brackets, giving it a way to continue validly. Listing
18-9 shows how to fix the code in Listing 18-8.</p>
19-9 shows how to fix the code in Listing 19-8.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span><span class="boring"> let some_option_value: Option&lt;i32&gt; = None;
</span> if let Some(x) = some_option_value {
println!("{x}");
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-9: Using <code>if let</code> and a block with refutable
patterns instead of <code>let</code></span></p>
<figcaption>Listing 19-9: Using <code>if let</code> and a block with refutable patterns instead of <code>let</code></figcaption>
</figure>
<p>Weve given the code an out! This code is perfectly valid now. However,
if we give <code>if let</code> an irrefutable pattern (a pattern that will always
match), such as <code>x</code>, as shown in Listing 18-10, the compiler will give a
match), such as <code>x</code>, as shown in Listing 19-10, the compiler will give a
warning.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> if let x = 5 {
println!("{x}");
};
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-10: Attempting to use an irrefutable pattern
with <code>if let</code></span></p>
<figcaption>Listing 19-10: Attempting to use an irrefutable pattern with <code>if let</code></figcaption>
</figure>
<p>Rust complains that it doesnt make sense to use <code>if let</code> with an irrefutable
pattern:</p>
<pre><code class="language-console">$ cargo run

View File

@@ -205,12 +205,13 @@ them many times in the book. However, there is a complication when you use
named variables in <code>match</code> expressions. Because <code>match</code> starts a new scope,
variables declared as part of a pattern inside the <code>match</code> expression will
shadow those with the same name outside the <code>match</code> construct, as is the case
with all variables. In Listing 18-11, we declare a variable named <code>x</code> with the
with all variables. In Listing 19-11, we declare a variable named <code>x</code> with the
value <code>Some(5)</code> and a variable <code>y</code> with the value <code>10</code>. We then create a
<code>match</code> expression on the value <code>x</code>. Look at the patterns in the match arms and
<code>println!</code> at the end, and try to figure out what the code will print before
running this code or reading further.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let x = Some(5);
let y = 10;
@@ -223,8 +224,8 @@ running this code or reading further.</p>
println!("at the end: x = {x:?}, y = {y}");
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-11: A <code>match</code> expression with an arm that
introduces a shadowed variable <code>y</code></span></p>
<figcaption>Listing 19-11: A <code>match</code> expression with an arm that introduces a shadowed variable <code>y</code></figcaption>
</figure>
<p>Lets walk through what happens when the <code>match</code> expression runs. The pattern
in the first match arm doesnt match the defined value of <code>x</code>, so the code
continues.</p>
@@ -298,9 +299,10 @@ numeric values, ranges are only allowed with numeric or <code>char</code> values
<p>We can also use patterns to destructure structs, enums, and tuples to use
different parts of these values. Lets walk through each value.</p>
<h4 id="destructuring-structs"><a class="header" href="#destructuring-structs">Destructuring Structs</a></h4>
<p>Listing 18-12 shows a <code>Point</code> struct with two fields, <code>x</code> and <code>y</code>, that we can
<p>Listing 19-12 shows a <code>Point</code> struct with two fields, <code>x</code> and <code>y</code>, that we can
break apart using a pattern with a <code>let</code> statement.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">struct Point {
x: i32,
y: i32,
@@ -313,8 +315,8 @@ fn main() {
assert_eq!(0, a);
assert_eq!(7, b);
}</code></pre></pre>
<p><span class="caption">Listing 18-12: Destructuring a structs fields into
separate variables</span></p>
<figcaption>Listing 19-12: Destructuring a structs fields into separate variables</figcaption>
</figure>
<p>This code creates the variables <code>a</code> and <code>b</code> that match the values of the <code>x</code>
and <code>y</code> fields of the <code>p</code> struct. This example shows that the names of the
variables in the pattern dont have to match the field names of the struct.
@@ -323,10 +325,11 @@ easier to remember which variables came from which fields. Because of this
common usage, and because writing <code>let Point { x: x, y: y } = p;</code> contains a
lot of duplication, Rust has a shorthand for patterns that match struct fields:
you only need to list the name of the struct field, and the variables created
from the pattern will have the same names. Listing 18-13 behaves in the same
way as the code in Listing 18-12, but the variables created in the <code>let</code>
from the pattern will have the same names. Listing 19-13 behaves in the same
way as the code in Listing 19-12, but the variables created in the <code>let</code>
pattern are <code>x</code> and <code>y</code> instead of <code>a</code> and <code>b</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">struct Point {
x: i32,
y: i32,
@@ -339,8 +342,8 @@ fn main() {
assert_eq!(0, x);
assert_eq!(7, y);
}</code></pre></pre>
<p><span class="caption">Listing 18-13: Destructuring struct fields using struct
field shorthand</span></p>
<figcaption>Listing 19-13: Destructuring struct fields using struct field shorthand</figcaption>
</figure>
<p>This code creates the variables <code>x</code> and <code>y</code> that match the <code>x</code> and <code>y</code> fields
of the <code>p</code> variable. The outcome is that the variables <code>x</code> and <code>y</code> contain the
values from the <code>p</code> struct.</p>
@@ -348,10 +351,11 @@ values from the <code>p</code> struct.</p>
rather than creating variables for all the fields. Doing so allows us to test
some of the fields for particular values while creating variables to
destructure the other fields.</p>
<p>In Listing 18-14, we have a <code>match</code> expression that separates <code>Point</code> values
<p>In Listing 19-14, we have a <code>match</code> expression that separates <code>Point</code> values
into three cases: points that lie directly on the <code>x</code> axis (which is true when
<code>y = 0</code>), on the <code>y</code> axis (<code>x = 0</code>), or neither.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">struct Point {
</span><span class="boring"> x: i32,
</span><span class="boring"> y: i32,
@@ -368,8 +372,8 @@ into three cases: points that lie directly on the <code>x</code> axis (which is
}
}
}</code></pre></pre>
<p><span class="caption">Listing 18-14: Destructuring and matching literal values
in one pattern</span></p>
<figcaption>Listing 19-14: Destructuring and matching literal values in one pattern</figcaption>
</figure>
<p>The first arm will match any point that lies on the <code>x</code> axis by specifying that
the <code>y</code> field matches if its value matches the literal <code>0</code>. The pattern still
creates an <code>x</code> variable that we can use in the code for this arm.</p>
@@ -386,9 +390,10 @@ and the <code>y</code> axis, this code would only print <code>On the x axis at 0
<p>Weve destructured enums in this book (for example, Listing 6-5 in Chapter 6),
but havent yet explicitly discussed that the pattern to destructure an enum
corresponds to the way the data stored within the enum is defined. As an
example, in Listing 18-15 we use the <code>Message</code> enum from Listing 6-2 and write
example, in Listing 19-15 we use the <code>Message</code> enum from Listing 6-2 and write
a <code>match</code> with patterns that will destructure each inner value.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">enum Message {
Quit,
Move { x: i32, y: i32 },
@@ -414,8 +419,8 @@ fn main() {
}
}
}</code></pre></pre>
<p><span class="caption">Listing 18-15: Destructuring enum variants that hold
different kinds of values</span></p>
<figcaption>Listing 19-15: Destructuring enum variants that hold different kinds of values</figcaption>
</figure>
<p>This code will print <code>Change the color to red 0, green 160, and blue 255</code>. Try
changing the value of <code>msg</code> to see the code from the other arms run.</p>
<p>For enum variants without any data, like <code>Message::Quit</code>, we cant destructure
@@ -425,7 +430,7 @@ and no variables are in that pattern.</p>
similar to the pattern we specify to match structs. After the variant name, we
place curly brackets and then list the fields with variables so we break apart
the pieces to use in the code for this arm. Here we use the shorthand form as
we did in Listing 18-13.</p>
we did in Listing 19-13.</p>
<p>For tuple-like enum variants, like <code>Message::Write</code> that holds a tuple with one
element and <code>Message::ChangeColor</code> that holds a tuple with three elements, the
pattern is similar to the pattern we specify to match tuples. The number of
@@ -434,8 +439,9 @@ matching.</p>
<h4 id="destructuring-nested-structs-and-enums"><a class="header" href="#destructuring-nested-structs-and-enums">Destructuring Nested Structs and Enums</a></h4>
<p>So far, our examples have all been matching structs or enums one level deep,
but matching can work on nested items too! For example, we can refactor the
code in Listing 18-15 to support RGB and HSV colors in the <code>ChangeColor</code>
message, as shown in Listing 18-16.</p>
code in Listing 19-15 to support RGB and HSV colors in the <code>ChangeColor</code>
message, as shown in Listing 19-16.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021">enum Color {
Rgb(i32, i32, i32),
Hsv(i32, i32, i32),
@@ -461,7 +467,8 @@ fn main() {
_ =&gt; (),
}
}</code></pre></pre>
<p><span class="caption">Listing 18-16: Matching on nested enums</span></p>
<figcaption>Listing 19-16: Matching on nested enums</figcaption>
</figure>
<p>The pattern of the first arm in the <code>match</code> expression matches a
<code>Message::ChangeColor</code> enum variant that contains a <code>Color::Rgb</code> variant; then
the pattern binds to the three inner <code>i32</code> values. The pattern of the second
@@ -496,8 +503,9 @@ parts of a value. Lets explore how and why to use each of these patterns.</p>
<p>Weve used the underscore as a wildcard pattern that will match any value but
not bind to the value. This is especially useful as the last arm in a <code>match</code>
expression, but we can also use it in any pattern, including function
parameters, as shown in Listing 18-17.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
parameters, as shown in Listing 19-17.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn foo(_: i32, y: i32) {
println!("This code only uses the y parameter: {y}");
}
@@ -505,7 +513,8 @@ parameters, as shown in Listing 18-17.</p>
fn main() {
foo(3, 4);
}</code></pre></pre>
<p><span class="caption">Listing 18-17: Using <code>_</code> in a function signature</span></p>
<figcaption>Listing 19-17: Using <code>_</code> in a function signature</figcaption>
</figure>
<p>This code will completely ignore the value <code>3</code> passed as the first argument,
and will print <code>This code only uses the y parameter: 4</code>.</p>
<p>In most cases when you no longer need a particular function parameter, you
@@ -518,10 +527,11 @@ would if you used a name instead.</p>
<h4 id="ignoring-parts-of-a-value-with-a-nested-_"><a class="header" href="#ignoring-parts-of-a-value-with-a-nested-_">Ignoring Parts of a Value with a Nested <code>_</code></a></h4>
<p>We can also use <code>_</code> inside another pattern to ignore just part of a value, for
example, when we want to test for only part of a value but have no use for the
other parts in the corresponding code we want to run. Listing 18-18 shows code
other parts in the corresponding code we want to run. Listing 19-18 shows code
responsible for managing a settings value. The business requirements are that
the user should not be allowed to overwrite an existing customization of a
setting but can unset the setting and give it a value if it is currently unset.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let mut setting_value = Some(5);
let new_setting_value = Some(10);
@@ -537,9 +547,8 @@ setting but can unset the setting and give it a value if it is currently unset.<
println!("setting is {setting_value:?}");
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-18: Using an underscore within patterns that
match <code>Some</code> variants when we dont need to use the value inside the
<code>Some</code></span></p>
<figcaption>Listing 19-18: Using an underscore within patterns that match <code>Some</code> variants when we dont need to use the value inside the <code>Some</code></figcaption>
</figure>
<p>This code will print <code>Can't overwrite an existing customized value</code> and then
<code>setting is Some(5)</code>. In the first match arm, we dont need to match on or use
the values inside either <code>Some</code> variant, but we do need to test for the case
@@ -550,8 +559,9 @@ changed.</p>
<code>None</code>) expressed by the <code>_</code> pattern in the second arm, we want to allow
<code>new_setting_value</code> to become <code>setting_value</code>.</p>
<p>We can also use underscores in multiple places within one pattern to ignore
particular values. Listing 18-19 shows an example of ignoring the second and
particular values. Listing 19-19 shows an example of ignoring the second and
fourth values in a tuple of five items.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let numbers = (2, 4, 8, 16, 32);
@@ -561,7 +571,8 @@ fourth values in a tuple of five items.</p>
}
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-19: Ignoring multiple parts of a tuple</span></p>
<figcaption>Listing 19-19: Ignoring multiple parts of a tuple</figcaption>
</figure>
<p>This code will print <code>Some numbers: 2, 8, 32</code>, and the values 4 and 16 will be
ignored.</p>
<h4 id="ignoring-an-unused-variable-by-starting-its-name-with-_"><a class="header" href="#ignoring-an-unused-variable-by-starting-its-name-with-_">Ignoring an Unused Variable by Starting Its Name with <code>_</code></a></h4>
@@ -570,21 +581,23 @@ warning because an unused variable could be a bug. However, sometimes its
useful to be able to create a variable you wont use yet, such as when youre
prototyping or just starting a project. In this situation, you can tell Rust
not to warn you about the unused variable by starting the name of the variable
with an underscore. In Listing 18-20, we create two unused variables, but when
with an underscore. In Listing 19-20, we create two unused variables, but when
we compile this code, we should only get a warning about one of them.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
let _x = 5;
let y = 10;
}</code></pre></pre>
<p><span class="caption">Listing 18-20: Starting a variable name with an
underscore to avoid getting unused variable warnings</span></p>
<figcaption>Listing 19-20: Starting a variable name with an underscore to avoid getting unused variable warnings</figcaption>
</figure>
<p>Here we get a warning about not using the variable <code>y</code>, but we dont get a
warning about not using <code>_x</code>.</p>
<p>Note that there is a subtle difference between using only <code>_</code> and using a name
that starts with an underscore. The syntax <code>_x</code> still binds the value to the
variable, whereas <code>_</code> doesnt bind at all. To show a case where this
distinction matters, Listing 18-21 will provide us with an error.</p>
distinction matters, Listing 19-21 will provide us with an error.</p>
<figure class="listing">
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span> let s = Some(String::from("Hello!"));
@@ -594,12 +607,13 @@ distinction matters, Listing 18-21 will provide us with an error.</p>
println!("{s:?}");
<span class="boring">}</span></code></pre>
<p><span class="caption">Listing 18-21: An unused variable starting with an
underscore still binds the value, which might take ownership of the value</span></p>
<figcaption>Listing 19-21: An unused variable starting with an underscore still binds the value, which might take ownership of the value</figcaption>
</figure>
<p>Well receive an error because the <code>s</code> value will still be moved into <code>_s</code>,
which prevents us from using <code>s</code> again. However, using the underscore by itself
doesnt ever bind to the value. Listing 18-22 will compile without any errors
doesnt ever bind to the value. Listing 19-22 will compile without any errors
because <code>s</code> doesnt get moved into <code>_</code>.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let s = Some(String::from("Hello!"));
@@ -609,17 +623,18 @@ because <code>s</code> doesnt get moved into <code>_</code>.</p>
println!("{s:?}");
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-22: Using an underscore does not bind the
value</span></p>
<figcaption>Listing 19-22: Using an underscore does not bind the value</figcaption>
</figure>
<p>This code works just fine because we never bind <code>s</code> to anything; it isnt moved.</p>
<h4 id="ignoring-remaining-parts-of-a-value-with-"><a class="header" href="#ignoring-remaining-parts-of-a-value-with-">Ignoring Remaining Parts of a Value with <code>..</code></a></h4>
<p>With values that have many parts, we can use the <code>..</code> syntax to use specific
parts and ignore the rest, avoiding the need to list underscores for each
ignored value. The <code>..</code> pattern ignores any parts of a value that we havent
explicitly matched in the rest of the pattern. In Listing 18-23, we have a
explicitly matched in the rest of the pattern. In Listing 19-23, we have a
<code>Point</code> struct that holds a coordinate in three-dimensional space. In the
<code>match</code> expression, we want to operate only on the <code>x</code> coordinate and ignore
the values in the <code>y</code> and <code>z</code> fields.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> struct Point {
x: i32,
@@ -633,15 +648,16 @@ the values in the <code>y</code> and <code>z</code> fields.</p>
Point { x, .. } =&gt; println!("x is {x}"),
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-23: Ignoring all fields of a <code>Point</code> except
for <code>x</code> by using <code>..</code></span></p>
<figcaption>Listing 19-23: Ignoring all fields of a <code>Point</code> except for <code>x</code> by using <code>..</code></figcaption>
</figure>
<p>We list the <code>x</code> value and then just include the <code>..</code> pattern. This is quicker
than having to list <code>y: _</code> and <code>z: _</code>, particularly when were working with
structs that have lots of fields in situations where only one or two fields are
relevant.</p>
<p>The syntax <code>..</code> will expand to as many values as it needs to be. Listing 18-24
<p>The syntax <code>..</code> will expand to as many values as it needs to be. Listing 19-24
shows how to use <code>..</code> with a tuple.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
let numbers = (2, 4, 8, 16, 32);
@@ -651,15 +667,16 @@ shows how to use <code>..</code> with a tuple.</p>
}
}
}</code></pre></pre>
<p><span class="caption">Listing 18-24: Matching only the first and last values in
a tuple and ignoring all other values</span></p>
<figcaption>Listing 19-24: Matching only the first and last values in a tuple and ignoring all other values</figcaption>
</figure>
<p>In this code, the first and last value are matched with <code>first</code> and <code>last</code>. The
<code>..</code> will match and ignore everything in the middle.</p>
<p>However, using <code>..</code> must be unambiguous. If it is unclear which values are
intended for matching and which should be ignored, Rust will give us an error.
Listing 18-25 shows an example of using <code>..</code> ambiguously, so it will not
Listing 19-25 shows an example of using <code>..</code> ambiguously, so it will not
compile.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">fn main() {
let numbers = (2, 4, 8, 16, 32);
@@ -669,8 +686,8 @@ compile.</p>
},
}
}</code></pre>
<p><span class="caption">Listing 18-25: An attempt to use <code>..</code> in an ambiguous
way</span></p>
<figcaption>Listing 19-25: An attempt to use <code>..</code> in an ambiguous way</figcaption>
</figure>
<p>When we compile this example, we get this error:</p>
<pre><code class="language-console">$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
@@ -695,9 +712,10 @@ compiler error because using <code>..</code> in two places like this is ambiguou
<p>A <em>match guard</em> is an additional <code>if</code> condition, specified after the pattern in
a <code>match</code> arm, that must also match for that arm to be chosen. Match guards are
useful for expressing more complex ideas than a pattern alone allows.</p>
<p>The condition can use variables created in the pattern. Listing 18-26 shows a
<p>The condition can use variables created in the pattern. Listing 19-26 shows a
<code>match</code> where the first arm has the pattern <code>Some(x)</code> and also has a match
guard of <code>if x % 2 == 0</code> (which will be true if the number is even).</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let num = Some(4);
@@ -707,7 +725,8 @@ guard of <code>if x % 2 == 0</code> (which will be true if the number is even).<
None =&gt; (),
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-26: Adding a match guard to a pattern</span></p>
<figcaption>Listing 19-26: Adding a match guard to a pattern</figcaption>
</figure>
<p>This example will print <code>The number 4 is even</code>. When <code>num</code> is compared to the
pattern in the first arm, it matches, because <code>Some(4)</code> matches <code>Some(x)</code>. Then
the match guard checks whether the remainder of dividing <code>x</code> by 2 is equal to
@@ -720,13 +739,14 @@ second arm doesnt have a match guard and therefore matches any <code>Some</co
the match guard gives us the ability to express this logic. The downside of
this additional expressiveness is that the compiler doesnt try to check for
exhaustiveness when match guard expressions are involved.</p>
<p>In Listing 18-11, we mentioned that we could use match guards to solve our
<p>In Listing 19-11, we mentioned that we could use match guards to solve our
pattern-shadowing problem. Recall that we created a new variable inside the
pattern in the <code>match</code> expression instead of using the variable outside the
<code>match</code>. That new variable meant we couldnt test against the value of the
outer variable. Listing 18-27 shows how we can use a match guard to fix this
outer variable. Listing 19-27 shows how we can use a match guard to fix this
problem.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn main() {
let x = Some(5);
let y = 10;
@@ -739,8 +759,8 @@ problem.</p>
println!("at the end: x = {x:?}, y = {y}");
}</code></pre></pre>
<p><span class="caption">Listing 18-27: Using a match guard to test for equality
with an outer variable</span></p>
<figcaption>Listing 19-27: Using a match guard to test for equality with an outer variable</figcaption>
</figure>
<p>This code will now print <code>Default case, x = Some(5)</code>. The pattern in the second
match arm doesnt introduce a new variable <code>y</code> that would shadow the outer <code>y</code>,
meaning we can use the outer <code>y</code> in the match guard. Instead of specifying the
@@ -753,10 +773,11 @@ we can look for a value that has the same value as the outer <code>y</code> by c
<code>n</code> to <code>y</code>.</p>
<p>You can also use the <em>or</em> operator <code>|</code> in a match guard to specify multiple
patterns; the match guard condition will apply to all the patterns. Listing
18-28 shows the precedence when combining a pattern that uses <code>|</code> with a match
19-28 shows the precedence when combining a pattern that uses <code>|</code> with a match
guard. The important part of this example is that the <code>if y</code> match guard
applies to <code>4</code>, <code>5</code>, <em>and</em> <code>6</code>, even though it might look like <code>if y</code> only
applies to <code>6</code>.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let x = 4;
let y = false;
@@ -766,8 +787,8 @@ applies to <code>6</code>.</p>
_ =&gt; println!("no"),
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-28: Combining multiple patterns with a match
guard</span></p>
<figcaption>Listing 19-28: Combining multiple patterns with a match guard</figcaption>
</figure>
<p>The match condition states that the arm only matches if the value of <code>x</code> is
equal to <code>4</code>, <code>5</code>, or <code>6</code> <em>and</em> if <code>y</code> is <code>true</code>. When this code runs, the
pattern of the first arm matches because <code>x</code> is <code>4</code>, but the match guard <code>if y</code>
@@ -787,11 +808,12 @@ were applied only to the final value in the list of values specified using the
<code>yes</code>.</p>
<h3 id="-bindings"><a class="header" href="#-bindings"><code>@</code> Bindings</a></h3>
<p>The <em>at</em> operator <code>@</code> lets us create a variable that holds a value at the same
time as were testing that value for a pattern match. In Listing 18-29, we want
time as were testing that value for a pattern match. In Listing 19-29, we want
to test that a <code>Message::Hello</code> <code>id</code> field is within the range <code>3..=7</code>. We also
want to bind the value to the variable <code>id_variable</code> so we can use it in the
code associated with the arm. We could name this variable <code>id</code>, the same as the
field, but for this example well use a different name.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> enum Message {
Hello { id: i32 },
@@ -809,8 +831,8 @@ field, but for this example well use a different name.</p>
Message::Hello { id } =&gt; println!("Found some other id: {id}"),
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 18-29: Using <code>@</code> to bind to a value in a pattern
while also testing it</span></p>
<figcaption>Listing 19-29: Using <code>@</code> to bind to a value in a pattern while also testing it</figcaption>
</figure>
<p>This example will print <code>Found an id in range: 5</code>. By specifying <code>id_variable @</code> before the range <code>3..=7</code>, were capturing whatever value matched the range
while also testing that the value matched the range pattern.</p>
<p>In the second arm, where we only have a range specified in the pattern, the code

View File

@@ -182,7 +182,7 @@
<main>
<h1 id="advanced-features"><a class="header" href="#advanced-features">Advanced Features</a></h1>
<p>By now, youve learned the most commonly used parts of the Rust programming
language. Before we do one more project in Chapter 20, well look at a few
language. Before we do one more project in Chapter 21, well look at a few
aspects of the language you might run into every once in a while, but may not
use every day. You can use this chapter as a reference for when you encounter
any unknowns. The features covered here are useful in very specific situations.

View File

@@ -257,15 +257,17 @@ mutable pointers or multiple mutable pointers to the same location</li>
<p>By opting out of having Rust enforce these guarantees, you can give up
guaranteed safety in exchange for greater performance or the ability to
interface with another language or hardware where Rusts guarantees dont apply.</p>
<p>Listing 19-1 shows how to create an immutable and a mutable raw pointer from
<p>Listing 20-1 shows how to create an immutable and a mutable raw pointer from
references.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let mut num = 5;
let r1 = &amp;num as *const i32;
let r2 = &amp;mut num as *mut i32;
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-1: Creating raw pointers from references</span></p>
<figcaption>Listing 20-1: Creating raw pointers from references</figcaption>
</figure>
<p>Notice that we dont include the <code>unsafe</code> keyword in this code. We can create
raw pointers in safe code; we just cant dereference raw pointers outside an
unsafe block, as youll see in a bit.</p>
@@ -275,21 +277,23 @@ directly from references guaranteed to be valid, we know these particular raw
pointers are valid, but we cant make that assumption about just any raw
pointer.</p>
<p>To demonstrate this, next well create a raw pointer whose validity we cant be
so certain of. Listing 19-2 shows how to create a raw pointer to an arbitrary
so certain of. Listing 20-2 shows how to create a raw pointer to an arbitrary
location in memory. Trying to use arbitrary memory is undefined: there might be
data at that address or there might not, the compiler might optimize the code
so there is no memory access, or the program might error with a segmentation
fault. Usually, there is no good reason to write code like this, but it is
possible.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let address = 0x012345usize;
let r = address as *const i32;
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-2: Creating a raw pointer to an arbitrary
memory address</span></p>
<figcaption>Listing 20-2: Creating a raw pointer to an arbitrary memory address</figcaption>
</figure>
<p>Recall that we can create raw pointers in safe code, but we cant <em>dereference</em>
raw pointers and read the data being pointed to. In Listing 19-3, we use the
raw pointers and read the data being pointed to. In Listing 20-3, we use the
dereference operator <code>*</code> on a raw pointer that requires an <code>unsafe</code> block.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let mut num = 5;
@@ -301,11 +305,11 @@ dereference operator <code>*</code> on a raw pointer that requires an <code>unsa
println!("r2 is: {}", *r2);
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-3: Dereferencing raw pointers within an
<code>unsafe</code> block</span></p>
<figcaption>Listing 20-3: Dereferencing raw pointers within an <code>unsafe</code> block</figcaption>
</figure>
<p>Creating a pointer does no harm; its only when we try to access the value that
it points at that we might end up dealing with an invalid value.</p>
<p>Note also that in Listing 19-1 and 19-3, we created <code>*const i32</code> and <code>*mut i32</code>
<p>Note also that in Listing 20-1 and 20-3, we created <code>*const i32</code> and <code>*mut i32</code>
raw pointers that both pointed to the same memory location, where <code>num</code> is
stored. If we instead tried to create an immutable and a mutable reference to
<code>num</code>, the code would not have compiled because Rusts ownership rules dont
@@ -366,7 +370,8 @@ a common abstraction. As an example, lets study the <code>split_at_mut</code>
from the standard library, which requires some unsafe code. Well explore how
we might implement it. This safe method is defined on mutable slices: it takes
one slice and makes it two by splitting the slice at the index given as an
argument. Listing 19-4 shows how to use <code>split_at_mut</code>.</p>
argument. Listing 20-4 shows how to use <code>split_at_mut</code>.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let mut v = vec![1, 2, 3, 4, 5, 6];
@@ -377,12 +382,13 @@ argument. Listing 19-4 shows how to use <code>split_at_mut</code>.</p>
assert_eq!(a, &amp;mut [1, 2, 3]);
assert_eq!(b, &amp;mut [4, 5, 6]);
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-4: Using the safe <code>split_at_mut</code>
function</span></p>
<figcaption>Listing 20-4: Using the safe <code>split_at_mut</code> function</figcaption>
</figure>
<p>We cant implement this function using only safe Rust. An attempt might look
something like Listing 19-5, which wont compile. For simplicity, well
something like Listing 20-5, which wont compile. For simplicity, well
implement <code>split_at_mut</code> as a function rather than a method and only for slices
of <code>i32</code> values rather than for a generic type <code>T</code>.</p>
<figure class="listing">
<pre><code class="language-rust ignore does_not_compile">fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;mut [i32]) {
let len = values.len();
@@ -395,8 +401,8 @@ of <code>i32</code> values rather than for a generic type <code>T</code>.</p>
</span><span class="boring"> let mut vector = vec![1, 2, 3, 4, 5, 6];
</span><span class="boring"> let (left, right) = split_at_mut(&amp;mut vector, 3);
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 19-5: An attempted implementation of
<code>split_at_mut</code> using only safe Rust</span></p>
<figcaption>Listing 20-5: An attempted implementation of <code>split_at_mut</code> using only safe Rust</figcaption>
</figure>
<p>This function first gets the total length of the slice. Then it asserts that
the index given as a parameter is within the slice by checking whether its
less than or equal to the length. The assertion means that if we pass an index
@@ -405,7 +411,7 @@ before it attempts to use that index.</p>
<p>Then we return two mutable slices in a tuple: one from the start of the
original slice to the <code>mid</code> index and another from <code>mid</code> to the end of the
slice.</p>
<p>When we try to compile the code in Listing 19-5, well get an error.</p>
<p>When we try to compile the code in Listing 20-5, well get an error.</p>
<pre><code class="language-console">$ cargo run
Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example)
error[E0499]: cannot borrow `*values` as mutable more than once at a time
@@ -431,8 +437,9 @@ the slice; it only knows that were borrowing from the same slice twice.
Borrowing different parts of a slice is fundamentally okay because the two
slices arent overlapping, but Rust isnt smart enough to know this. When we
know code is okay, but Rust doesnt, its time to reach for unsafe code.</p>
<p>Listing 19-6 shows how to use an <code>unsafe</code> block, a raw pointer, and some calls
<p>Listing 20-6 shows how to use an <code>unsafe</code> block, a raw pointer, and some calls
to unsafe functions to make the implementation of <code>split_at_mut</code> work.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021">use std::slice;
fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;mut [i32]) {
@@ -453,8 +460,8 @@ fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;
</span><span class="boring"> let mut vector = vec![1, 2, 3, 4, 5, 6];
</span><span class="boring"> let (left, right) = split_at_mut(&amp;mut vector, 3);
</span><span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-6: Using unsafe code in the implementation of
the <code>split_at_mut</code> function</span></p>
<figcaption>Listing 20-6: Using unsafe code in the implementation of the <code>split_at_mut</code> function</figcaption>
</figure>
<p>Recall from <a href="ch04-03-slices.html#the-slice-type">“The Slice Type”</a><!-- ignore --> section in
Chapter 4 that slices are a pointer to some data and the length of the slice.
We use the <code>len</code> method to get the length of a slice and the <code>as_mut_ptr</code>
@@ -482,9 +489,10 @@ appropriate use of <code>unsafe</code>.</p>
abstraction to the unsafe code with an implementation of the function that uses
<code>unsafe</code> code in a safe way, because it creates only valid pointers from the
data this function has access to.</p>
<p>In contrast, the use of <code>slice::from_raw_parts_mut</code> in Listing 19-7 would
<p>In contrast, the use of <code>slice::from_raw_parts_mut</code> in Listing 20-7 would
likely crash when the slice is used. This code takes an arbitrary memory
location and creates a slice 10,000 items long.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> use std::slice;
@@ -493,8 +501,8 @@ location and creates a slice 10,000 items long.</p>
let values: &amp;[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) };
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-7: Creating a slice from an arbitrary memory
location</span></p>
<figcaption>Listing 20-7: Creating a slice from an arbitrary memory location</figcaption>
</figure>
<p>We dont own the memory at this arbitrary location, and there is no guarantee
that the slice this code creates contains valid <code>i32</code> values. Attempting to use
<code>values</code> as though its a valid slice results in undefined behavior.</p>
@@ -504,12 +512,13 @@ language. For this, Rust has the keyword <code>extern</code> that facilitates th
and use of a <em>Foreign Function Interface (FFI)</em>. An FFI is a way for a
programming language to define functions and enable a different (foreign)
programming language to call those functions.</p>
<p>Listing 19-8 demonstrates how to set up an integration with the <code>abs</code> function
<p>Listing 20-8 demonstrates how to set up an integration with the <code>abs</code> function
from the C standard library. Functions declared within <code>extern</code> blocks are
always unsafe to call from Rust code. The reason is that other languages dont
enforce Rusts rules and guarantees, and Rust cant check them, so
responsibility falls on the programmer to ensure safety.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">extern "C" {
fn abs(input: i32) -&gt; i32;
}
@@ -519,8 +528,8 @@ fn main() {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
}</code></pre></pre>
<p><span class="caption">Listing 19-8: Declaring and calling an <code>extern</code> function
defined in another language</span></p>
<figcaption>Listing 20-8: Declaring and calling an <code>extern</code> function defined in another language</figcaption>
</figure>
<p>Within the <code>extern "C"</code> block, we list the names and signatures of external
functions from another language we want to call. The <code>"C"</code> part defines which
<em>application binary interface (ABI)</em> the external function uses: the ABI
@@ -553,17 +562,18 @@ pub extern "C" fn call_from_c() {
<p>In this book, weve not yet talked about <em>global variables</em>, which Rust does
support but can be problematic with Rusts ownership rules. If two threads are
accessing the same mutable global variable, it can cause a data race.</p>
<p>In Rust, global variables are called <em>static</em> variables. Listing 19-9 shows an
<p>In Rust, global variables are called <em>static</em> variables. Listing 20-9 shows an
example declaration and use of a static variable with a string slice as a
value.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">static HELLO_WORLD: &amp;str = "Hello, world!";
fn main() {
println!("name is: {HELLO_WORLD}");
}</code></pre></pre>
<p><span class="caption">Listing 19-9: Defining and using an immutable static
variable</span></p>
<figcaption>Listing 20-9: Defining and using an immutable static variable</figcaption>
</figure>
<p>Static variables are similar to constants, which we discussed in the
<a href="ch03-01-variables-and-mutability.html#constants">“Differences Between Variables and
Constants”</a><!-- ignore --> section
@@ -577,9 +587,10 @@ values in a static variable have a fixed address in memory. Using the value
will always access the same data. Constants, on the other hand, are allowed to
duplicate their data whenever theyre used. Another difference is that static
variables can be mutable. Accessing and modifying mutable static variables is
<em>unsafe</em>. Listing 19-10 shows how to declare, access, and modify a mutable
<em>unsafe</em>. Listing 20-10 shows how to declare, access, and modify a mutable
static variable named <code>COUNTER</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
@@ -595,8 +606,8 @@ fn main() {
println!("COUNTER: {COUNTER}");
}
}</code></pre></pre>
<p><span class="caption">Listing 19-10: Reading from or writing to a mutable
static variable is unsafe</span></p>
<figcaption>Listing 20-10: Reading from or writing to a mutable static variable is unsafe</figcaption>
</figure>
<p>As with regular variables, we specify mutability using the <code>mut</code> keyword. Any
code that reads or writes from <code>COUNTER</code> must be within an <code>unsafe</code> block. This
code compiles and prints <code>COUNTER: 3</code> as we would expect because its single
@@ -612,7 +623,8 @@ that data accessed from different threads is done safely.</p>
least one of its methods has some invariant that the compiler cant verify. We
declare that a trait is <code>unsafe</code> by adding the <code>unsafe</code> keyword before <code>trait</code>
and marking the implementation of the trait as <code>unsafe</code> too, as shown in
Listing 19-11.</p>
Listing 20-11.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021">unsafe trait Foo {
// methods go here
}
@@ -622,8 +634,8 @@ unsafe impl Foo for i32 {
}
fn main() {}</code></pre></pre>
<p><span class="caption">Listing 19-11: Defining and implementing an unsafe
trait</span></p>
<figcaption>Listing 20-11: Defining and implementing an unsafe trait</figcaption>
</figure>
<p>By using <code>unsafe impl</code>, were promising that well uphold the invariants that
the compiler cant verify.</p>
<p>As an example, recall the <code>Sync</code> and <code>Send</code> marker traits we discussed in the

View File

@@ -200,14 +200,15 @@ the other features discussed in this chapter.</p>
standard library provides. The associated type is named <code>Item</code> and stands in
for the type of the values the type implementing the <code>Iterator</code> trait is
iterating over. The definition of the <code>Iterator</code> trait is as shown in Listing
19-12.</p>
20-12.</p>
<figure class="listing">
<pre><code class="language-rust noplayground">pub trait Iterator {
type Item;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt;;
}</code></pre>
<p><span class="caption">Listing 19-12: The definition of the <code>Iterator</code> trait
that has an associated type <code>Item</code></span></p>
<figcaption>Listing 20-12: The definition of the <code>Iterator</code> trait that has an associated type <code>Item</code></figcaption>
</figure>
<p>The type <code>Item</code> is a placeholder, and the <code>next</code> methods definition shows that
it will return values of type <code>Option&lt;Self::Item&gt;</code>. Implementors of the
<code>Iterator</code> trait will specify the concrete type for <code>Item</code>, and the <code>next</code>
@@ -217,7 +218,8 @@ latter allow us to define a function without specifying what types it can
handle. To examine the difference between the two concepts, well look at an
implementation of the <code>Iterator</code> trait on a type named <code>Counter</code> that specifies
the <code>Item</code> type is <code>u32</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore"><span class="boring">struct Counter {
</span><span class="boring"> count: u32,
</span><span class="boring">}
@@ -241,14 +243,16 @@ the <code>Item</code> type is <code>u32</code>:</p>
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
</figure>
<p>This syntax seems comparable to that of generics. So why not just define the
<code>Iterator</code> trait with generics, as shown in Listing 19-13?</p>
<code>Iterator</code> trait with generics, as shown in Listing 20-13?</p>
<figure class="listing">
<pre><code class="language-rust noplayground">pub trait Iterator&lt;T&gt; {
fn next(&amp;mut self) -&gt; Option&lt;T&gt;;
}</code></pre>
<p><span class="caption">Listing 19-13: A hypothetical definition of the
<code>Iterator</code> trait using generics</span></p>
<p>The difference is that when using generics, as in Listing 19-13, we must
<figcaption>Listing A hypothetical definition of the `Iterator` trait using generics</figcaption>
</figure>
<p>The difference is that when using generics, as in Listing 20-13, we must
annotate the types in each implementation; because we can also implement
<code>Iterator&lt;String&gt; for Counter</code> or any other type, we could have multiple
implementations of <code>Iterator</code> for <code>Counter</code>. In other words, when a trait has a
@@ -257,7 +261,7 @@ the concrete types of the generic type parameters each time. When we use the
<code>next</code> method on <code>Counter</code>, we would have to provide type annotations to
indicate which implementation of <code>Iterator</code> we want to use.</p>
<p>With associated types, we dont need to annotate types because we cant
implement a trait on a type multiple times. In Listing 19-12 with the
implement a trait on a type multiple times. In Listing 20-12 with the
definition that uses associated types, we can only choose what the type of
<code>Item</code> will be once, because there can only be one <code>impl Iterator for Counter</code>.
We dont have to specify that we want an iterator of <code>u32</code> values everywhere
@@ -277,10 +281,11 @@ in particular situations.</p>
<p>Rust doesnt allow you to create your own operators or overload arbitrary
operators. But you can overload the operations and corresponding traits listed
in <code>std::ops</code> by implementing the traits associated with the operator. For
example, in Listing 19-14 we overload the <code>+</code> operator to add two <code>Point</code>
example, in Listing 20-14 we overload the <code>+</code> operator to add two <code>Point</code>
instances together. We do this by implementing the <code>Add</code> trait on a <code>Point</code>
struct:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">use std::ops::Add;
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -306,8 +311,8 @@ fn main() {
Point { x: 3, y: 3 }
);
}</code></pre></pre>
<p><span class="caption">Listing 19-14: Implementing the <code>Add</code> trait to overload
the <code>+</code> operator for <code>Point</code> instances</span></p>
<figcaption>Listing 20-14: Implementing the <code>Add</code> trait to overload the <code>+</code> operator for <code>Point</code> instances</figcaption>
</figure>
<p>The <code>add</code> method adds the <code>x</code> values of two <code>Point</code> instances and the <code>y</code>
values of two <code>Point</code> instances to create a new <code>Point</code>. The <code>Add</code> trait has an
associated type named <code>Output</code> that determines the type returned from the <code>add</code>
@@ -339,8 +344,9 @@ units. This thin wrapping of an existing type in another struct is known as the
Pattern to Implement External Traits on External Types”</a><!-- ignore
--> section. We want to add values in millimeters to values in meters and have
the implementation of <code>Add</code> do the conversion correctly. We can implement <code>Add</code>
for <code>Millimeters</code> with <code>Meters</code> as the <code>Rhs</code>, as shown in Listing 19-15.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
for <code>Millimeters</code> with <code>Meters</code> as the <code>Rhs</code>, as shown in Listing 20-15.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::ops::Add;
struct Millimeters(u32);
@@ -353,8 +359,8 @@ impl Add&lt;Meters&gt; for Millimeters {
Millimeters(self.0 + (other.0 * 1000))
}
}</code></pre>
<p><span class="caption">Listing 19-15: Implementing the <code>Add</code> trait on
<code>Millimeters</code> to add <code>Millimeters</code> to <code>Meters</code></span></p>
<figcaption>Listing 20-15: Implementing the <code>Add</code> trait on <code>Millimeters</code> to add <code>Millimeters</code> to <code>Meters</code></figcaption>
</figure>
<p>To add <code>Millimeters</code> and <code>Meters</code>, we specify <code>impl Add&lt;Meters&gt;</code> to set the
value of the <code>Rhs</code> type parameter instead of using the default of <code>Self</code>.</p>
<p>Youll use default type parameters in two main ways:</p>
@@ -378,11 +384,12 @@ another traits method, nor does Rust prevent you from implementing both trait
on one type. Its also possible to implement a method directly on the type with
the same name as methods from traits.</p>
<p>When calling methods with the same name, youll need to tell Rust which one you
want to use. Consider the code in Listing 19-16 where weve defined two traits,
want to use. Consider the code in Listing 20-16 where weve defined two traits,
<code>Pilot</code> and <code>Wizard</code>, that both have a method called <code>fly</code>. We then implement
both traits on a type <code>Human</code> that already has a method named <code>fly</code> implemented
on it. Each <code>fly</code> method does something different.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">trait Pilot {
fn fly(&amp;self);
}
@@ -412,12 +419,12 @@ impl Human {
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre></pre>
<p><span class="caption">Listing 19-16: Two traits are defined to have a <code>fly</code>
method and are implemented on the <code>Human</code> type, and a <code>fly</code> method is
implemented on <code>Human</code> directly</span></p>
<figcaption>Listing 20-16: Two traits are defined to have a <code>method and are implemented on the</code>Human<code>type, and a</code>fly<code>method is implemented on</code>Human` directly</figcaption>
</figure>
<p>When we call <code>fly</code> on an instance of <code>Human</code>, the compiler defaults to calling
the method that is directly implemented on the type, as shown in Listing 19-17.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
the method that is directly implemented on the type, as shown in Listing 20-17.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
@@ -450,14 +457,15 @@ the method that is directly implemented on the type, as shown in Listing 19-17.<
let person = Human;
person.fly();
}</code></pre></pre>
<p><span class="caption">Listing 19-17: Calling <code>fly</code> on an instance of
<code>Human</code></span></p>
<figcaption>Listing 20-17: Calling <code>fly</code> on an instance of <code>Human</code></figcaption>
</figure>
<p>Running this code will print <code>*waving arms furiously*</code>, showing that Rust
called the <code>fly</code> method implemented on <code>Human</code> directly.</p>
<p>To call the <code>fly</code> methods from either the <code>Pilot</code> trait or the <code>Wizard</code> trait,
we need to use more explicit syntax to specify which <code>fly</code> method we mean.
Listing 19-18 demonstrates this syntax.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
Listing 20-18 demonstrates this syntax.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
@@ -492,12 +500,12 @@ Listing 19-18 demonstrates this syntax.</p>
Wizard::fly(&amp;person);
person.fly();
}</code></pre></pre>
<p><span class="caption">Listing 19-18: Specifying which traits <code>fly</code> method we
want to call</span></p>
<figcaption>Listing 20-18: Specifying which traits <code>fly</code> method we want to call</figcaption>
</figure>
<p>Specifying the trait name before the method name clarifies to Rust which
implementation of <code>fly</code> we want to call. We could also write
<code>Human::fly(&amp;person)</code>, which is equivalent to the <code>person.fly()</code> that we used
in Listing 19-18, but this is a bit longer to write if we dont need to
in Listing 20-18, but this is a bit longer to write if we dont need to
disambiguate.</p>
<p>Running this code prints the following:</p>
<pre><code class="language-console">$ cargo run
@@ -514,12 +522,13 @@ trait to use based on the type of <code>self</code>.</p>
<p>However, associated functions that are not methods dont have a <code>self</code>
parameter. When there are multiple types or traits that define non-method
functions with the same function name, Rust doesnt always know which type you
mean unless you use <em>fully qualified syntax</em>. For example, in Listing 19-19 we
mean unless you use <em>fully qualified syntax</em>. For example, in Listing 20-19 we
create a trait for an animal shelter that wants to name all baby dogs <em>Spot</em>.
We make an <code>Animal</code> trait with an associated non-method function <code>baby_name</code>.
The <code>Animal</code> trait is implemented for the struct <code>Dog</code>, on which we also
provide an associated non-method function <code>baby_name</code> directly.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">trait Animal {
fn baby_name() -&gt; String;
}
@@ -541,9 +550,8 @@ impl Animal for Dog {
fn main() {
println!("A baby dog is called a {}", Dog::baby_name());
}</code></pre></pre>
<p><span class="caption">Listing 19-19: A trait with an associated function and a
type with an associated function of the same name that also implements the
trait</span></p>
<figcaption>Listing 20-19: A trait with an associated function and a type with an associated function of the same name that also implements the trait</figcaption>
</figure>
<p>We implement the code for naming all puppies Spot in the <code>baby_name</code> associated
function that is defined on <code>Dog</code>. The <code>Dog</code> type also implements the trait
<code>Animal</code>, which describes characteristics that all animals have. Baby dogs are
@@ -560,9 +568,10 @@ A baby dog is called a Spot
<p>This output isnt what we wanted. We want to call the <code>baby_name</code> function that
is part of the <code>Animal</code> trait that we implemented on <code>Dog</code> so the code prints
<code>A baby dog is called a puppy</code>. The technique of specifying the trait name that
we used in Listing 19-18 doesnt help here; if we change <code>main</code> to the code in
Listing 19-20, well get a compilation error.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
we used in Listing 20-18 doesnt help here; if we change <code>main</code> to the code in
Listing 20-20, well get a compilation error.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">trait Animal {
</span><span class="boring"> fn baby_name() -&gt; String;
</span><span class="boring">}
@@ -584,9 +593,8 @@ Listing 19-20, well get a compilation error.</p>
</span>fn main() {
println!("A baby dog is called a {}", Animal::baby_name());
}</code></pre>
<p><span class="caption">Listing 19-20: Attempting to call the <code>baby_name</code>
function from the <code>Animal</code> trait, but Rust doesnt know which implementation to
use</span></p>
<figcaption>Listing 20-20: Attempting to call the <code>baby_name</code> function from the <code>Animal</code> trait, but Rust doesnt know which implementation to use</figcaption>
</figure>
<p>Because <code>Animal::baby_name</code> doesnt have a <code>self</code> parameter, and there could be
other types that implement the <code>Animal</code> trait, Rust cant figure out which
implementation of <code>Animal::baby_name</code> we want. Well get this compiler error:</p>
@@ -611,9 +619,10 @@ error: could not compile `traits-example` (bin "traits-example") due to 1 previo
</code></pre>
<p>To disambiguate and tell Rust that we want to use the implementation of
<code>Animal</code> for <code>Dog</code> as opposed to the implementation of <code>Animal</code> for some other
type, we need to use fully qualified syntax. Listing 19-21 demonstrates how to
type, we need to use fully qualified syntax. Listing 20-21 demonstrates how to
use fully qualified syntax.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">trait Animal {
</span><span class="boring"> fn baby_name() -&gt; String;
</span><span class="boring">}
@@ -635,9 +644,8 @@ use fully qualified syntax.</p>
</span>fn main() {
println!("A baby dog is called a {}", &lt;Dog as Animal&gt;::baby_name());
}</code></pre></pre>
<p><span class="caption">Listing 19-21: Using fully qualified syntax to specify
that we want to call the <code>baby_name</code> function from the <code>Animal</code> trait as
implemented on <code>Dog</code></span></p>
<figcaption>Listing 20-21: Using fully qualified syntax to specify that we want to call the <code>baby_name</code> function from the <code>Animal</code> trait as implemented on <code>Dog</code></figcaption>
</figure>
<p>Were providing Rust with a type annotation within the angle brackets, which
indicates we want to call the <code>baby_name</code> method from the <code>Animal</code> trait as
implemented on <code>Dog</code> by saying that we want to treat the <code>Dog</code> type as an
@@ -680,9 +688,10 @@ should print the following:</p>
<code>OutlinePrint</code> trait will work only for types that also implement <code>Display</code> and
provide the functionality that <code>OutlinePrint</code> needs. We can do that in the
trait definition by specifying <code>OutlinePrint: Display</code>. This technique is
similar to adding a trait bound to the trait. Listing 19-22 shows an
similar to adding a trait bound to the trait. Listing 20-22 shows an
implementation of the <code>OutlinePrint</code> trait.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">use std::fmt;
trait OutlinePrint: fmt::Display {
@@ -698,8 +707,8 @@ trait OutlinePrint: fmt::Display {
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre></pre>
<p><span class="caption">Listing 19-22: Implementing the <code>OutlinePrint</code> trait that
requires the functionality from <code>Display</code></span></p>
<figcaption>Listing 20-22: Implementing the <code>OutlinePrint</code> trait that requires the functionality from <code>Display</code></figcaption>
</figure>
<p>Because weve specified that <code>OutlinePrint</code> requires the <code>Display</code> trait, we
can use the <code>to_string</code> function that is automatically implemented for any type
that implements <code>Display</code>. If we tried to use <code>to_string</code> without adding a
@@ -708,7 +717,8 @@ error saying that no method named <code>to_string</code> was found for the type
the current scope.</p>
<p>Lets see what happens when we try to implement <code>OutlinePrint</code> on a type that
doesnt implement <code>Display</code>, such as the <code>Point</code> struct:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::fmt;
</span><span class="boring">
</span><span class="boring">trait OutlinePrint: fmt::Display {
@@ -734,6 +744,7 @@ impl OutlinePrint for Point {}
</span><span class="boring"> let p = Point { x: 1, y: 3 };
</span><span class="boring"> p.outline_print();
</span><span class="boring">}</span></code></pre>
</figure>
<p>We get an error saying that <code>Display</code> is required but not implemented:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
@@ -772,7 +783,8 @@ error: could not compile `traits-example` (bin "traits-example") due to 2 previo
</code></pre>
<p>To fix this, we implement <code>Display</code> on <code>Point</code> and satisfy the constraint that
<code>OutlinePrint</code> requires, like so:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">trait OutlinePrint: fmt::Display {
</span><span class="boring"> fn outline_print(&amp;self) {
</span><span class="boring"> let output = self.to_string();
@@ -804,6 +816,7 @@ impl fmt::Display for Point {
</span><span class="boring"> let p = Point { x: 1, y: 3 };
</span><span class="boring"> p.outline_print();
</span><span class="boring">}</span></code></pre></pre>
</figure>
<p>Then implementing the <code>OutlinePrint</code> trait on <code>Point</code> will compile
successfully, and we can call <code>outline_print</code> on a <code>Point</code> instance to display
it within an outline of asterisks.</p>
@@ -825,8 +838,9 @@ type is elided at compile time.</p>
orphan rule prevents us from doing directly because the <code>Display</code> trait and the
<code>Vec&lt;T&gt;</code> type are defined outside our crate. We can make a <code>Wrapper</code> struct
that holds an instance of <code>Vec&lt;T&gt;</code>; then we can implement <code>Display</code> on
<code>Wrapper</code> and use the <code>Vec&lt;T&gt;</code> value, as shown in Listing 19-23.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<code>Wrapper</code> and use the <code>Vec&lt;T&gt;</code> value, as shown in Listing 20-23.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">use std::fmt;
struct Wrapper(Vec&lt;String&gt;);
@@ -841,8 +855,8 @@ fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {w}");
}</code></pre></pre>
<p><span class="caption">Listing 19-23: Creating a <code>Wrapper</code> type around
<code>Vec&lt;String&gt;</code> to implement <code>Display</code></span></p>
<figcaption>Listing 20-23: Creating a <code>Wrapper</code> type around <code>Vec&lt;String&gt;</code> to implement <code>Display</code></figcaption>
</figure>
<p>The implementation of <code>Display</code> uses <code>self.0</code> to access the inner <code>Vec&lt;T&gt;</code>,
because <code>Wrapper</code> is a tuple struct and <code>Vec&lt;T&gt;</code> is the item at index 0 in the
tuple. Then we can use the functionality of the <code>Display</code> trait on <code>Wrapper</code>.</p>

View File

@@ -195,7 +195,7 @@ Types.”</a><!-- ignore --></p>
<p>The newtype pattern is also useful for tasks beyond those weve discussed so
far, including statically enforcing that values are never confused and
indicating the units of a value. You saw an example of using newtypes to
indicate units in Listing 19-15: recall that the <code>Millimeters</code> and <code>Meters</code>
indicate units in Listing 20-15: recall that the <code>Millimeters</code> and <code>Meters</code>
structs wrapped <code>u32</code> values in a newtype. If we wrote a function with a
parameter of type <code>Millimeters</code>, we couldnt compile a program that
accidentally tried to call that function with a value of type <code>Meters</code> or a
@@ -212,7 +212,7 @@ internally. The newtype pattern is a lightweight way to achieve encapsulation
to hide implementation details, which we discussed in the <a href="ch18-01-what-is-oo.html#encapsulation-that-hides-implementation-details">“Encapsulation that
Hides Implementation
Details”</a><!-- ignore -->
section of Chapter 17.</p>
section of Chapter 18.</p>
<h3 id="creating-type-synonyms-with-type-aliases"><a class="header" href="#creating-type-synonyms-with-type-aliases">Creating Type Synonyms with Type Aliases</a></h3>
<p>Rust provides the ability to declare a <em>type alias</em> to give an existing type
another name. For this we use the <code>type</code> keyword. For example, we can create
@@ -226,7 +226,7 @@ the alias <code>Kilometers</code> to <code>i32</code> like so:</p>
</span><span class="boring"> println!("x + y = {}", x + y);
</span><span class="boring">}</span></code></pre></pre>
<p>Now, the alias <code>Kilometers</code> is a <em>synonym</em> for <code>i32</code>; unlike the <code>Millimeters</code>
and <code>Meters</code> types we created in Listing 19-15, <code>Kilometers</code> is not a separate,
and <code>Meters</code> types we created in Listing 20-15, <code>Kilometers</code> is not a separate,
new type. Values that have the type <code>Kilometers</code> will be treated the same as
values of type <code>i32</code>:</p>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
@@ -248,7 +248,8 @@ might have a lengthy type like this:</p>
<pre><code class="language-rust ignore">Box&lt;dyn Fn() + Send + 'static&gt;</code></pre>
<p>Writing this lengthy type in function signatures and as type annotations all
over the code can be tiresome and error prone. Imagine having a project full of
code like that in Listing 19-24.</p>
code like that in Listing 20-24.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> let f: Box&lt;dyn Fn() + Send + 'static&gt; = Box::new(|| println!("hi"));
@@ -261,10 +262,12 @@ code like that in Listing 19-24.</p>
<span class="boring"> Box::new(|| ())
</span> }
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-24: Using a long type in many places</span></p>
<figcaption>Listing 20-24: Using a long type in many places</figcaption>
</figure>
<p>A type alias makes this code more manageable by reducing the repetition. In
Listing 19-25, weve introduced an alias named <code>Thunk</code> for the verbose type and
Listing 20-25, weve introduced an alias named <code>Thunk</code> for the verbose type and
can replace all uses of the type with the shorter alias <code>Thunk</code>.</p>
<figure class="listing">
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">fn main() {
</span> type Thunk = Box&lt;dyn Fn() + Send + 'static&gt;;
@@ -279,8 +282,8 @@ can replace all uses of the type with the shorter alias <code>Thunk</code>.</p>
<span class="boring"> Box::new(|| ())
</span> }
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 19-25: Introducing a type alias <code>Thunk</code> to reduce
repetition</span></p>
<figcaption>Listing 20-25: Introducing a type alias <code>Thunk</code> to reduce repetition</figcaption>
</figure>
<p>This code is much easier to read and write! Choosing a meaningful name for a
type alias can help communicate your intent as well (<em>thunk</em> is a word for code
to be evaluated at a later time, so its an appropriate name for a closure that
@@ -348,7 +351,8 @@ never are called <em>diverging functions</em>. We cant create values of the t
so <code>bar</code> can never possibly return.</p>
<p>But what use is a type you can never create values for? Recall the code from
Listing 2-5, part of the number guessing game; weve reproduced a bit of it
here in Listing 19-26.</p>
here in Listing 20-26.</p>
<figure class="listing">
<pre><code class="language-rust ignore"><span class="boring">use rand::Rng;
</span><span class="boring">use std::cmp::Ordering;
</span><span class="boring">use std::io;
@@ -390,8 +394,8 @@ here in Listing 19-26.</p>
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 19-26: A <code>match</code> with an arm that ends in
<code>continue</code></span></p>
<figcaption>Listing 20-26: A <code>match</code> with an arm that ends in <code>continue</code></figcaption>
</figure>
<p>At the time, we skipped over some details in this code. In Chapter 6 in <a href="ch06-02-match.html#the-match-control-flow-operator">“The
<code>match</code> Control Flow Operator”</a><!-- ignore -->
section, we discussed that <code>match</code> arms must all return the same type. So, for
@@ -406,7 +410,7 @@ example, the following code doesnt work:</p>
<p>The type of <code>guess</code> in this code would have to be an integer <em>and</em> a string,
and Rust requires that <code>guess</code> have only one type. So what does <code>continue</code>
return? How were we allowed to return a <code>u32</code> from one arm and have another arm
that ends with <code>continue</code> in Listing 19-26?</p>
that ends with <code>continue</code> in Listing 20-26?</p>
<p>As you might have guessed, <code>continue</code> has a <code>!</code> value. That is, when Rust
computes the type of <code>guess</code>, it looks at both match arms, the former with a
value of <code>u32</code> and the latter with a <code>!</code> value. Because <code>!</code> can never have a
@@ -434,7 +438,7 @@ this definition:</p>
}
}
}</code></pre>
<p>In this code, the same thing happens as in the <code>match</code> in Listing 19-26: Rust
<p>In this code, the same thing happens as in the <code>match</code> in Listing 20-26: Rust
sees that <code>val</code> has the type <code>T</code> and <code>panic!</code> has the type <code>!</code>, so the result
of the overall <code>match</code> expression is <code>T</code>. This code works because <code>panic!</code>
doesnt produce a value; it ends the program. In the <code>None</code> case, we wont be
@@ -487,7 +491,7 @@ types behind a pointer of some kind.</p>
<p>We can combine <code>str</code> with all kinds of pointers: for example, <code>Box&lt;str&gt;</code> or
<code>Rc&lt;str&gt;</code>. In fact, youve seen this before but with a different dynamically
sized type: traits. Every trait is a dynamically sized type we can refer to by
using the name of the trait. In Chapter 17 in the <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects That
using the name of the trait. In Chapter 18 in the <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects That
Allow for Values of Different
Types”</a><!--
ignore --> section, we mentioned that to use traits as trait objects, we must

View File

@@ -192,14 +192,15 @@ closure trait. The <code>fn</code> type is called a <em>function pointer</em>. P
with function pointers will allow you to use functions as arguments to other
functions.</p>
<p>The syntax for specifying that a parameter is a function pointer is similar to
that of closures, as shown in Listing 19-27, where weve defined a function
that of closures, as shown in Listing 20-27, where weve defined a function
<code>add_one</code> that adds one to its parameter. The function <code>do_twice</code> takes two
parameters: a function pointer to any function that takes an <code>i32</code> parameter
and returns an <code>i32</code>, and one <code>i32</code> value. The <code>do_twice</code> function calls the
function <code>f</code> twice, passing it the <code>arg</code> value, then adds the two function call
results together. The <code>main</code> function calls <code>do_twice</code> with the arguments
<code>add_one</code> and <code>5</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust edition2021">fn add_one(x: i32) -&gt; i32 {
x + 1
}
@@ -213,8 +214,8 @@ fn main() {
println!("The answer is: {answer}");
}</code></pre></pre>
<p><span class="caption">Listing 19-27: Using the <code>fn</code> type to accept a function
pointer as an argument</span></p>
<figcaption>Listing 20-27: Using the <code>fn</code> type to accept a function pointer as an argument</figcaption>
</figure>
<p>This code prints <code>The answer is: 12</code>. We specify that the parameter <code>f</code> in
<code>do_twice</code> is an <code>fn</code> that takes one parameter of type <code>i32</code> and returns an
<code>i32</code>. We can then call <code>f</code> in the body of <code>do_twice</code>. In <code>main</code>, we can pass
@@ -310,7 +311,7 @@ We can use a trait object:</p>
<p>This code will compile just fine. For more about trait objects, refer to the
section <a href="ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types">“Using Trait Objects That Allow for Values of Different
Types”</a><!--
ignore --> in Chapter 18.</p>
ignore --> in Chapter 19.</p>
<p>Next, lets look at macros!</p>
</main>

View File

@@ -243,8 +243,9 @@ integers:</p>
<p>We could also use the <code>vec!</code> macro to make a vector of two integers or a vector
of five string slices. We wouldnt be able to use a function to do the same
because we wouldnt know the number or type of values up front.</p>
<p>Listing 19-28 shows a slightly simplified definition of the <code>vec!</code> macro.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<p>Listing 20-28 shows a slightly simplified definition of the <code>vec!</code> macro.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">#[macro_export]
macro_rules! vec {
( $( $x:expr ),* ) =&gt; {
@@ -257,8 +258,8 @@ macro_rules! vec {
}
};
}</code></pre>
<p><span class="caption">Listing 19-28: A simplified version of the <code>vec!</code> macro
definition</span></p>
<figcaption>Listing 20-28: A simplified version of the <code>vec!</code> macro definition</figcaption>
</figure>
<section class="note" aria-role="note">
<p>Note: The actual definition of the <code>vec!</code> macro in the standard library
includes code to preallocate the correct amount of memory up front. That code
@@ -278,9 +279,9 @@ is the only pattern in this macro, there is only one valid way to match; any
other pattern will result in an error. More complex macros will have more than
one arm.</p>
<p>Valid pattern syntax in macro definitions is different than the pattern syntax
covered in Chapter 18 because macro patterns are matched against Rust code
covered in Chapter 19 because macro patterns are matched against Rust code
structure rather than values. Lets walk through what the pattern pieces in
Listing 19-28 mean; for the full macro pattern syntax, see the <a href="../reference/macros-by-example.html">Rust
Listing 20-28 mean; for the full macro pattern syntax, see the <a href="../reference/macros-by-example.html">Rust
Reference</a>.</p>
<p>First, we use a set of parentheses to encompass the whole pattern. We use a
dollar sign (<code>$</code>) to declare a variable in the macro system that will contain
@@ -321,17 +322,18 @@ macros do. The three kinds of procedural macros are custom derive,
attribute-like, and function-like, and all work in a similar fashion.</p>
<p>When creating procedural macros, the definitions must reside in their own crate
with a special crate type. This is for complex technical reasons that we hope
to eliminate in the future. In Listing 19-29, we show how to define a
to eliminate in the future. In Listing 20-29, we show how to define a
procedural macro, where <code>some_attribute</code> is a placeholder for using a specific
macro variety.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore">use proc_macro;
#[some_attribute]
pub fn some_name(input: TokenStream) -&gt; TokenStream {
}</code></pre>
<p><span class="caption">Listing 19-29: An example of defining a procedural
macro</span></p>
<figcaption>Listing 20-29: An example of defining a procedural macro</figcaption>
</figure>
<p>The function that defines a procedural macro takes a <code>TokenStream</code> as an input
and produces a <code>TokenStream</code> as an output. The <code>TokenStream</code> type is defined by
the <code>proc_macro</code> crate that is included with Rust and represents a sequence of
@@ -351,8 +353,9 @@ well provide a procedural macro so users can annotate their type with
<code>#[derive(HelloMacro)]</code> to get a default implementation of the <code>hello_macro</code>
function. The default implementation will print <code>Hello, Macro! My name is TypeName!</code> where <code>TypeName</code> is the name of the type on which this trait has
been defined. In other words, well write a crate that enables another
programmer to write code like Listing 19-30 using our crate.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
programmer to write code like Listing 20-30 using our crate.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;
@@ -362,17 +365,19 @@ struct Pancakes;
fn main() {
Pancakes::hello_macro();
}</code></pre>
<p><span class="caption">Listing 19-30: The code a user of our crate will be able
to write when using our procedural macro</span></p>
<figcaption>Listing 20-30: The code a user of our crate will be able to write when using our procedural macro</figcaption>
</figure>
<p>This code will print <code>Hello, Macro! My name is Pancakes!</code> when were done. The
first step is to make a new library crate, like this:</p>
<pre><code class="language-console">$ cargo new hello_macro --lib
</code></pre>
<p>Next, well define the <code>HelloMacro</code> trait and its associated function:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub trait HelloMacro {
fn hello_macro();
}</code></pre>
</figure>
<p>We have a trait and its function. At this point, our crate user could implement
the trait to achieve the desired functionality, like so:</p>
<pre><code class="language-rust ignore">use hello_macro::HelloMacro;
@@ -417,7 +422,8 @@ possible for programmers to use <code>hello_macro</code> even if they dont wa
Well also need functionality from the <code>syn</code> and <code>quote</code> crates, as youll see
in a moment, so we need to add them as dependencies. Add the following to the
<em>Cargo.toml</em> file for <code>hello_macro_derive</code>:</p>
<p><span class="filename">Filename: hello_macro_derive/Cargo.toml</span></p>
<figure class="listing">
<span class="file-name">Filename: hello_macro_derive/Cargo.toml</span>
<pre><code class="language-toml">[lib]
proc-macro = true
@@ -425,10 +431,12 @@ proc-macro = true
syn = "2.0"
quote = "1.0"
</code></pre>
<p>To start defining the procedural macro, place the code in Listing 19-31 into
</figure>
<p>To start defining the procedural macro, place the code in Listing 20-31 into
your <em>src/lib.rs</em> file for the <code>hello_macro_derive</code> crate. Note that this code
wont compile until we add a definition for the <code>impl_hello_macro</code> function.</p>
<p><span class="filename">Filename: hello_macro_derive/src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: hello_macro_derive/src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile">use proc_macro::TokenStream;
use quote::quote;
@@ -441,8 +449,8 @@ pub fn hello_macro_derive(input: TokenStream) -&gt; TokenStream {
// Build the trait implementation
impl_hello_macro(&amp;ast)
}</code></pre>
<p><span class="caption">Listing 19-31: Code that most procedural macro crates
will require in order to process Rust code</span></p>
<figcaption>Listing 20-31: Code that most procedural macro crates will require in order to process Rust code</figcaption>
</figure>
<p>Notice that weve split the code into the <code>hello_macro_derive</code> function, which
is responsible for parsing the <code>TokenStream</code>, and the <code>impl_hello_macro</code>
function, which is responsible for transforming the syntax tree: this makes
@@ -469,8 +477,9 @@ convention most procedural macros follow.</p>
<code>TokenStream</code> to a data structure that we can then interpret and perform
operations on. This is where <code>syn</code> comes into play. The <code>parse</code> function in
<code>syn</code> takes a <code>TokenStream</code> and returns a <code>DeriveInput</code> struct representing the
parsed Rust code. Listing 19-32 shows the relevant parts of the <code>DeriveInput</code>
parsed Rust code. Listing 20-32 shows the relevant parts of the <code>DeriveInput</code>
struct we get from parsing the <code>struct Pancakes;</code> string:</p>
<figure class="listing">
<pre><code class="language-rust ignore">DeriveInput {
// --snip--
@@ -488,8 +497,8 @@ struct we get from parsing the <code>struct Pancakes;</code> string:</p>
}
)
}</code></pre>
<p><span class="caption">Listing 19-32: The <code>DeriveInput</code> instance we get when
parsing the code that has the macros attribute in Listing 19-30</span></p>
<figcaption>Listing 20-32: The <code>DeriveInput</code> instance we get when parsing the code that has the macros attribute in Listing 20-30</figcaption>
</figure>
<p>The fields of this struct show that the Rust code weve parsed is a unit struct
with the <code>ident</code> (identifier, meaning the name) of <code>Pancakes</code>. There are more
fields on this struct for describing all sorts of Rust code; check the <a href="https://docs.rs/syn/2.0/syn/struct.DeriveInput.html"><code>syn</code>
@@ -509,8 +518,9 @@ conform to the procedural macro API. Weve simplified this example by using
about what went wrong by using <code>panic!</code> or <code>expect</code>.</p>
<p>Now that we have the code to turn the annotated Rust code from a <code>TokenStream</code>
into a <code>DeriveInput</code> instance, lets generate the code that implements the
<code>HelloMacro</code> trait on the annotated type, as shown in Listing 19-33.</p>
<p><span class="filename">Filename: hello_macro_derive/src/lib.rs</span></p>
<code>HelloMacro</code> trait on the annotated type, as shown in Listing 20-33.</p>
<figure class="listing">
<span class="file-name">Filename: hello_macro_derive/src/lib.rs</span>
<pre><code class="language-rust ignore"><span class="boring">use proc_macro::TokenStream;
</span><span class="boring">use quote::quote;
</span><span class="boring">
@@ -535,15 +545,15 @@ into a <code>DeriveInput</code> instance, lets generate the code that impleme
};
gen.into()
}</code></pre>
<p><span class="caption">Listing 19-33: Implementing the <code>HelloMacro</code> trait using
the parsed Rust code</span></p>
<figcaption>Listing 20-33: Implementing the <code>HelloMacro</code> trait using the parsed Rust code</figcaption>
</figure>
<p>We get an <code>Ident</code> struct instance containing the name (identifier) of the
annotated type using <code>ast.ident</code>. The struct in Listing 19-32 shows that when
we run the <code>impl_hello_macro</code> function on the code in Listing 19-30, the
annotated type using <code>ast.ident</code>. The struct in Listing 20-32 shows that when
we run the <code>impl_hello_macro</code> function on the code in Listing 20-30, the
<code>ident</code> we get will have the <code>ident</code> field with a value of <code>"Pancakes"</code>. Thus,
the <code>name</code> variable in Listing 19-33 will contain an <code>Ident</code> struct instance
the <code>name</code> variable in Listing 20-33 will contain an <code>Ident</code> struct instance
that, when printed, will be the string <code>"Pancakes"</code>, the name of the struct in
Listing 19-30.</p>
Listing 20-30.</p>
<p>The <code>quote!</code> macro lets us define the Rust code that we want to return. The
compiler expects something different to the direct result of the <code>quote!</code>
macros execution, so we need to convert it to a <code>TokenStream</code>. We do this by
@@ -567,7 +577,7 @@ expression to print literally, so we use <code>stringify!</code>. Using <code>st
saves an allocation by converting <code>#name</code> to a string literal at compile time.</p>
<p>At this point, <code>cargo build</code> should complete successfully in both <code>hello_macro</code>
and <code>hello_macro_derive</code>. Lets hook up these crates to the code in Listing
19-30 to see the procedural macro in action! Create a new binary project in
20-30 to see the procedural macro in action! Create a new binary project in
your <em>projects</em> directory using <code>cargo new pancakes</code>. We need to add
<code>hello_macro</code> and <code>hello_macro_derive</code> as dependencies in the <code>pancakes</code>
crates <em>Cargo.toml</em>. If youre publishing your versions of <code>hello_macro</code> and
@@ -576,7 +586,7 @@ dependencies; if not, you can specify them as <code>path</code> dependencies as
<pre><code class="language-toml">hello_macro = { path = "../hello_macro" }
hello_macro_derive = { path = "../hello_macro/hello_macro_derive" }
</code></pre>
<p>Put the code in Listing 19-30 into <em>src/main.rs</em>, and run <code>cargo run</code>: it
<p>Put the code in Listing 20-30 into <em>src/main.rs</em>, and run <code>cargo run</code>: it
should print <code>Hello, Macro! My name is Pancakes!</code> The implementation of the
<code>HelloMacro</code> trait from the procedural macro was included without the
<code>pancakes</code> crate needing to implement it; the <code>#[derive(HelloMacro)]</code> added the

View File

@@ -204,10 +204,11 @@ this. Lets make a new project in the usual fashion:</p>
Created binary (application) `hello` project
$ cd hello
</code></pre>
<p>Now enter the code in Listing 20-1 in <em>src/main.rs</em> to start. This code will
<p>Now enter the code in Listing 21-1 in <em>src/main.rs</em> to start. This code will
listen at the local address <code>127.0.0.1:7878</code> for incoming TCP streams. When it
gets an incoming stream, it will print <code>Connection established!</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021">use std::net::TcpListener;
fn main() {
@@ -219,8 +220,8 @@ fn main() {
println!("Connection established!");
}
}</code></pre></pre>
<p><span class="caption">Listing 20-1: Listening for incoming streams and printing
a message when we receive a stream</span></p>
<figcaption>Listing 21-1: Listening for incoming streams and printing a message when we receive a stream</figcaption>
</figure>
<p>Using <code>TcpListener</code>, we can listen for TCP connections at the address
<code>127.0.0.1:7878</code>. In the address, the section before the colon is an IP address
representing your computer (this is the same on every computer and doesnt
@@ -291,8 +292,9 @@ separate the concerns of first getting a connection and then taking some action
with the connection, well start a new function for processing connections. In
this new <code>handle_connection</code> function, well read data from the TCP stream and
print it so we can see the data being sent from the browser. Change the code to
look like Listing 20-2.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
look like Listing 21-2.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021">use std::{
io::{prelude::*, BufReader},
net::{TcpListener, TcpStream},
@@ -318,8 +320,8 @@ fn handle_connection(mut stream: TcpStream) {
println!("Request: {http_request:#?}");
}</code></pre></pre>
<p><span class="caption">Listing 20-2: Reading from the <code>TcpStream</code> and printing
the data</span></p>
<figcaption>Listing 21-2: Reading from the <code>TcpStream</code> and printing the data</figcaption>
</figure>
<p>We bring <code>std::io::prelude</code> and <code>std::io::BufReader</code> into scope to get access
to traits and types that let us read from and write to the stream. In the <code>for</code>
loop in the <code>main</code> function, instead of printing a message that says we made a
@@ -425,8 +427,9 @@ response.</p>
successful HTTP response. Lets write this to the stream as our response to a
successful request! From the <code>handle_connection</code> function, remove the
<code>println!</code> that was printing the request data and replace it with the code in
Listing 20-3.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
Listing 21-3.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">use std::{
</span><span class="boring"> io::{prelude::*, BufReader},
</span><span class="boring"> net::{TcpListener, TcpStream},
@@ -454,8 +457,8 @@ Listing 20-3.</p>
stream.write_all(response.as_bytes()).unwrap();
}</code></pre></pre>
<p><span class="caption">Listing 20-3: Writing a tiny successful HTTP response to
the stream</span></p>
<figcaption>Listing 21-3: Writing a tiny successful HTTP response to the stream</figcaption>
</figure>
<p>The first new line defines the <code>response</code> variable that holds the success
messages data. Then we call <code>as_bytes</code> on our <code>response</code> to convert the string
data to bytes. The <code>write_all</code> method on <code>stream</code> takes a <code>&amp;[u8]</code> and sends
@@ -470,9 +473,10 @@ request and sending a response!</p>
<h3 id="returning-real-html"><a class="header" href="#returning-real-html">Returning Real HTML</a></h3>
<p>Lets implement the functionality for returning more than a blank page. Create
the new file <em>hello.html</em> in the root of your project directory, not in the
<em>src</em> directory. You can input any HTML you want; Listing 20-4 shows one
<em>src</em> directory. You can input any HTML you want; Listing 21-4 shows one
possibility.</p>
<p><span class="filename">Filename: hello.html</span></p>
<figure class="listing">
<span class="file-name">Filename: hello.html</span>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
@@ -485,13 +489,14 @@ possibility.</p>
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><span class="caption">Listing 20-4: A sample HTML file to return in a
response</span></p>
<figcaption>Listing 21-4: A sample HTML file to return in a response</figcaption>
</figure>
<p>This is a minimal HTML5 document with a heading and some text. To return this
from the server when a request is received, well modify <code>handle_connection</code> as
shown in Listing 20-5 to read the HTML file, add it to the response as a body,
shown in Listing 21-5 to read the HTML file, add it to the response as a body,
and send it.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021">use std::{
fs,
io::{prelude::*, BufReader},
@@ -526,8 +531,8 @@ and send it.</p>
stream.write_all(response.as_bytes()).unwrap();
}</code></pre></pre>
<p><span class="caption">Listing 20-5: Sending the contents of <em>hello.html</em> as the
body of the response</span></p>
<figcaption>Listing 21-5: Sending the contents of <em>hello.html</em> as the body of the response</figcaption>
</figure>
<p>Weve added <code>fs</code> to the <code>use</code> statement to bring the standard librarys
filesystem module into scope. The code for reading the contents of a file to a
string should look familiar; we used it in Chapter 12 when we read the contents
@@ -550,10 +555,11 @@ request to <em>/</em>.</p>
client requested. Lets add functionality to check that the browser is
requesting <em>/</em> before returning the HTML file and return an error if the
browser requests anything else. For this we need to modify <code>handle_connection</code>,
as shown in Listing 20-6. This new code checks the content of the request
as shown in Listing 21-6. This new code checks the content of the request
received against what we know a request for <em>/</em> looks like and adds <code>if</code> and
<code>else</code> blocks to treat requests differently.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">use std::{
</span><span class="boring"> fs,
</span><span class="boring"> io::{prelude::*, BufReader},
@@ -589,14 +595,14 @@ fn handle_connection(mut stream: TcpStream) {
// some other request
}
}</code></pre></pre>
<p><span class="caption">Listing 20-6: Handling requests to <em>/</em> differently from
other requests</span></p>
<figcaption>Listing 21-6: Handling requests to <em>/</em> differently from other requests</figcaption>
</figure>
<p>Were only going to be looking at the first line of the HTTP request, so rather
than reading the entire request into a vector, were calling <code>next</code> to get the
first item from the iterator. The first <code>unwrap</code> takes care of the <code>Option</code> and
stops the program if the iterator has no items. The second <code>unwrap</code> handles the
<code>Result</code> and has the same effect as the <code>unwrap</code> that was in the <code>map</code> added in
Listing 20-2.</p>
Listing 21-2.</p>
<p>Next, we check the <code>request_line</code> to see if it equals the request line of a GET
request to the <em>/</em> path. If it does, the <code>if</code> block returns the contents of our
HTML file.</p>
@@ -606,12 +612,13 @@ a moment to respond to all other requests.</p>
<p>Run this code now and request <em>127.0.0.1:7878</em>; you should get the HTML in
<em>hello.html</em>. If you make any other request, such as
<em>127.0.0.1:7878/something-else</em>, youll get a connection error like those you
saw when running the code in Listing 20-1 and Listing 20-2.</p>
<p>Now lets add the code in Listing 20-7 to the <code>else</code> block to return a response
saw when running the code in Listing 21-1 and Listing 21-2.</p>
<p>Now lets add the code in Listing 21-7 to the <code>else</code> block to return a response
with the status code 404, which signals that the content for the request was
not found. Well also return some HTML for a page to render in the browser
indicating the response to the end user.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">use std::{
</span><span class="boring"> fs,
</span><span class="boring"> io::{prelude::*, BufReader},
@@ -655,14 +662,15 @@ indicating the response to the end user.</p>
stream.write_all(response.as_bytes()).unwrap();
}
<span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 20-7: Responding with status code 404 and an
error page if anything other than <em>/</em> was requested</span></p>
<figcaption>Listing 21-7: Responding with status code 404 and an error page if anything other than <em>/</em> was requested</figcaption>
</figure>
<p>Here, our response has a status line with status code 404 and the reason phrase
<code>NOT FOUND</code>. The body of the response will be the HTML in the file <em>404.html</em>.
Youll need to create a <em>404.html</em> file next to <em>hello.html</em> for the error
page; again feel free to use any HTML you want or use the example HTML in
Listing 20-8.</p>
<p><span class="filename">Filename: 404.html</span></p>
Listing 21-8.</p>
<figure class="listing">
<span class="file-name">Filename: 404.html</span>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
@@ -675,8 +683,8 @@ Listing 20-8.</p>
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><span class="caption">Listing 20-8: Sample content for the page to send back
with any 404 response</span></p>
<figcaption>Listing 21-8: Sample content for the page to send back with any 404 response</figcaption>
</figure>
<p>With these changes, run your server again. Requesting <em>127.0.0.1:7878</em> should
return the contents of <em>hello.html</em>, and any other request, like
<em>127.0.0.1:7878/foo</em>, should return the error HTML from <em>404.html</em>.</p>
@@ -687,9 +695,10 @@ differences are the status line and the filename. Lets make the code more
concise by pulling out those differences into separate <code>if</code> and <code>else</code> lines
that will assign the values of the status line and the filename to variables;
we can then use those variables unconditionally in the code to read the file
and write the response. Listing 20-9 shows the resulting code after replacing
and write the response. Listing 21-9 shows the resulting code after replacing
the large <code>if</code> and <code>else</code> blocks.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">use std::{
</span><span class="boring"> fs,
</span><span class="boring"> io::{prelude::*, BufReader},
@@ -726,18 +735,18 @@ fn handle_connection(mut stream: TcpStream) {
stream.write_all(response.as_bytes()).unwrap();
}</code></pre></pre>
<p><span class="caption">Listing 20-9: Refactoring the <code>if</code> and <code>else</code> blocks to
contain only the code that differs between the two cases</span></p>
<figcaption>Listing 21-9: Refactoring the <code>if</code> and <code>else</code> blocks to contain only the code that differs between the two cases</figcaption>
</figure>
<p>Now the <code>if</code> and <code>else</code> blocks only return the appropriate values for the
status line and filename in a tuple; we then use destructuring to assign these
two values to <code>status_line</code> and <code>filename</code> using a pattern in the <code>let</code>
statement, as discussed in Chapter 18.</p>
statement, as discussed in Chapter 19.</p>
<p>The previously duplicated code is now outside the <code>if</code> and <code>else</code> blocks and
uses the <code>status_line</code> and <code>filename</code> variables. This makes it easier to see
the difference between the two cases, and it means we have only one place to
update the code if we want to change how the file reading and response writing
work. The behavior of the code in Listing 20-9 will be the same as that in
Listing 20-7.</p>
work. The behavior of the code in Listing 21-9 will be the same as that in
Listing 21-7.</p>
<p>Awesome! We now have a simple web server in approximately 40 lines of Rust code
that responds to one request with a page of content and responds to all other
requests with a 404 response.</p>

View File

@@ -190,10 +190,11 @@ finished, even if the new requests can be processed quickly. Well need to fix
this, but first, well look at the problem in action.</p>
<h3 id="simulating-a-slow-request-in-the-current-server-implementation"><a class="header" href="#simulating-a-slow-request-in-the-current-server-implementation">Simulating a Slow Request in the Current Server Implementation</a></h3>
<p>Well look at how a slow-processing request can affect other requests made to
our current server implementation. Listing 20-10 implements handling a request
our current server implementation. Listing 21-10 implements handling a request
to <em>/sleep</em> with a simulated slow response that will cause the server to sleep
for 5 seconds before responding.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021">use std::{
fs,
io::{prelude::*, BufReader},
@@ -238,16 +239,16 @@ fn handle_connection(mut stream: TcpStream) {
</span><span class="boring">
</span><span class="boring"> stream.write_all(response.as_bytes()).unwrap();
</span>}</code></pre></pre>
<p><span class="caption">Listing 20-10: Simulating a slow request by sleeping for
5 seconds</span></p>
<figcaption>Listing 21-10: Simulating a slow request by sleeping for 5 seconds</figcaption>
</figure>
<p>We switched from <code>if</code> to <code>match</code> now that we have three cases. We need to
explicitly match on a slice of <code>request_line</code> to pattern match against the
string literal values; <code>match</code> doesnt do automatic referencing and
dereferencing like the equality method does.</p>
<p>The first arm is the same as the <code>if</code> block from Listing 20-9. The second arm
<p>The first arm is the same as the <code>if</code> block from Listing 21-9. The second arm
matches a request to <em>/sleep</em>. When that request is received, the server will
sleep for 5 seconds before rendering the successful HTML page. The third arm is
the same as the <code>else</code> block from Listing 20-9.</p>
the same as the <code>else</code> block from Listing 21-9.</p>
<p>You can see how primitive our server is: real libraries would handle the
recognition of multiple requests in a much less verbose way!</p>
<p>Start the server using <code>cargo run</code>. Then open two browser windows: one for
@@ -305,9 +306,10 @@ every connection. As mentioned earlier, this isnt our final plan due to the
problems with potentially spawning an unlimited number of threads, but it is a
starting point to get a working multithreaded server first. Then well add the
thread pool as an improvement, and contrasting the two solutions will be
easier. Listing 20-11 shows the changes to make to <code>main</code> to spawn a new thread
easier. Listing 21-11 shows the changes to make to <code>main</code> to spawn a new thread
to handle each stream within the <code>for</code> loop.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">use std::{
</span><span class="boring"> fs,
</span><span class="boring"> io::{prelude::*, BufReader},
@@ -349,8 +351,8 @@ to handle each stream within the <code>for</code> loop.</p>
</span><span class="boring">
</span><span class="boring"> stream.write_all(response.as_bytes()).unwrap();
</span><span class="boring">}</span></code></pre></pre>
<p><span class="caption">Listing 20-11: Spawning a new thread for each
stream</span></p>
<figcaption>Listing 21-11: Spawning a new thread for each stream</figcaption>
</figure>
<p>As you learned in Chapter 16, <code>thread::spawn</code> will create a new thread and then
run the code in the closure in the new thread. If you run this code and load
<em>/sleep</em> in your browser, then <em>/</em> in two more browser tabs, youll indeed see
@@ -362,9 +364,10 @@ new threads without any limit.</p>
<h4 id="creating-a-finite-number-of-threads"><a class="header" href="#creating-a-finite-number-of-threads">Creating a Finite Number of Threads</a></h4>
<p>We want our thread pool to work in a similar, familiar way so switching from
threads to a thread pool doesnt require large changes to the code that uses
our API. Listing 20-12 shows the hypothetical interface for a <code>ThreadPool</code>
our API. Listing 21-12 shows the hypothetical interface for a <code>ThreadPool</code>
struct we want to use instead of <code>thread::spawn</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::{
</span><span class="boring"> fs,
</span><span class="boring"> io::{prelude::*, BufReader},
@@ -407,7 +410,8 @@ struct we want to use instead of <code>thread::spawn</code>.</p>
</span><span class="boring">
</span><span class="boring"> stream.write_all(response.as_bytes()).unwrap();
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-12: Our ideal <code>ThreadPool</code> interface</span></p>
<figcaption>Listing 21-12: Our ideal <code>ThreadPool</code> interface</figcaption>
</figure>
<p>We use <code>ThreadPool::new</code> to create a new thread pool with a configurable number
of threads, in this case four. Then, in the <code>for</code> loop, <code>pool.execute</code> has a
similar interface as <code>thread::spawn</code> in that it takes a closure the pool should
@@ -417,7 +421,7 @@ compile, but well try so the compiler can guide us in how to fix it.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="building-the-threadpool-struct-using-compiler-driven-development"></a></p>
<h4 id="building-threadpool-using-compiler-driven-development"><a class="header" href="#building-threadpool-using-compiler-driven-development">Building <code>ThreadPool</code> Using Compiler Driven Development</a></h4>
<p>Make the changes in Listing 20-12 to <em>src/main.rs</em>, and then lets use the
<p>Make the changes in Listing 21-12 to <em>src/main.rs</em>, and then lets use the
compiler errors from <code>cargo check</code> to drive our development. Here is the first
error we get:</p>
<pre><code class="language-console">$ cargo check
@@ -440,11 +444,14 @@ library for any work we want to do using a thread pool, not just for serving
web requests.</p>
<p>Create a <em>src/lib.rs</em> that contains the following, which is the simplest
definition of a <code>ThreadPool</code> struct that we can have for now:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub struct ThreadPool;</code></pre>
</figure>
<p>Then edit <em>main.rs</em> file to bring <code>ThreadPool</code> into scope from the library
crate by adding the following code to the top of <em>src/main.rs</em>:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore">use hello::ThreadPool;
<span class="boring">use std::{
</span><span class="boring"> fs,
@@ -488,6 +495,7 @@ crate by adding the following code to the top of <em>src/main.rs</em>:</p>
</span><span class="boring">
</span><span class="boring"> stream.write_all(response.as_bytes()).unwrap();
</span><span class="boring">}</span></code></pre>
</figure>
<p>This code still wont work, but lets check it again to get the next error that
we need to address:</p>
<pre><code class="language-console">$ cargo check
@@ -506,7 +514,8 @@ error: could not compile `hello` (bin "hello") due to 1 previous error
that can accept <code>4</code> as an argument and should return a <code>ThreadPool</code> instance.
Lets implement the simplest <code>new</code> function that will have those
characteristics:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub struct ThreadPool;
impl ThreadPool {
@@ -514,6 +523,7 @@ impl ThreadPool {
ThreadPool
}
}</code></pre>
</figure>
<p>We chose <code>usize</code> as the type of the <code>size</code> parameter, because we know that a
negative number of threads doesnt make any sense. We also know well use this
4 as the number of elements in a collection of threads, which is what the
@@ -562,7 +572,8 @@ requests closure one time, which matches the <code>Once</code> in <code>FnOnc
closure from one thread to another and <code>'static</code> because we dont know how long
the thread will take to execute. Lets create an <code>execute</code> method on
<code>ThreadPool</code> that will take a generic parameter of type <code>F</code> with these bounds:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct ThreadPool;
</span><span class="boring">
</span>impl ThreadPool {
@@ -577,6 +588,7 @@ the thread will take to execute. Lets create an <code>execute</code> method o
{
}
}</code></pre>
</figure>
<p>We still use the <code>()</code> after <code>FnOnce</code> because this <code>FnOnce</code> represents a closure
that takes no parameters and returns the unit type <code>()</code>. Just like function
definitions, the return type can be omitted from the signature, but even if we
@@ -607,8 +619,9 @@ parameter, because a pool with a negative number of threads makes no sense.
However, a pool with zero threads also makes no sense, yet zero is a perfectly
valid <code>usize</code>. Well add code to check that <code>size</code> is greater than zero before
we return a <code>ThreadPool</code> instance and have the program panic if it receives a
zero by using the <code>assert!</code> macro, as shown in Listing 20-13.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
zero by using the <code>assert!</code> macro, as shown in Listing 21-13.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">pub struct ThreadPool;
</span><span class="boring">
</span>impl ThreadPool {
@@ -632,8 +645,8 @@ zero by using the <code>assert!</code> macro, as shown in Listing 20-13.</p>
</span><span class="boring"> {
</span><span class="boring"> }
</span>}</code></pre>
<p><span class="caption">Listing 20-13: Implementing <code>ThreadPool::new</code> to panic if
<code>size</code> is zero</span></p>
<figcaption>Listing 21-13: Implementing <code>ThreadPool::new</code> to panic if <code>size</code> is zero</figcaption>
</figure>
<p>Weve also added some documentation for our <code>ThreadPool</code> with doc comments.
Note that we followed good documentation practices by adding a section that
calls out the situations in which our function can panic, as discussed in
@@ -660,12 +673,13 @@ look at the <code>thread::spawn</code> signature:</p>
closure returns. Lets try using <code>JoinHandle</code> too and see what happens. In our
case, the closures were passing to the thread pool will handle the connection
and not return anything, so <code>T</code> will be the unit type <code>()</code>.</p>
<p>The code in Listing 20-14 will compile but doesnt create any threads yet.
<p>The code in Listing 21-14 will compile but doesnt create any threads yet.
Weve changed the definition of <code>ThreadPool</code> to hold a vector of
<code>thread::JoinHandle&lt;()&gt;</code> instances, initialized the vector with a capacity of
<code>size</code>, set up a <code>for</code> loop that will run some code to create the threads, and
returned a <code>ThreadPool</code> instance containing them.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore not_desired_behavior">use std::thread;
pub struct ThreadPool {
@@ -700,8 +714,8 @@ impl ThreadPool {
</span><span class="boring"> {
</span><span class="boring"> }
</span>}</code></pre>
<p><span class="caption">Listing 20-14: Creating a vector for <code>ThreadPool</code> to hold
the threads</span></p>
<figcaption>Listing 21-14: Creating a vector for <code>ThreadPool</code> to hold the threads</figcaption>
</figure>
<p>Weve brought <code>std::thread</code> into scope in the library crate, because were
using <code>thread::JoinHandle</code> as the type of the items in the vector in
<code>ThreadPool</code>.</p>
@@ -713,7 +727,7 @@ this allocation up front is slightly more efficient than using <code>Vec::new</c
which resizes itself as elements are inserted.</p>
<p>When you run <code>cargo check</code> again, it should succeed.</p>
<h4 id="a-worker-struct-responsible-for-sending-code-from-the-threadpool-to-a-thread"><a class="header" href="#a-worker-struct-responsible-for-sending-code-from-the-threadpool-to-a-thread">A <code>Worker</code> Struct Responsible for Sending Code from the <code>ThreadPool</code> to a Thread</a></h4>
<p>We left a comment in the <code>for</code> loop in Listing 20-14 regarding the creation of
<p>We left a comment in the <code>for</code> loop in Listing 21-14 regarding the creation of
threads. Here, well look at how we actually create threads. The standard
library provides <code>thread::spawn</code> as a way to create threads, and
<code>thread::spawn</code> expects to get some code the thread should run as soon as the
@@ -747,9 +761,10 @@ closure.</li>
a new <code>Worker</code> with that <code>id</code>, and store the worker in the vector.</li>
</ol>
<p>If youre up for a challenge, try implementing these changes on your own before
looking at the code in Listing 20-15.</p>
<p>Ready? Here is Listing 20-15 with one way to make the preceding modifications.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
looking at the code in Listing 21-15.</p>
<p>Ready? Here is Listing 21-15 with one way to make the preceding modifications.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::thread;
pub struct ThreadPool {
@@ -797,8 +812,8 @@ impl Worker {
Worker { id, thread }
}
}</code></pre>
<p><span class="caption">Listing 20-15: Modifying <code>ThreadPool</code> to hold <code>Worker</code>
instances instead of holding threads directly</span></p>
<figcaption>Listing 21-15: Modifying <code>ThreadPool</code> to hold <code>Worker</code> instances instead of holding threads directly</figcaption>
</figure>
<p>Weve changed the name of the field on <code>ThreadPool</code> from <code>threads</code> to <code>workers</code>
because its now holding <code>Worker</code> instances instead of <code>JoinHandle&lt;()&gt;</code>
instances. We use the counter in the <code>for</code> loop as an argument to
@@ -842,10 +857,11 @@ sender.</li>
closures of any jobs it receives.</li>
</ol>
<p>Lets start by creating a channel in <code>ThreadPool::new</code> and holding the sender
in the <code>ThreadPool</code> instance, as shown in Listing 20-16. The <code>Job</code> struct
in the <code>ThreadPool</code> instance, as shown in Listing 21-16. The <code>Job</code> struct
doesnt hold anything for now but will be the type of item were sending down
the channel.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::{sync::mpsc, thread};
pub struct ThreadPool {
@@ -898,15 +914,16 @@ impl ThreadPool {
</span><span class="boring"> Worker { id, thread }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-16: Modifying <code>ThreadPool</code> to store the
sender of a channel that transmits <code>Job</code> instances</span></p>
<figcaption>Listing 21-16: Modifying <code>ThreadPool</code> to store the sender of a channel that transmits <code>Job</code> instances</figcaption>
</figure>
<p>In <code>ThreadPool::new</code>, we create our new channel and have the pool hold the
sender. This will successfully compile.</p>
<p>Lets try passing a receiver of the channel into each worker as the thread pool
creates the channel. We know we want to use the receiver in the thread that the
workers spawn, so well reference the <code>receiver</code> parameter in the closure. The
code in Listing 20-17 wont quite compile yet.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
code in Listing 21-17 wont quite compile yet.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::{sync::mpsc, thread};
</span><span class="boring">
</span><span class="boring">pub struct ThreadPool {
@@ -964,7 +981,8 @@ code in Listing 20-17 wont quite compile yet.</p>
Worker { id, thread }
}
}</code></pre>
<p><span class="caption">Listing 20-17: Passing the receiver to the workers</span></p>
<figcaption>Listing 21-17: Passing the receiver to the workers</figcaption>
</figure>
<p>Weve made some small and straightforward changes: we pass the receiver into
<code>Worker::new</code>, and then we use it inside the closure.</p>
<p>When we try to check this code, we get this error:</p>
@@ -1009,8 +1027,9 @@ otherwise, we might get race conditions (as covered in Chapter 16).</p>
ownership across multiple threads and allow the threads to mutate the value, we
need to use <code>Arc&lt;Mutex&lt;T&gt;&gt;</code>. The <code>Arc</code> type will let multiple workers own the
receiver, and <code>Mutex</code> will ensure that only one worker gets a job from the
receiver at a time. Listing 20-18 shows the changes we need to make.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
receiver at a time. Listing 21-18 shows the changes we need to make.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::{
sync::{mpsc, Arc, Mutex},
thread,
@@ -1075,8 +1094,8 @@ receiver at a time. Listing 20-18 shows the changes we need to make.</p>
</span><span class="boring"> Worker { id, thread }
</span> }
}</code></pre>
<p><span class="caption">Listing 20-18: Sharing the receiver among the workers
using <code>Arc</code> and <code>Mutex</code></span></p>
<figcaption>Listing 21-18: Sharing the receiver among the workers using <code>Arc</code> and <code>Mutex</code></figcaption>
</figure>
<p>In <code>ThreadPool::new</code>, we put the receiver in an <code>Arc</code> and a <code>Mutex</code>. For each
new worker, we clone the <code>Arc</code> to bump the reference count so the workers can
share ownership of the receiver.</p>
@@ -1086,9 +1105,10 @@ share ownership of the receiver.</p>
<code>Job</code> from a struct to a type alias for a trait object that holds the type of
closure that <code>execute</code> receives. As discussed in the <a href="ch20-04-advanced-types.html#creating-type-synonyms-with-type-aliases">“Creating Type Synonyms
with Type Aliases”</a><!-- ignore -->
section of Chapter 19, type aliases allow us to make long types shorter for
ease of use. Look at Listing 20-19.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
section of Chapter 20, type aliases allow us to make long types shorter for
ease of use. Look at Listing 21-19.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -1154,8 +1174,8 @@ impl ThreadPool {
</span><span class="boring"> Worker { id, thread }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-19: Creating a <code>Job</code> type alias for a <code>Box</code>
that holds each closure and then sending the job down the channel</span></p>
<figcaption>Listing 21-19: Creating a <code>Job</code> type alias for a <code>Box</code> that holds each closure and then sending the job down the channel</figcaption>
</figure>
<p>After creating a new <code>Job</code> instance using the closure we get in <code>execute</code>, we
send that job down the sending end of the channel. Were calling <code>unwrap</code> on
<code>send</code> for the case that sending fails. This might happen if, for example, we
@@ -1168,8 +1188,9 @@ compiler doesnt know that.</p>
<code>thread::spawn</code> still only <em>references</em> the receiving end of the channel.
Instead, we need the closure to loop forever, asking the receiving end of the
channel for a job and running the job when it gets one. Lets make the change
shown in Listing 20-20 to <code>Worker::new</code>.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
shown in Listing 21-20 to <code>Worker::new</code>.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -1236,8 +1257,8 @@ impl Worker {
Worker { id, thread }
}
}</code></pre>
<p><span class="caption">Listing 20-20: Receiving and executing the jobs in the
workers thread</span></p>
<figcaption>Listing 21-20: Receiving and executing the jobs in the workers thread</figcaption>
</figure>
<p>Here, we first call <code>lock</code> on the <code>receiver</code> to acquire the mutex, and then we
call <code>unwrap</code> to panic on any errors. Acquiring a lock might fail if the mutex
is in a <em>poisoned</em> state, which can happen if some other thread panicked while
@@ -1255,7 +1276,7 @@ wait until a job becomes available. The <code>Mutex&lt;T&gt;</code> ensures that
<p>Our thread pool is now in a working state! Give it a <code>cargo run</code> and make some
requests:</p>
<!-- manual-regeneration
cd listings/ch20-web-server/listing-20-20
cd listings/ch21-web-server/listing-21-20
cargo run
make some requests to 127.0.0.1:7878
Can't automate because the output depends on making requests
@@ -1307,9 +1328,10 @@ might load one at a time in 5 second intervals. Some web browsers execute
multiple instances of the same request sequentially for caching reasons. This
limitation is not caused by our web server.</p>
</section>
<p>After learning about the <code>while let</code> loop in Chapter 18, you might be wondering
why we didnt write the worker thread code as shown in Listing 20-21.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<p>After learning about the <code>while let</code> loop in Chapters 17 and 18, you might be
wondering why we didnt write the worker thread code as shown in Listing 21-21.</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore not_desired_behavior"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -1375,8 +1397,8 @@ impl Worker {
Worker { id, thread }
}
}</code></pre>
<p><span class="caption">Listing 20-21: An alternative implementation of
<code>Worker::new</code> using <code>while let</code></span></p>
<figcaption>Listing 21-21: An alternative implementation of <code>Worker::new</code> using <code>while let</code></figcaption>
</figure>
<p>This code compiles and runs but doesnt result in the desired threading
behavior: a slow request will still cause other requests to wait to be
processed. The reason is somewhat subtle: the <code>Mutex</code> struct has no public
@@ -1387,10 +1409,10 @@ that a resource guarded by a <code>Mutex</code> cannot be accessed unless we hol
lock. However, this implementation can also result in the lock being held
longer than intended if we arent mindful of the lifetime of the
<code>MutexGuard&lt;T&gt;</code>.</p>
<p>The code in Listing 20-20 that uses <code>let job = receiver.lock().unwrap().recv().unwrap();</code> works because with <code>let</code>, any
<p>The code in Listing 21-20 that uses <code>let job = receiver.lock().unwrap().recv().unwrap();</code> works because with <code>let</code>, any
temporary values used in the expression on the right hand side of the equals
sign are immediately dropped when the <code>let</code> statement ends. However, <code>while let</code> (and <code>if let</code> and <code>match</code>) does not drop temporary values until the end of
the associated block. In Listing 20-21, the lock remains held for the duration
the associated block. In Listing 21-21, the lock remains held for the duration
of the call to <code>job()</code>, meaning other workers cannot receive jobs.</p>
</main>

View File

@@ -181,7 +181,7 @@
<div id="content" class="content">
<main>
<h2 id="graceful-shutdown-and-cleanup"><a class="header" href="#graceful-shutdown-and-cleanup">Graceful Shutdown and Cleanup</a></h2>
<p>The code in Listing 20-20 is responding to requests asynchronously through the
<p>The code in Listing 21-20 is responding to requests asynchronously through the
use of a thread pool, as we intended. We get some warnings about the <code>workers</code>,
<code>id</code>, and <code>thread</code> fields that were not using in a direct way that reminds us
were not cleaning up anything. When we use the less elegant
@@ -197,9 +197,10 @@ thread pool.</p>
<h3 id="implementing-the-drop-trait-on-threadpool"><a class="header" href="#implementing-the-drop-trait-on-threadpool">Implementing the <code>Drop</code> Trait on <code>ThreadPool</code></a></h3>
<p>Lets start with implementing <code>Drop</code> on our thread pool. When the pool is
dropped, our threads should all join to make sure they finish their work.
Listing 20-22 shows a first attempt at a <code>Drop</code> implementation; this code wont
Listing 21-22 shows a first attempt at a <code>Drop</code> implementation; this code wont
quite work yet.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -274,8 +275,8 @@ quite work yet.</p>
</span><span class="boring"> Worker { id, thread }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-22: Joining each thread when the thread pool
goes out of scope</span></p>
<figcaption>Listing 21-22: Joining each thread when the thread pool goes out of scope</figcaption>
</figure>
<p>First, we loop through each of the thread pool <code>workers</code>. We use <code>&amp;mut</code> for
this because <code>self</code> is a mutable reference, and we also need to be able to
mutate <code>worker</code>. For each worker, we print a message saying that this
@@ -310,7 +311,8 @@ will have a <code>Some</code> variant in <code>thread</code>, and when we want t
<code>Worker</code>, well replace <code>Some</code> with <code>None</code> so the <code>Worker</code> doesnt have a
thread to run.</p>
<p>So we know we want to update the definition of <code>Worker</code> like this:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -385,6 +387,7 @@ thread to run.</p>
</span><span class="boring"> Worker { id, thread }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
</figure>
<p>Now lets lean on the compiler to find the other places that need to change.
Checking this code, we get two errors:</p>
<pre><code class="language-console">$ cargo check
@@ -422,7 +425,8 @@ error: could not compile `hello` (lib) due to 2 previous errors
<p>Lets address the second error, which points to the code at the end of
<code>Worker::new</code>; we need to wrap the <code>thread</code> value in <code>Some</code> when we create a
new <code>Worker</code>. Make the following changes to fix this error:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -502,10 +506,12 @@ new <code>Worker</code>. Make the following changes to fix this error:</p>
}
}
}</code></pre>
</figure>
<p>The first error is in our <code>Drop</code> implementation. We mentioned earlier that we
intended to call <code>take</code> on the <code>Option</code> value to move <code>thread</code> out of <code>worker</code>.
The following changes will do so:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore not_desired_behavior"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -585,7 +591,8 @@ The following changes will do so:</p>
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p>As discussed in Chapter 17, the <code>take</code> method on <code>Option</code> takes the <code>Some</code>
</figure>
<p>As discussed in Chapter 18, the <code>take</code> method on <code>Option</code> takes the <code>Some</code>
variant out and leaves <code>None</code> in its place. Were using <code>if let</code> to destructure
the <code>Some</code> and get the thread; then we call <code>join</code> on the thread. If a workers
thread is already <code>None</code>, we know that worker has already had its thread
@@ -601,11 +608,12 @@ block forever waiting for the first thread to finish.</p>
<p>To fix this problem, well need a change in the <code>ThreadPool</code> <code>drop</code>
implementation and then a change in the <code>Worker</code> loop.</p>
<p>First, well change the <code>ThreadPool</code> <code>drop</code> implementation to explicitly drop
the <code>sender</code> before waiting for the threads to finish. Listing 20-23 shows the
the <code>sender</code> before waiting for the threads to finish. Listing 21-23 shows the
changes to <code>ThreadPool</code> to explicitly drop <code>sender</code>. We use the same <code>Option</code>
and <code>take</code> technique as we did with the thread to be able to move <code>sender</code> out
of <code>ThreadPool</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground not_desired_behavior"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -693,14 +701,15 @@ impl Drop for ThreadPool {
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-23: Explicitly drop <code>sender</code> before joining
the worker threads</span></p>
<figcaption>Listing 21-23: Explicitly drop <code>sender</code> before joining the worker threads</figcaption>
</figure>
<p>Dropping <code>sender</code> closes the channel, which indicates no more messages will be
sent. When that happens, all the calls to <code>recv</code> that the workers do in the
infinite loop will return an error. In Listing 20-24, we change the <code>Worker</code>
infinite loop will return an error. In Listing 21-24, we change the <code>Worker</code>
loop to gracefully exit the loop in that case, which means the threads will
finish when the <code>ThreadPool</code> <code>drop</code> implementation calls <code>join</code> on them.</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground"><span class="boring">use std::{
</span><span class="boring"> sync::{mpsc, Arc, Mutex},
</span><span class="boring"> thread,
@@ -793,11 +802,12 @@ finish when the <code>ThreadPool</code> <code>drop</code> implementation calls <
}
}
}</code></pre>
<p><span class="caption">Listing 20-24: Explicitly break out of the loop when
<code>recv</code> returns an error</span></p>
<figcaption>Listing 21-24: Explicitly break out of the loop when <code>recv</code> returns an error</figcaption>
</figure>
<p>To see this code in action, lets modify <code>main</code> to accept only two requests
before gracefully shutting down the server, as shown in Listing 20-25.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
before gracefully shutting down the server, as shown in Listing 21-25.</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore"><span class="boring">use hello::ThreadPool;
</span><span class="boring">use std::{
</span><span class="boring"> fs,
@@ -843,8 +853,8 @@ before gracefully shutting down the server, as shown in Listing 20-25.</p>
</span><span class="boring">
</span><span class="boring"> stream.write_all(response.as_bytes()).unwrap();
</span><span class="boring">}</span></code></pre>
<p><span class="caption">Listing 20-25: Shut down the server after serving two
requests by exiting the loop</span></p>
<figcaption>Listing 21-25: Shut down the server after serving two requests by exiting the loop</figcaption>
</figure>
<p>You wouldnt want a real-world web server to shut down after serving only two
requests. This code just demonstrates that the graceful shutdown and cleanup is
in working order.</p>
@@ -854,7 +864,7 @@ end of <code>main</code>, and the <code>drop</code> implementation will run.</p>
<p>Start the server with <code>cargo run</code>, and make three requests. The third request
should error, and in your terminal you should see output similar to this:</p>
<!-- manual-regeneration
cd listings/ch20-web-server/listing-20-25
cd listings/ch21-web-server/listing-21-25
cargo run
curl http://127.0.0.1:7878
curl http://127.0.0.1:7878
@@ -897,7 +907,8 @@ all exited their loops and stopped.</p>
a thread pool to respond asynchronously. Were able to perform a graceful
shutdown of the server, which cleans up all the threads in the pool.</p>
<p>Heres the full code for reference:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore">use hello::ThreadPool;
use std::{
fs,
@@ -943,7 +954,9 @@ fn handle_connection(mut stream: TcpStream) {
stream.write_all(response.as_bytes()).unwrap();
}</code></pre>
<p><span class="filename">Filename: src/lib.rs</span></p>
</figure>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::{
sync::{mpsc, Arc, Mutex},
thread,
@@ -1036,6 +1049,7 @@ impl Worker {
}
}
}</code></pre>
</figure>
<p>We could do more here! If you want to continue enhancing this project, here are
some ideas:</p>
<ul>

1148
print.html

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long