1
use std::io;
2
use std::io::BufRead;
3
use std::io::BufReader;
4
use std::io::Read;
5
use streaming_iterator::StreamingIterator;
6

            
7
/// A lending iterator over the lines of a type implementing Read.
8
pub struct LineIterator<T: Read> {
9
    reader: BufReader<T>,
10
    buffer: String,
11
    error: Option<io::Error>,
12
    end: bool,
13
}
14

            
15
impl<T: Read> LineIterator<T> {
16
321
    pub fn new(reader: T) -> LineIterator<T> {
17
321
        LineIterator {
18
321
            reader: BufReader::new(reader),
19
321
            buffer: String::new(),
20
321
            error: None,
21
321
            end: false,
22
321
        }
23
321
    }
24

            
25
    /// Returns the I/O error that terminated iteration, if any.
26
    pub fn error(&self) -> Option<&io::Error> {
27
        self.error.as_ref()
28
    }
29
}
30

            
31
impl<T: Read> StreamingIterator for LineIterator<T> {
32
    type Item = String;
33

            
34
213830
    fn advance(&mut self) {
35
213830
        self.buffer.clear();
36
213830
        match self.reader.read_line(&mut self.buffer) {
37
213830
            Ok(n) if n > 0 => {
38
213511
                if self.buffer.ends_with('\n') {
39
213502
                    self.buffer.pop();
40
213502
                    if self.buffer.ends_with('\r') {
41
374
                        self.buffer.pop();
42
213128
                    }
43
9
                }
44
            }
45
319
            Ok(_) => self.end = true,
46
            Err(e) => {
47
                self.error = Some(e);
48
                self.end = true;
49
            }
50
        }
51
213830
    }
52

            
53
213830
    fn get(&self) -> Option<&Self::Item> {
54
213830
        if self.end { None } else { Some(&self.buffer) }
55
213830
    }
56
}
57

            
58
#[cfg(test)]
59
mod tests {
60
    use super::LineIterator;
61

            
62
    use std::io::Cursor;
63
    use streaming_iterator::StreamingIterator;
64

            
65
    #[test]
66
1
    fn test_line_iterator_basic() {
67
1
        let data = "line1\nline2\nline3";
68
1
        let cursor = Cursor::new(data);
69
1
        let mut line_iterator = LineIterator::new(cursor);
70

            
71
1
        let mut lines = Vec::new();
72
4
        while let Some(line) = line_iterator.next() {
73
3
            lines.push(line.clone());
74
3
        }
75

            
76
1
        assert_eq!(lines, vec!["line1", "line2", "line3"]);
77
1
    }
78

            
79
    #[test]
80
1
    fn test_line_iterator_empty() {
81
1
        let data = "";
82
1
        let cursor = Cursor::new(data);
83
1
        let mut line_iterator = LineIterator::new(cursor);
84

            
85
1
        let mut lines = Vec::new();
86
1
        while let Some(line) = line_iterator.next() {
87
            lines.push(line.clone());
88
        }
89

            
90
1
        assert!(lines.is_empty());
91
1
    }
92

            
93
    #[test]
94
1
    fn test_line_iterator_single_line() {
95
1
        let data = "single line";
96
1
        let cursor = Cursor::new(data);
97
1
        let mut line_iterator = LineIterator::new(cursor);
98

            
99
1
        let mut lines = Vec::new();
100
2
        while let Some(line) = line_iterator.next() {
101
1
            lines.push(line.clone());
102
1
        }
103

            
104
1
        assert_eq!(lines, vec!["single line"]);
105
1
    }
106

            
107
    #[test]
108
1
    fn test_line_iterator_with_carriage_return() {
109
1
        let data = "line1\r\nline2\r\nline3";
110
1
        let cursor = Cursor::new(data);
111
1
        let mut line_iterator = LineIterator::new(cursor);
112

            
113
1
        let mut lines = Vec::new();
114
4
        while let Some(line) = line_iterator.next() {
115
3
            lines.push(line.clone());
116
3
        }
117

            
118
1
        assert_eq!(lines, vec!["line1", "line2", "line3"]);
119
1
    }
120
}