Using the Read trait in Rust instead of taking a file path

This example shows how to make use of the Read trait to generalize IO in Rust.

It also shows the use of a Cursor to pass an in-memory buffer as input (useful for tests) and BufReader to perform IO efficiently (without this, each call to read() may involve a system call).

use std::io::prelude::*;
use std::io::BufReader;
use std::io::Cursor;
use std::io::Result;

fn count_lines<R: Read>(input: &mut R) -> Result<u32> {
    let reader = BufReader::new(input);
    let mut count = 0;
    for line in reader.lines() {
        line?;
        count += 1;
    }
    Ok(count)
}

fn main() {
    let mut input = Cursor::new(String::from("foo\nbar\nbaz\n"));
    let line_count = count_lines(&mut input).expect("read error");
    assert_eq!(line_count, 3);
}