Part 5. Implementing Display (15 points)

The debug representation of a type—the thing you get from the {:?} format specifier—is extremely handy for developers. Rust makes it trivial to automatically get this representation for almost every type using #[derive(Debug)] which is why we add it to all of our types.

The downside is that as a user of a program, it kinda sucks: It shows a bunch of internal details about the types and users don’t care about that; it can be too verbose by including data that’s important for the implementation, but not for the end users; it’s hard to read if you don’t know what you’re looking at; and so on.

In this part, you’re going to remedy this by implementing the std::fmt::Display trait. Unlike Debug, the compiler cannot derive the Display trait for you. Fortunately, Rust makes this pretty easy.

Every trait has a list of required methods that must be implemented by a type that implements a trait. This is just like implementing an interface in Java. Some traits have 0 required methods. (These so-called “marker” traits convey information to the compiler. The Copy trait is one such trait. A type that implements Copy behaves like the primitive types like i32 in that copies of the data are made rather than moving the data.) Most traits have 1 or a small handful of methods that must be implemented. Traits can have additional methods that have default implementations (much like abstract classes in Java).

The Display trait has a single method to implement: fmt(). Read the documentation for Display and pay particular attention to the example showing how to implement Display.

The write!() macro and its companion writeln!() work very similarly to the print!() and println!() macros. There are two differences between write!()/writeln!() and print!()/println!().

  1. The print macros write to stdout whereas the write macros write to their first argument, in this case it’s the mutable reference to a Formatter object; and
  2. The print macros will panic (a safe crash) if writing to stdout fails whereas the write macros return a Result.

The upshot of 2 is that if you want to make multiple calls to writeln!() in the fmt() method, you can use the ? operator as usual.

writeln!(f, "First line")?;
writeln!(f, "Second line")?;
Ok(())

Your task

Implement Display for Entry. It should behave as follows:

  1. If the entry has an author (i.e., it’s not None), then the author line should be printed (see examples below) otherwise the author line should be omitted;
  2. Print the title line;
  3. Print the URL line; and
  4. If there are resources, print the list of resources.

Change your run() function to print out the Display representation for each matching entry.

fn run() -> Result<()> {
    let index = Index::new()?;

    println!("There are {} entries in the index", index.len());
    let results = index.title_search("the inferno");
    for entry in results {
        println!("{entry}");
    }
    Ok(())
}

If everything has been implemented correctly, the three entries should appear like this.

Author: Barbusse, Henri; O'Brien, Edward J. (Edward Joseph)
Title: The Inferno
URL: https://www.gutenberg.org/ebooks/12414
Resources
- text: https://www.gutenberg.org/ebooks/12414.html.images
- epub: https://www.gutenberg.org/ebooks/12414.epub3.images
- text: https://www.gutenberg.org/ebooks/12414.html.noimages
- epub: https://www.gutenberg.org/ebooks/12414.epub.images
- epub: https://www.gutenberg.org/ebooks/12414.epub.noimages
- text: https://www.gutenberg.org/ebooks/12414.txt.utf-8
- text: https://www.gutenberg.org/files/12414/12414-8.txt
- text: https://www.gutenberg.org/files/12414/12414-8.zip
- text: https://www.gutenberg.org/files/12414/12414.txt
- text: https://www.gutenberg.org/files/12414/12414.zip

Author: Dante Alighieri; Sibbald, James Romanes
Title: The Divine Comedy of Dante Alighieri: The Inferno
URL: https://www.gutenberg.org/ebooks/41537
Resources
- text: https://www.gutenberg.org/ebooks/41537.html.images
- text: https://www.gutenberg.org/files/41537/41537-h/41537-h.htm
- epub: https://www.gutenberg.org/ebooks/41537.epub3.images
- epub: https://www.gutenberg.org/ebooks/41537.epub.images
- epub: https://www.gutenberg.org/ebooks/41537.epub.noimages
- text: https://www.gutenberg.org/ebooks/41537.txt.utf-8
- text: https://www.gutenberg.org/files/41537/41537-0.txt

Author: Strindberg, August; Field, Claud
Title: The Inferno
URL: https://www.gutenberg.org/ebooks/44108
Resources
- text: https://www.gutenberg.org/ebooks/44108.html.images
- text: https://www.gutenberg.org/files/44108/44108-h/44108-h.htm
- text: https://www.gutenberg.org/files/44108/44108-h.zip
- epub: https://www.gutenberg.org/ebooks/44108.epub3.images
- epub: https://www.gutenberg.org/ebooks/44108.epub.images
- epub: https://www.gutenberg.org/ebooks/44108.epub.noimages
- text: https://www.gutenberg.org/files/44108/44108-0.txt
- text: https://www.gutenberg.org/files/44108/44108-0.zip