From 20263c94747127e23a4fdc6988f5377a49111ba8 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Thu, 23 Mar 2023 08:09:58 +0000 Subject: [PATCH] Use impl Write over a closure --- src/lib.rs | 99 ++++++++++++++++++++++++----------------------------- src/main.rs | 10 ++---- 2 files changed, 46 insertions(+), 63 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f9cbb8f..f26afee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,11 @@ use clap::Parser; -use std::fmt::{Debug, Formatter}; +use std::fmt::Debug; use std::fs; +use std::io::Write; use std::path::PathBuf; +pub type Result = std::result::Result>; + #[derive(Parser, Debug)] #[command(version)] pub struct Cli { @@ -26,58 +29,44 @@ pub struct Cli { ignore_extras: bool, } -pub struct SkipError(String); - -impl Debug for SkipError { - fn fmt(&self, f: &mut Formatter<'_>) -> core::result::Result<(), std::fmt::Error> { - write!(f, "{}", self.0) - } -} - -pub type Result = core::result::Result; - -pub fn skip(cli: &Cli, out: F) -> Result<()> -where - F: FnMut(String) -> (), -{ +pub fn skip(cli: &Cli, writer: &mut impl Write) -> Result<()> { match &cli.file { Some(ref file) => { if let Some(line) = &cli.line { - skip_file_lines_matching(&cli, out, file, line) + skip_file_lines_matching(&cli, writer, file, line) } else if let Some(ref token) = cli.token { - skip_file_tokens(cli, out, file, token) + skip_file_tokens(cli, writer, file, token) } else { - skip_file_lines(cli, out, file) + skip_file_lines(cli, writer, file) } } - None => Err(SkipError("Not yet implemented - reading from stdin".into())), + None => todo!("reading from stdin"), } } -fn skip_file_lines(cli: &Cli, mut out: F, file: &PathBuf) -> Result<()> -where - F: FnMut(String) -> (), -{ +fn skip_file_lines(cli: &Cli, writer: &mut impl Write, file: &PathBuf) -> Result<()> { let content = fs::read_to_string(file).expect("Could not read file"); let mut counter = 0usize; for current_line in content.lines() { if counter >= cli.lines { - out(String::from(current_line)); + writeln!(writer, "{}", current_line)?; } counter += 1; } Ok(()) } -fn skip_file_lines_matching(cli: &Cli, mut out: F, file: &PathBuf, line: &str) -> Result<()> -where - F: FnMut(String) -> (), -{ +fn skip_file_lines_matching( + cli: &Cli, + writer: &mut impl Write, + file: &PathBuf, + line: &str, +) -> Result<()> { let content = fs::read_to_string(file).expect("Could not read file"); let mut counter = 0usize; for current_line in content.lines() { if counter >= cli.lines { - out(String::from(current_line)); + writeln!(writer, "{}", current_line)?; } if line == current_line { counter += 1; @@ -86,15 +75,12 @@ where Ok(()) } -fn skip_file_tokens(cli: &Cli, mut out: F, file: &PathBuf, token: &str) -> Result<()> -where - F: FnMut(String) -> (), -{ +fn skip_file_tokens(cli: &Cli, writer: &mut impl Write, file: &PathBuf, token: &str) -> Result<()> { let content = fs::read_to_string(file).expect("Could not read file"); let mut counter = 0usize; for current_line in content.lines() { if counter >= cli.lines { - out(String::from(current_line)); + writeln!(writer, "{}", current_line)?; } if current_line.contains(&token) { if cli.ignore_extras { @@ -123,13 +109,13 @@ mod tests { token: None, ignore_extras: false, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then - assert_eq!(lines, vec!["line 2"]); + assert_eq!(String::from_utf8(lines)?, "line 2\n"); Ok(()) } @@ -143,13 +129,13 @@ mod tests { token: None, ignore_extras: false, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then - assert_eq!(lines, vec!["alpha", "gamma"]); + assert_eq!(String::from_utf8(lines)?, vec!["alpha", "gamma\n"].join("\n")); Ok(()) } @@ -163,13 +149,13 @@ mod tests { token: None, ignore_extras: false, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then - assert_eq!(lines, vec!["gamma"]); + assert_eq!(String::from_utf8(lines)?, "gamma\n"); Ok(()) } @@ -183,19 +169,20 @@ mod tests { token: Some(String::from("one")), ignore_extras: false, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then assert_eq!( - lines, + String::from_utf8(lines)?, vec![ "Or help one fainting robin", "Unto his nest again,", - "I shall not live in vain." + "I shall not live in vain.\n" ] + .join("\n") ); Ok(()) } @@ -210,14 +197,14 @@ mod tests { token: Some(String::from("or")), ignore_extras: false, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then assert_eq!( - lines, + String::from_utf8(lines)?, vec![ //Lorem ipsum dolor sit amet, -- +2 = 2 //consectetur adipiscing elit, @@ -226,8 +213,9 @@ mod tests { "Ut enim ad minim veniam,", "quis nostrud exercitation ullamco", "laboris nisi ut aliquip ex ea", - "commodo consequat." + "commodo consequat.\n" ] + .join("\n") ); Ok(()) } @@ -242,14 +230,14 @@ mod tests { token: Some(String::from("or")), ignore_extras: true, }; - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); //when - skip(&cli, |line| lines.push(line))?; + skip(&cli, &mut lines)?; //then assert_eq!( - lines, + String::from_utf8(lines)?, vec![ //Lorem ipsum dolor sit amet, -- 1 //consectetur adipiscing elit, @@ -258,8 +246,9 @@ mod tests { //Ut enim ad minim veniam, //quis nostrud exercitation ullamco //laboris nisi ut aliquip ex ea -- 4 - "commodo consequat." + "commodo consequat.\n" ] + .join("\n") ); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 1e0dc80..2df5010 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,9 @@ use clap::Parser; use skip::{skip, Cli, Result}; -use std::io::Write; fn main() -> Result<()> { let cli = Cli::parse(); + let mut stdout = std::io::stdout(); - let stdout = std::io::stdout(); - let mut output = stdout.lock(); - - skip(&cli, |line| match writeln!(output, "{}", line) { - Err(_) => (), - Ok(_) => (), - }) + skip(&cli, &mut stdout) }