Turns out there’s a much simpler way to read lines from something that is BufRead. BufRead provides an API to iterate over the lines of a Reader. While the examples in #12 still illustrate the point I was making, a simpler implementation is provided below for brevity:

  1. Static polymorphism
    fn print_lines<T: BufRead>(b: &mut T) -> Result<(), io::Error> {
     for line in b.lines() {
         println!("{}", line?);
     }
    
     Ok(())
    }
    
  2. Dynamic polymorphism
    fn print_lines(b: &mut dyn BufRead) -> Result<(), io::Error> {
     for line in b.lines() {
         println!("{}", line?);
     }
    
     Ok(())
    }