Skip to content

Commit 41f93d4

Browse files
authored
Merge pull request #19 from edilmedeiros/edilmedeiros-chap-7-edit
Minor edit in chapter 07
2 parents dd822b4 + d90578f commit 41f93d4

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

07_arrays_and_conversions.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Arrays and Conversions
22

3-
There's a simple method we can use on the `u32` data type called [`from_le_bytes`](https://doc.rust-lang.org/std/primitive.u32.html#method.from_le_bytes). This will convert a collection of bytes represented in little endian into an integer.
3+
There's a simple method we can use on the `u32` data type called [`from_le_bytes`](https://doc.rust-lang.org/std/primitive.u32.html#method.from_le_bytes).
4+
This will convert a collection of bytes represented in little endian into an integer.
45

56
Let's use that and see what happens:
67

@@ -11,35 +12,50 @@ fn read_version(transaction_hex: &str) -> u32 {
1112
}
1213
```
1314

14-
This won't work unfortunately. We'll get a compiler error:
15+
This won't work unfortunately.
16+
We'll get a compiler error:
1517
```shell
1618
expected `[u8; 4]`, found `&[u8]`
1719
```
1820

19-
If we look at the `from_le_bytes` method in the documentation and look at the function signature, we'll see that the parameter expected is of the type `[u8; 4]`. However, we're passing in a slice `&[u8]`. What is the difference between these two?
21+
If we look at the `from_le_bytes` method in the documentation and check the function signature, we'll see that the parameter expected is of the type `[u8; 4]`.
22+
However, we're passing in a slice `&[u8]`.
23+
What is the difference between these two?
2024

21-
Well, in Rust, the data type `[T; N]` where `T` is any type and `N` is the number of elements, is called an *array*. Now we have to be careful because this is not the same as an array in other languages, such as Javascript and it's not the same as a list in Python. An array here is a fixed size collection that is stored on the stack as opposed to the heap. This means the data is available directly at runtime and no memory lookup is required to retrieve the data. An array's size is constant, cannot be changed and must be known and defined at compile time.
25+
Well, in Rust, the data type `[T; N]` where `T` is any type and `N` is the number of elements, is called an *array*.
26+
Now we have to be careful because this is not the same as an array in other languages, such as Javascript and it's not the same as a list in Python.
27+
An array here is a fixed size collection that is stored on the stack as opposed to the heap.
28+
This means the data is available more efficiently at runtime as there is no need to lookup that data on the heap with the use of a pointer.
29+
An array's size is constant, cannot be changed and must be known and defined at compile time.
2230

23-
So the method `from_le_bytes` only works with arrays, which makes sense. It wants to be assured that it is only working with 4 bytes at compile time because that is exactly what is needed to create a `u32` integer on the stack. So how do we convert a slice to an array? One way is to initialize an array of 4 elements and then modify it by iterating over our slice and reading each value. But there's an easier way. Most primitive and standard data types implement the [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) trait, which means they have methods which allow you to convert between types.
31+
So the method `from_le_bytes` only works with arrays, which makes sense.
32+
It wants to be assured that it is only working with 4 bytes at compile time because that is exactly what is needed to create a `u32` integer on the stack.
33+
So how do we convert a slice to an array?
34+
One way is to initialize an array of 4 elements and then modify it by iterating over our slice and reading each value.
35+
But there's an easier way.
36+
Most primitive and standard data types implement the [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) trait, which means they have methods which allow you to convert between types.
2437

2538
So we can do something like the following:
2639
```rust
2740
<[u8; 4]>::try_from(&transaction_bytes[0..4])
2841
```
2942

30-
Now remember, this method returns a `Result` type because the conversion could fail. So we need to handle that. We can do so by calling `unwrap` again.
43+
Now remember, this method returns a `Result` type because the conversion could fail.
44+
So we need to handle that.
45+
We can do so by calling `unwrap` again.
3146

3247
```rust
3348
<[u8; 4]>::try_from(&transaction_bytes[0..4]).unwrap()
3449
```
3550

36-
If a type implements the `TryFrom` it also provides a `try_into` method that can be used in the other direction. For example, we can also do something like this by being explicit about our variable's data type:
51+
If a type implements the `TryFrom` it also provides a `try_into` method that can be used in the other direction.
52+
For example, we can also do something like this by being explicit about our variable's data type:
3753

3854
```rust
3955
let version_bytes: [u8; 4] = &transaction_bytes[0..4].try_into().unwrap();
4056
```
4157

42-
This way of doing conversions tends to be more common and is slightly more readable so we'll go with that.
58+
This way of doing conversions tends to be more common and is slightly more readable so we'll go with that.
4359

4460
Let's update our function now:
4561
```rust
@@ -50,7 +66,10 @@ fn read_version(transaction_hex: &str) -> u32 {
5066
}
5167
```
5268

53-
If we run this, we'll get an error expecting the conversion type to be `&[u8; 4]` instead of `[u8; 4]`. This is because of the `&` in front of `transaction_bytes` which is incorrectly interpeted as a reference to everything that follows. What we need to do is ensure that it only refers to the slice. We'll add some parentheses:
69+
If we run this, we'll get an error expecting the conversion type to be `&[u8; 4]` instead of `[u8; 4]`.
70+
This is because of the `&` in front of `transaction_bytes` which is incorrectly interpeted as a reference to everything that follows.
71+
What we need to do is ensure that it only refers to the slice.
72+
We'll add some parentheses:
5473

5574
```rust
5675
fn read_version(transaction_hex: &str) -> u32 {
@@ -60,7 +79,7 @@ fn read_version(transaction_hex: &str) -> u32 {
6079
}
6180
```
6281

63-
Let's run it now.
82+
Let's run it now.
6483

6584
And voila! It prints out the correct version number! Congratulations!
6685

@@ -69,7 +88,8 @@ Version: 1
6988
```
7089

7190
### Quiz
72-
*Can we easily convert an `array` into a `vec` similar to how we converted a `slice` into an `array` above? If so, how does it work?*
91+
*Can we easily convert an `array` into a `vec` similar to how we converted a `slice` into an `array` above?
92+
If so, how does it work?*
7393

7494
### Additional Reading
7595
* Array Documentation: https://doc.rust-lang.org/std/primitive.array.html

0 commit comments

Comments
 (0)