diff --git a/src/uu/shuf/src/shuf.rs b/src/uu/shuf/src/shuf.rs index 9a899d746..ce0af5ec2 100644 --- a/src/uu/shuf/src/shuf.rs +++ b/src/uu/shuf/src/shuf.rs @@ -7,14 +7,12 @@ // spell-checker:ignore (ToDO) cmdline evec seps rvec fdata -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use rand::Rng; use std::fs::File; use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write}; use uucore::display::Quotable; +use uucore::error::{FromIo, UResult, USimpleError}; use uucore::InvalidEncodingHandling; enum Mode { @@ -52,7 +50,8 @@ mod options { pub static FILE: &str = "file"; } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); @@ -65,7 +64,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { match parse_range(range) { Ok(m) => Mode::InputRange(m), Err(msg) => { - crash!(1, "{}", msg); + return Err(USimpleError::new(1, msg)); } } } else { @@ -77,8 +76,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Some(count) => match count.parse::() { Ok(val) => val, Err(_) => { - show_error!("invalid line count: {}", count.quote()); - return 1; + return Err(USimpleError::new( + 1, + format!("invalid line count: {}", count.quote()), + )); } }, None => std::usize::MAX, @@ -97,22 +98,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Mode::Echo(args) => { let mut evec = args.iter().map(String::as_bytes).collect::>(); find_seps(&mut evec, options.sep); - shuf_bytes(&mut evec, options); + shuf_bytes(&mut evec, options)?; } Mode::InputRange((b, e)) => { let rvec = (b..e).map(|x| format!("{}", x)).collect::>(); let mut rvec = rvec.iter().map(String::as_bytes).collect::>(); - shuf_bytes(&mut rvec, options); + shuf_bytes(&mut rvec, options)?; } Mode::Default(filename) => { - let fdata = read_input_file(&filename); + let fdata = read_input_file(&filename)?; let mut fdata = vec![&fdata[..]]; find_seps(&mut fdata, options.sep); - shuf_bytes(&mut fdata, options); + shuf_bytes(&mut fdata, options)?; } } - 0 + Ok(()) } pub fn uu_app() -> App<'static, 'static> { @@ -180,22 +181,20 @@ pub fn uu_app() -> App<'static, 'static> { .arg(Arg::with_name(options::FILE).takes_value(true)) } -fn read_input_file(filename: &str) -> Vec { +fn read_input_file(filename: &str) -> UResult> { let mut file = BufReader::new(if filename == "-" { Box::new(stdin()) as Box } else { - match File::open(filename) { - Ok(f) => Box::new(f) as Box, - Err(e) => crash!(1, "failed to open {}: {}", filename.quote(), e), - } + let file = File::open(filename) + .map_err_context(|| format!("failed to open {}", filename.quote()))?; + Box::new(file) as Box }); let mut data = Vec::new(); - if let Err(e) = file.read_to_end(&mut data) { - crash!(1, "failed reading {}: {}", filename.quote(), e) - }; + file.read_to_end(&mut data) + .map_err_context(|| format!("failed reading {}", filename.quote()))?; - data + Ok(data) } fn find_seps(data: &mut Vec<&[u8]>, sep: u8) { @@ -231,22 +230,22 @@ fn find_seps(data: &mut Vec<&[u8]>, sep: u8) { } } -fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) { +fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) -> UResult<()> { let mut output = BufWriter::new(match opts.output { None => Box::new(stdout()) as Box, - Some(s) => match File::create(&s[..]) { - Ok(f) => Box::new(f) as Box, - Err(e) => crash!(1, "failed to open {} for writing: {}", s.quote(), e), - }, + Some(s) => { + let file = File::create(&s[..]) + .map_err_context(|| format!("failed to open {} for writing", s.quote()))?; + Box::new(file) as Box + } }); let mut rng = match opts.random_source { - Some(r) => WrappedRng::RngFile(rand::rngs::adapter::ReadRng::new( - match File::open(&r[..]) { - Ok(f) => f, - Err(e) => crash!(1, "failed to open random source {}: {}", r.quote(), e), - }, - )), + Some(r) => { + let file = File::open(&r[..]) + .map_err_context(|| format!("failed to open random source {}", r.quote()))?; + WrappedRng::RngFile(rand::rngs::adapter::ReadRng::new(file)) + } None => WrappedRng::RngDefault(rand::thread_rng()), }; @@ -268,10 +267,10 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) { // write the randomly chosen value and the separator output .write_all(input[r]) - .unwrap_or_else(|e| crash!(1, "write failed: {}", e)); + .map_err_context(|| "write failed".to_string())?; output .write_all(&[opts.sep]) - .unwrap_or_else(|e| crash!(1, "write failed: {}", e)); + .map_err_context(|| "write failed".to_string())?; // if we do not allow repeats, remove the chosen value from the input vector if !opts.repeat { @@ -284,6 +283,7 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) { count -= 1; } + Ok(()) } fn parse_range(input_range: &str) -> Result<(usize, usize), String> {