lines 0.0.7

Utililities for iterating readers efficiently line-by-line.
Documentation
use std::{
    hint::black_box,
    io::{BufRead, BufReader, Read, Result},
};

use criterion::{Criterion, criterion_group, criterion_main};

use lines::{linemapper, linereader};

fn bench_count_lines(b: &mut Criterion) {
    let s = {
        const LINE: &str = "foo bar baz quux\n";
        const REP: usize = 200;

        let mut s = String::with_capacity(LINE.len() * REP);
        for _ in 0..REP {
            s.push_str(LINE);
        }
        s
    };
    let data = s.as_bytes();

    b.bench_function(
        &format!("bench_linemapper_over_{}_bytes", data.len()),
        |b| b.iter(|| black_box(linemapper::count_lines(BufReader::new(data)))),
    );

    b.bench_function(
        &format!("bench_linereader_over_{}_bytes", data.len()),
        |b| b.iter(|| black_box(linereader::count_lines(linereader::LineReader::new(data)))),
    );

    b.bench_function(&format!("bench_bufreader_over_{}_bytes", data.len()), |b| {
        b.iter(|| black_box(count_lines_using_bufreader_read_line(data)));
    });
}

/// Count the lines by reading lines using the std lib's
/// BufReader#read_line method. Note: that this method does UTF-8
/// validation (whereas linemapper and linereader do not.)
fn count_lines_using_bufreader_read_line<R: Read>(r: R) -> Result<usize> {
    let mut lines = 0_usize;
    let mut br = BufReader::new(r);
    let mut line = String::with_capacity(512);
    loop {
        br.read_line(&mut line)?;
        if line.is_empty() {
            break;
        }
        line.clear();
        lines += 1;
    }
    Ok(lines)
}

criterion_group!(benches, bench_count_lines);
criterion_main!(benches);