1use super::Source;
4use crate::error::SelError;
5use crate::{Line, Result};
6use std::io::{self, BufRead, BufReader, Stdin, StdinLock};
7
8pub struct StdinSource {
9 reader: BufReader<StdinLock<'static>>,
10 line_no: u64,
11}
12
13impl StdinSource {
14 pub fn new() -> Self {
15 let stdin: Stdin = io::stdin();
16 let lock: StdinLock<'static> = Box::leak(Box::new(stdin)).lock();
18 Self {
19 reader: BufReader::new(lock),
20 line_no: 0,
21 }
22 }
23}
24
25impl Default for StdinSource {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl Source for StdinSource {
32 fn next_line(&mut self) -> Result<Option<Line>> {
33 let mut buf: Vec<u8> = Vec::new();
34 let n = self
35 .reader
36 .read_until(b'\n', &mut buf)
37 .map_err(|source| SelError::Io {
38 path: "-".to_string(),
39 source,
40 })?;
41 if n == 0 {
42 return Ok(None);
43 }
44 if buf.ends_with(b"\n") {
45 buf.pop();
46 if buf.ends_with(b"\r") {
47 buf.pop();
48 }
49 }
50 self.line_no += 1;
51 Ok(Some(Line::new(self.line_no, buf)))
52 }
53
54 fn label(&self) -> &str {
55 "-"
56 }
57
58 fn is_seekable(&self) -> bool {
59 false
60 }
61}