@ -159,23 +159,24 @@ program only operated on values between 1 and 100, and it had many functions
@@ -159,23 +159,24 @@ program only operated on values between 1 and 100, and it had many functions
with this requirement, having a check like this in every function would be
tedious (and might impact performance).
Instead, we can make a new type and put the validations in a function to create
an instance of the type rather than repeating the validations everywhere. That
way, it’s safe for functions to use the new type in their signatures and
confidently use the values they receive. Listing 9-13 shows one way to define a
`Guess` type that will only create an instance of `Guess` if the `new` function
receives a value between 1 and 100.
Instead, we can make a new type in a dedicated module and put the validations in
a function to create an instance of the type rather than repeating the
validations everywhere. That way, it’s safe for functions to use the new type in
their signatures and confidently use the values they receive. Listing 9-13 shows
one way to define a `Guess` type that will only create an instance of `Guess` if
the `new` function receives a value between 1 and 100.
<Listingnumber="9-13"caption="A `Guess` type that will only continue with values between 1 and 100">
<Listingnumber="9-13"caption="A `Guess` type that will only continue with values between 1 and 100"file-name="src/guessing_game.rs">
First we define a struct named `Guess` that has a field named `value` that
holds an `i32`. This is where the number will be stored.
First we create a new module named `guessing_game`. Next we define a struct in
that module named `Guess` that has a field named `value` that holds an `i32`.
This is where the number will be stored.
Then we implement an associated function named `new` on `Guess` that creates
instances of `Guess` values. The `new` function is defined to have one
@ -197,9 +198,9 @@ a _getter_ because its purpose is to get some data from its fields and return
@@ -197,9 +198,9 @@ a _getter_ because its purpose is to get some data from its fields and return
it. This public method is necessary because the `value` field of the `Guess`
struct is private. It’s important that the `value` field be private so code
using the `Guess` struct is not allowed to set `value` directly: code outside
the module _must_ use the `Guess::new` function to create an instance of
`Guess`, thereby ensuring there’s no way for a `Guess` to have a`value` that
hasn’t been checked by the conditions in the `Guess::new` function.
the `guessing_game`module _must_ use the `Guess::new` function to create an
instance of `Guess`, thereby ensuring there’s no way for a `Guess` to have a
`value` that hasn’t been checked by the conditions in the `Guess::new` function.
A function that has a parameter or returns only numbers between 1 and 100 could
then declare in its signature that it takes or returns a `Guess` rather than an
@ -55,7 +55,7 @@ same type `T`.
@@ -55,7 +55,7 @@ same type `T`.
Listing 10-5 shows the combined `largest` function definition using the generic
data type in its signature. The listing also shows how we can call the function
with either a slice of `i32` values or `char` values. Note that this code won’t
compile yet, but we’ll fix it later in this chapter.
compile yet.
<Listingnumber="10-5"file-name="src/main.rs"caption="The `largest` function using generic type parameters; this doesn’t compile yet">
@ -77,10 +77,10 @@ states that the body of `largest` won’t work for all possible types that `T`
@@ -77,10 +77,10 @@ states that the body of `largest` won’t work for all possible types that `T`
could be. Because we want to compare values of type `T` in the body, we can
only use types whose values can be ordered. To enable comparisons, the standard
library has the `std::cmp::PartialOrd` trait that you can implement on types
(see Appendix C for more on this trait). By following the help text’s
suggestion, we restrict the types valid for `T` to only those that implement
`PartialOrd` and this example will compile, because the standard library
implements `PartialOrd` on both `i32` and `char`.
(see Appendix C for more on this trait). To fix the example code above, we would
need to follow the help text's suggestions and restrict the types valid for `T`
to only those that implement `PartialOrd`. The example would then compile, because
the standard library implements `PartialOrd` on both `i32` and `char`.
@ -196,9 +196,9 @@ tell us that the first async block (`src/main.rs:8:23: 20:10`) does not
@@ -196,9 +196,9 @@ tell us that the first async block (`src/main.rs:8:23: 20:10`) does not
implement the `Unpin` trait and suggests using `pin!` or `Box::pin` to resolve
it. Later in the chapter, we’ll dig into a few more details about `Pin` and
`Unpin`. For the moment, though, we can just follow the compiler’s advice to get
unstuck. In Listing 17-18, we start by updating the type annotation for
`futures`, with a `Pin` wrapping each `Box`. Second, we use `Box::pin` to pin
the futures themselves.
unstuck. In Listing 17-18, we start by importing `Pin` from `std::pin`. Next we
update the type annotation for `futures`, with a `Pin` wrapping each `Box`.
Finally, we use `Box::pin` to pin the futures themselves.
<Listingnumber="17-18"caption="Using `Pin` and `Box::pin` to make the `Vec` type check"file-name="src/main.rs">
@ -238,9 +238,10 @@ future, using the `std::pin::pin` macro.
@@ -238,9 +238,10 @@ future, using the `std::pin::pin` macro.
However, we must still be explicit about the type of the pinned reference;
otherwise, Rust will still not know to interpret these as dynamic trait objects,
which is what we need them to be in the `Vec`. We therefore `pin!` each future
when we define it, and define `futures` as a `Vec` containing pinned mutable
references to the dynamic future type, as in Listing 17-19.
which is what we need them to be in the `Vec`. We therefore add `pin` to our
list of imports from `std::pin`. Then we can `pin!` each future when we define
it and define `futures` as a `Vec` containing pinned mutable references to the
dynamic future type, as in Listing 17-19.
<Listingnumber="17-19"caption="Using `Pin` directly with the `pin!` macro to avoid unnecessary heap allocations"file-name="src/main.rs">
@ -359,11 +359,12 @@ known at compile time. (This is one of the dyn compatibility rules mentioned
@@ -359,11 +359,12 @@ known at compile time. (This is one of the dyn compatibility rules mentioned
earlier.)
Other duplication includes the similar implementations of the `request_review`
and `approve` methods on `Post`. Both methods delegate to the implementation of
the same method on the value in the `state` field of `Option` and set the new
value of the `state` field to the result. If we had a lot of methods on `Post`
that followed this pattern, we might consider defining a macro to eliminate the
repetition (see [“Macros”][macros]<!-- ignore --> in Chapter 20).
and `approve` methods on `Post`. Both methods use `Option::take` with the
`state` field of `Post`, and if `state` is `Some`, they delegate to the wrapped
value’s implementation of the same method and set the new value of the `state`
field to the result. If we had a lot of methods on `Post` that followed this
pattern, we might consider defining a macro to eliminate the repetition (see
[“Macros”][macros]<!-- ignore --> in Chapter 20).
By implementing the state pattern exactly as it’s defined for object-oriented
languages, we’re not taking as full advantage of Rust’s strengths as we could.
@ -329,7 +329,8 @@ Within the `unsafe extern "C"` block, we list the names and signatures of
@@ -329,7 +329,8 @@ Within the `unsafe extern "C"` block, we list the names and signatures of
external functions from another language we want to call. The `"C"` part defines
which _application binary interface (ABI)_ the external function uses: the ABI
defines how to call the function at the assembly level. The `"C"` ABI is the
most common and follows the C programming language’s ABI.
most common and follows the C programming language’s ABI. Information about all
the ABIs Rust supports is available in [the Rust Reference][ABI].
Every item declared within an `unsafe extern` block is implicitly `unsafe`.
However, some FFI functions *are* safe to call. For example, the `abs` function
@ -486,7 +487,7 @@ The final action that works only with `unsafe` is accessing fields of a union. A
@@ -486,7 +487,7 @@ The final action that works only with `unsafe` is accessing fields of a union. A
particular instance at one time. Unions are primarily used to interface with
unions in C code. Accessing union fields is unsafe because Rust can’t guarantee
the type of the data currently being stored in the union instance. You can learn
more about unions in [the Rust Reference][reference].
more about unions in [the Rust Reference][unions].
### Using Miri to Check Unsafe Code
@ -548,10 +549,11 @@ For a much deeper exploration of how to work effectively with unsafe Rust, read
@@ -548,10 +549,11 @@ For a much deeper exploration of how to work effectively with unsafe Rust, read
Rust’s official guide to the subject, the [Rustonomicon][nomicon].