1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::io::{BufRead, Result};
use bytes;
pub fn count_lines<R: BufRead>(r: R) -> Result<usize> {
let mut lines = 0usize;
try!(map_lines(r, |_| { lines += 1; true }));
Ok(lines)
}
pub fn map_lines<R, F>(mut r: R, mut f: F) -> Result<()>
where R: BufRead, F: FnMut(&[u8]) -> bool
{
let mut line_start: Vec<u8> = Vec::new();
let mut consumed = 0usize;
loop {
r.consume(consumed);
let b = match r.fill_buf() {
Ok(b) => {
if b.len() == 0 {
break;
}
b
},
Err(e) => { return Err(e); }
};
match bytes::index(b, b'\n') {
Some(i) => {
{
let b = if line_start.is_empty() {
&b[..i+1]
} else {
line_start.extend_from_slice((&b[..i+1]));
&line_start[..]
};
if !f(b) {
return Ok(())
}
}
if ! line_start.is_empty() {
unsafe { line_start.set_len(0); }
}
consumed = i+1;
}
None => {
line_start.extend_from_slice(b);
consumed = b.len();
}
}
}
if ! line_start.is_empty() {
f(&line_start[..]);
}
Ok(())
}