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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![deny(missing_docs)]
use {linereader::LineReader, std::io::Read};
mod bound;
pub trait ReadExt {
type Read: std::io::Read;
fn lines_rc_with_capacity(self, buffer_capacity: usize) -> bound::RcLineIterator<Self::Read>;
fn lines_rc(self) -> bound::RcLineIterator<Self::Read>;
}
impl<T: Read> ReadExt for T {
type Read = T;
fn lines_rc(self) -> bound::RcLineIterator<T> {
self.lines_rc_with_capacity(64 * 1024)
}
fn lines_rc_with_capacity(self, buffer_capacity: usize) -> bound::RcLineIterator<Self::Read> {
bound::RcLineIterator::new(
LineReader::with_capacity(buffer_capacity, self),
buffer_capacity,
)
}
}
#[derive(thiserror::Error, Debug)]
pub enum Error<T: std::fmt::Debug> {
#[error("io")]
Io(#[from] std::io::Error),
#[error("encoding")]
Encoding(#[from] std::str::Utf8Error),
#[error("Incomplete line")]
Incomplete(T),
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::{BufRead, BufReader, Cursor};
#[test]
fn return_whitespace_line() {
assert_behave_same(&" \r\n");
assert_behave_same(&" \n");
}
#[test]
fn return_whitespace_on_last_line() {
assert_behave_same(&"\r\n ");
assert_behave_same(&"\n ");
}
#[test]
fn return_trailing_double_linebkreak() {
assert_behave_same(&"\r\n\r\n");
assert_behave_same(&"\n\n");
}
#[test]
fn return_whitespace_line_and_terminating_a() {
assert_behave_same(&"\r\na")
}
#[test]
fn assert_non_ascii_returns_error() {
let buf = ['a' as u8, 'b' as u8, 254];
assert_behave_same(&buf);
}
fn assert_behave_same<T: AsRef<[u8]>>(input: &T) {
let mut own_iter = BufReader::new(Cursor::new(input)).lines();
let mut rc_iter = std::io::Cursor::new(input).lines_rc();
for (own_line, rc_line) in own_iter.by_ref().zip(rc_iter.by_ref()) {
match own_line {
Ok(o) => assert_eq!(o, *rc_line.unwrap()),
Err(_) => {
rc_line.unwrap_err();
}
}
}
assert_eq!(own_iter.count(), 0);
assert_eq!(rc_iter.count(), 0);
}
}