Skip to content

Commit 3ce32db

Browse files
authored
Merge pull request #14 from edilmedeiros/edilmedeiros-chap05-edit
Edit chapter 05
2 parents d79493a + 6574800 commit 3ce32db

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

05_vectors_and_result_enum.md

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@ fn read_version(transaction_hex: &str) -> u32 {
1010

1111
There are two different ways we can approach this:
1212
1. Read the first 4 pairs of characters and do some base math to determine the u32 integer.
13-
2. Convert the transaction into a collection bytes first and then just work with the methods available for that type.
13+
2. Convert the transaction into a collection of bytes first and then work with the methods available for that type.
1414

15-
Now that we have a basic understanding of hexadecimal format and bytes, we're going to take approach #2 and leverage an external library. It will be easier and more efficient to work with an array of `u8` integers to traverse the byte data, rather than read from a string and do unnecessary math. The library can handle the conversion for us. It will also be easier to work with as we decode the rest of the transaction.
15+
Now that we have a basic understanding of hexadecimal format and bytes, we're going to take approach #2 and leverage an external library.
16+
It will be easier and more efficient to work with an array of `u8` integers to traverse the byte sequence, rather than read from a string and do unnecessary math.
17+
The library can handle the conversion for us.
18+
It will also be easier to work with as we decode the rest of the transaction.
1619

17-
So the first thing we want to do is convert our hexadecimal string into a collection of bytes. We'll use the popular [`hex` crate](https://docs.rs/hex/latest/hex/).
20+
The first thing we want to do is convert our hexadecimal string into a collection of bytes.
21+
We'll use the popular [`hex` crate](https://docs.rs/hex/latest/hex/).
22+
23+
Let's add a dependency to our `Cargo.toml` file.
24+
Note the `hex` crate set to version `0.4` at the bottom under the `[dependencies]` section:
1825

19-
Let's add a dependency to our `Cargo.toml` file. Note the `hex` crate set to version `0.4` at the bottom under the `[dependencies]` section:
2026
```toml
2127
[package]
2228
name = "bitcoin-transaction-decoder"
@@ -29,9 +35,11 @@ edition = "2021"
2935
hex = "0.4"
3036
```
3137

32-
Now, the hex library's top-level module `hex` should be available to use in our `main.rs` file. *Note: As we'll see in future sections of this course, if we want to use submodules of a crate, we'll have to import them with a `use` statement.*
38+
Now, the hex library's top-level module `hex` should be available to use in our `main.rs` file.
39+
*Note: As we'll see in future sections of this course, if we want to use submodules of a crate, we'll have to import them with a `use` statement.*
3340

3441
If we look through the documentation at https://docs.rs/hex/latest/hex/, we see that we can convert the hex to bytes by calling the `decode` method from the `hex` module like so:
42+
3543
```rust
3644
fn read_version(transaction_hex: &str) -> u32 {
3745
// convert hex to bytes
@@ -40,11 +48,19 @@ fn read_version(transaction_hex: &str) -> u32 {
4048
}
4149
```
4250

43-
We'll keep returning `1` at the bottom of the function for now so the compiler doesn't complain a `u32` wasn't returned. *Note: Rust will simply return the last expression without a semi-colon so the `return` keyword is not needed.*
44-
45-
Let's run this now and see what happens. Run `$ cargo run` from the terminal.
51+
We'll keep returning `1` at the bottom of the function for now so the compiler doesn't complain a `u32` wasn't returned.
52+
*Note: Rust will simply return the last expression without a semi-colon so the `return` keyword is not needed.*
53+
Let's run this now and see what happens.
54+
Execute `$ cargo run` from the terminal.
4655

47-
So far, so good. That should compile fine. Let's now get the first 4 bytes from the returned collection. The returned data is a `vec` - short for Vector - which is something like a `list` in Python or an array in javascript. Of course, it's more nuanced in Rust. We'll dive deeper into some of the differences in the next few lessons. But with a `vec` we can grab the first 4 items doing something like `vec[0..4]` where `0..4` represents a range from 0 to 4, not including 4. This might be a pattern you're already familiar with.
56+
So far, so good.
57+
That should compile fine.
58+
Let's now get the first 4 bytes from the returned collection.
59+
The returned data is a `vec` - short for Vector - which is something like a `list` in Python or an array in javascript.
60+
Of course, it's more nuanced in Rust.
61+
We'll dive deeper into some of the differences in the next few lessons.
62+
With a `vec` we can grab the first 4 items by doing something like `vec[0..4]` where `0..4` represents a range from 0 to 4, not including 4.
63+
This might be a pattern you're already familiar with.
4864

4965
So let's add that line.
5066

@@ -57,18 +73,37 @@ fn read_version(transaction_hex: &str) -> u32 {
5773
}
5874
```
5975

60-
What happens when we run `$ cargo run`? Well, we get an error. Take some time to read through it. You should see something like the following:
76+
What happens when we execute `$ cargo run`?
77+
78+
Well, we get an error.
79+
Take some time to read through it.
80+
You should see something like the following:
81+
6182
```console
6283
error[E0608]: cannot index into a value of type `Result<Vec<u8>, FromHexError>`
6384
```
6485

65-
Let's examine what `hex::decode` returns. [Here is the doc](https://docs.rs/hex/latest/hex/fn.decode.html) for the `decode` method. Remember, we want to work with a Vector of bytes so a `vec<u8>` is the data type we're looking for. However, if we look at the return type of the `decode` function we see that the data structure we want is wrapped *inside* of a `Result` type.
86+
Let's examine what `hex::decode` returns.
87+
[Here is the doc](https://docs.rs/hex/latest/hex/fn.decode.html) for the `decode` method.
88+
Remember, we want to work with a Vector of bytes so a `vec<u8>` is the data type we're looking for.
89+
However, if we look at the return type of the `decode` function we see that the data structure we want is wrapped *inside* of a `Result` type.
6690

67-
The `Result` type is a common `enum` that you will see in Rust code. Enums are a way to describe a mutually exclusive set of options for a particular variable. If you think about it, it's possible that the `hex::decode` function fails to return a proper collection of bytes. For example, what if one of the characters is not a hex character? So we get two possibilities from a `Result`, an `Ok` response or an `Err` response.
91+
The `Result` type is a common `enum` that you will see in Rust code.
92+
Enums are a way to describe a mutually exclusive set of values for a particular variable.
93+
If you think about it, the `hex::decode` function can fail to return a proper collection of bytes.
94+
For example, what if one of the characters is not a hex character?
95+
So we get two possibilities from a `Result`, an `Ok` response or an `Err` response.
96+
The former represents a successful computation whereas the latter indicates an error occurred.
6897

69-
So how should we work with this? There are a few different ways to work with an enum. We'll explore different ways of handling a `Result` later on in this course, but for now we'll use the `unwrap` method. Every `Result` enum has an [`unwrap`](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap) method that you can call. This will return the underlying data type if the result is an `Ok` type or it will `panic` and the program will crash if the result is an `Err` type. Crashing your program is probably not the best way to handle an error, unless you're confident that an `Err` result *should* not be possible. But we'll look into better ways of error handling later on.
98+
There are a few different ways to work with an enum.
99+
Every `Result` enum has an [`unwrap`](https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap) method that you can call.
100+
This will return the underlying data type if the result is an `Ok` type or it will `panic` and the program will crash if the result is an `Err` type.
101+
Crashing your program is probably not the best way to handle an error, unless you're confident that an `Err` result *should* not be possible.
102+
For now we'll use the `unwrap` method.
103+
We'll explore different ways of handling a `Result` and doing proper error handling later on in this course.
104+
105+
For now, let's our function so that we are actually working with the underlying vector of bytes and not the wrapped `Result` type:
70106

71-
For now, let's update this so that we are actually working with the underlying vector of bytes and not the wrapped `Result` type:
72107
```rust
73108
fn read_version(transaction_hex: &str) -> u32 {
74109
// convert hex to bytes
@@ -78,15 +113,23 @@ fn read_version(transaction_hex: &str) -> u32 {
78113
}
79114
```
80115

81-
How does the program run now? Let's see by running `cargo run`.
116+
How does the program run now?
117+
Let's see by running `cargo run`.
82118

83119
We're going to get another compile error and it's going to be a confusing one:
84-
`error[E0277]: the size for values of type [u8] cannot be known at compilation time`
85120

86-
This will make more sense as we develop a better understanding of the difference between arrays, slices and vectors in Rust as well as the difference between the stack and the heap. We'll get a better handle on these concepts as we continue on in the course, but let's get a brief overview of these concepts in the next lesson.
121+
```console
122+
error[E0277]: the size for values of type [u8] cannot be known at compilation time
123+
```
124+
125+
This will make more sense as we develop a better understanding of the difference between arrays, slices and vectors in Rust as well as the difference between the stack and the heap.
126+
Let's get a brief overview of these concepts in the next lesson.
87127

88128
### Quiz
89-
*Notice the last line of this function. What will the compiler complain is wrong with this function? And why?*
129+
*Notice the last line of this function.
130+
What will the compiler complain is wrong with this function?
131+
And why?*
132+
90133
```rust
91134
fn read_version(transaction_hex: &str) -> u32 {
92135
// convert hex to bytes

0 commit comments

Comments
 (0)