3

As a newbie on rust i wonder to know if there is way to use a single function/macro/anything-else to read a line from a passed file or from stdin, passing as argument a kind of buffer reader maybe?

I haven't found anything that help yet, the following code works fine, once I was able to wrap some validations on a macro I know that code can be improved. I'm open for suggestion about how to improve that macro indeed

... macro_rules! validate { ($line:expr, $blank:expr, $squeeze:expr, $line_count:expr, $show_number:expr) => { if $line.len() <= 0 { $blank +=1; } else{ $blank = 0; } if $squeeze & ($blank > 1) { continue; } if $show_number { $line_count += 1; } } } ... for file in opt.files { blank_line_count = 0; line_count = 0; if file.to_str() != Some("-") { let f = File::open(file)?; for line in BufReader::new(f).lines() { let l = line.unwrap(); validate!(l, blank_line_count, opt.squeeze_blank, line_count, opt.number); // will continue the loop if not valid println!("{}", format_line(l, opt.show_ends, opt.show_tabs, opt.show_nonprinting, line_count)); // will be skipped if not valid } } else { let stdin = io::stdin(); let mut bytes_read: usize; loop { let mut line = String::new(); bytes_read = stdin.lock().read_line(&mut line).expect("Could not read line"); if bytes_read == 0 { break; } line.pop(); validate!(line, blank_line_count, opt.squeeze_blank, line_count, opt.number);// will continue the loop if not valid println!("{}", format_line(line, opt.show_ends, opt.show_tabs, opt.show_nonprinting, line_count)); // will be skipped if not valid } } } .... 

As shown File and stdin have different treatments, but they both basically do the same thing, run through a loop looking for a valid entry

3
  • 3
    Something like the Read trait? Commented Jun 20, 2019 at 11:48
  • Both the read_line method you are calling on the result of stdin.lock() and the lines() method you are calling on the BufReader::new(f) are from the same BufRead. So you are already using the trait you are looking for! Commented Jun 20, 2019 at 12:13
  • @PeterHall, no, not Read, but BufRead, because lines are wanted. Commented Jun 20, 2019 at 12:13

1 Answer 1

6

thanks @PeterHall, that Read trait thing lighted bulb on, I didn't realized that I could pass stdin to BufReader, so that does the trick:

 let stdin = io::stdin(); for line in BufReader::new(stdin).lines() { ... 

the same way that one does:

let f = File::open(file)?; for line in BufReader::new(f).lines() { 

This is what a I was looking for.

Thanks a mil

Sign up to request clarification or add additional context in comments.

1 Comment

This has saved me probably an hour because I have completely forgot how to do it (haven't touched that part of Rust for months). Thanks a lot!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.