Part 4. Modeling resources (10 points)

In this part, you’re going to create a new type, an enumeration (enum) rather than a structure type (struct), in order to represent (or model) a resource associated with the entries in the Project Gutenberg index.

Briefly, an enum lets us model the situation where a value is one of a finite set of choices. For example, the Option<T> type is either None or it’s a Some(x) (for some value x of type T). Review Chapter 6 of the Rust book as needed for details on enums.

In this case, there are three different types of resources: epub (an ebook format), text, and audio.

Let’s return to the example index entry we saw before:

Roosevelt, Wyn; Schneider, S.	The Frontier Boys in the Sierras; Or, The Lost Mine	https://www.gutenberg.org/ebooks/32253	text https://www.gutenberg.org/ebooks/32253.html.images	text https://www.gutenberg.org/files/32253/32253-h/32253-h.htm	text https://www.gutenberg.org/files/32253/32253-h.zip	epub https://www.gutenberg.org/ebooks/32253.epub3.images	epub https://www.gutenberg.org/ebooks/32253.epub.images	epub https://www.gutenberg.org/ebooks/32253.epub.noimages	text https://www.gutenberg.org/ebooks/32253.txt.utf-8	text https://www.gutenberg.org/files/32253/32253-8.txt	text https://www.gutenberg.org/files/32253/32253-8.zip	text https://www.gutenberg.org/files/32253/32253.txt	text https://www.gutenberg.org/files/32253/32253.zip

Each of the tab-separated fields after the author, title, and URL fields consists of the word epub, text, or audio followed by a space and then a URL of the resource in question.

Your task

Define a new enum Resource which has variants corresponding to the epub, text, and audio resources. Each variant should hold its corresponding URL. For inspiration, look at the definition of enum IpAddr in the book.

You should make sure you derive Debug as normal so that you can print the debug representation using the {:?} format specifier.

let x = Resource::Audio("https://example.com");
println!("{x:?}"); // Prints debug representation of `x`

Next, modify your Entry structure to hold 0 or more Resources and update Index::new() to correctly fill in the resources from the resource fields pgindex.txt.

Tip

You can split each resource field on a space and then match on the first part.

fn main() -> Result<(), Box<dyn std::error::Error>> {
let parts = vec!["audio", "https://example.com"];
match parts[0] {
    "epub" => todo!(),
    "text" => todo!(),
    "audio" => todo!(),
    _ => return Err(format!("Unknown format: {}", parts[0]).into()),
}
Ok(())
}

How cool is that?

At this point, the run() function from the previous part should work (assuming you derived Debug as suggested) and its output should include all of the resources associated with each of the three entries matching the query.