Line-by-line parsing
Now it’s time to actually do something with every file line that we read. To do
that, we want to loop through the lines in the file that we are given with the
reader
variable. This reader
variable, being assigned the value of the
BufReader::new(file)
call, now gives us a .lines()
method that we can iterate
over with a simple for-loop.
In Rust, a for-loop’s syntax is “for x in y”, like this:
|
|
Perfect: now each line buffered into reader
can be parsed.
We’re not quite ready to read the line yet, though. Remember when we did that
condensed and verbose example of File::open()
because it returned a Result
object? Well, line
here is also a Result
object! So how do we get the value
of the line–the actual contents–out?
You might think we need to use a match
block, like the verbose example for
File::open()
. While you can do it this way, there’s really nothing we care to
do if the line is empty (i.e., if the Result
object produces an Err()
). Think
about it: if the file was opened correctly, and the contents were buffered
correctly, what could cause the line
variable within this for-loop to be an
error?
Well, it might be the end of the file! So instead of doing error checking on this line every time, we’ll just do a Rust trick called unwrapping. When you unwrap an Result object, you are telling Rust that you 1) expect the value to be available, and 2) don’t care if the value is garbage.
If you wanted to do it the verbose way, you might write:
|
|
Notice how we would have to match each of the Result
elements (Ok()
and
Err()
). We don’t really need all this because, frankly, it’s a bit overkill
for just reading the contents of a line in a toy markdown compiler. So instead
of manually unwrapping the Result
object, we can just use Rust’s .unwrap()
method:
|
|
Let’s look at what we have so far for the for-loop, complete with some comments:
|
|
You’re doing great! Get a drink of water, stretch your back and legs, and come back when you’re ready.