mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
shuf: use UResult
This commit is contained in:
parent
bcef1d6cca
commit
06f3db8c55
1 changed files with 34 additions and 34 deletions
|
@ -7,14 +7,12 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) cmdline evec seps rvec fdata
|
// spell-checker:ignore (ToDO) cmdline evec seps rvec fdata
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
|
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
|
use uucore::error::{FromIo, UResult, USimpleError};
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::InvalidEncodingHandling;
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
@ -52,7 +50,8 @@ mod options {
|
||||||
pub static FILE: &str = "file";
|
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
|
let args = args
|
||||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
.accept_any();
|
.accept_any();
|
||||||
|
@ -65,7 +64,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
match parse_range(range) {
|
match parse_range(range) {
|
||||||
Ok(m) => Mode::InputRange(m),
|
Ok(m) => Mode::InputRange(m),
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
crash!(1, "{}", msg);
|
return Err(USimpleError::new(1, msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,8 +76,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
Some(count) => match count.parse::<usize>() {
|
Some(count) => match count.parse::<usize>() {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
show_error!("invalid line count: {}", count.quote());
|
return Err(USimpleError::new(
|
||||||
return 1;
|
1,
|
||||||
|
format!("invalid line count: {}", count.quote()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => std::usize::MAX,
|
None => std::usize::MAX,
|
||||||
|
@ -97,22 +98,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
Mode::Echo(args) => {
|
Mode::Echo(args) => {
|
||||||
let mut evec = args.iter().map(String::as_bytes).collect::<Vec<_>>();
|
let mut evec = args.iter().map(String::as_bytes).collect::<Vec<_>>();
|
||||||
find_seps(&mut evec, options.sep);
|
find_seps(&mut evec, options.sep);
|
||||||
shuf_bytes(&mut evec, options);
|
shuf_bytes(&mut evec, options)?;
|
||||||
}
|
}
|
||||||
Mode::InputRange((b, e)) => {
|
Mode::InputRange((b, e)) => {
|
||||||
let rvec = (b..e).map(|x| format!("{}", x)).collect::<Vec<String>>();
|
let rvec = (b..e).map(|x| format!("{}", x)).collect::<Vec<String>>();
|
||||||
let mut rvec = rvec.iter().map(String::as_bytes).collect::<Vec<&[u8]>>();
|
let mut rvec = rvec.iter().map(String::as_bytes).collect::<Vec<&[u8]>>();
|
||||||
shuf_bytes(&mut rvec, options);
|
shuf_bytes(&mut rvec, options)?;
|
||||||
}
|
}
|
||||||
Mode::Default(filename) => {
|
Mode::Default(filename) => {
|
||||||
let fdata = read_input_file(&filename);
|
let fdata = read_input_file(&filename)?;
|
||||||
let mut fdata = vec![&fdata[..]];
|
let mut fdata = vec![&fdata[..]];
|
||||||
find_seps(&mut fdata, options.sep);
|
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> {
|
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))
|
.arg(Arg::with_name(options::FILE).takes_value(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_input_file(filename: &str) -> Vec<u8> {
|
fn read_input_file(filename: &str) -> UResult<Vec<u8>> {
|
||||||
let mut file = BufReader::new(if filename == "-" {
|
let mut file = BufReader::new(if filename == "-" {
|
||||||
Box::new(stdin()) as Box<dyn Read>
|
Box::new(stdin()) as Box<dyn Read>
|
||||||
} else {
|
} else {
|
||||||
match File::open(filename) {
|
let file = File::open(filename)
|
||||||
Ok(f) => Box::new(f) as Box<dyn Read>,
|
.map_err_context(|| format!("failed to open {}", filename.quote()))?;
|
||||||
Err(e) => crash!(1, "failed to open {}: {}", filename.quote(), e),
|
Box::new(file) as Box<dyn Read>
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
if let Err(e) = file.read_to_end(&mut data) {
|
file.read_to_end(&mut data)
|
||||||
crash!(1, "failed reading {}: {}", filename.quote(), e)
|
.map_err_context(|| format!("failed reading {}", filename.quote()))?;
|
||||||
};
|
|
||||||
|
|
||||||
data
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_seps(data: &mut Vec<&[u8]>, sep: u8) {
|
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 {
|
let mut output = BufWriter::new(match opts.output {
|
||||||
None => Box::new(stdout()) as Box<dyn Write>,
|
None => Box::new(stdout()) as Box<dyn Write>,
|
||||||
Some(s) => match File::create(&s[..]) {
|
Some(s) => {
|
||||||
Ok(f) => Box::new(f) as Box<dyn Write>,
|
let file = File::create(&s[..])
|
||||||
Err(e) => crash!(1, "failed to open {} for writing: {}", s.quote(), e),
|
.map_err_context(|| format!("failed to open {} for writing", s.quote()))?;
|
||||||
},
|
Box::new(file) as Box<dyn Write>
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut rng = match opts.random_source {
|
let mut rng = match opts.random_source {
|
||||||
Some(r) => WrappedRng::RngFile(rand::rngs::adapter::ReadRng::new(
|
Some(r) => {
|
||||||
match File::open(&r[..]) {
|
let file = File::open(&r[..])
|
||||||
Ok(f) => f,
|
.map_err_context(|| format!("failed to open random source {}", r.quote()))?;
|
||||||
Err(e) => crash!(1, "failed to open random source {}: {}", r.quote(), e),
|
WrappedRng::RngFile(rand::rngs::adapter::ReadRng::new(file))
|
||||||
},
|
}
|
||||||
)),
|
|
||||||
None => WrappedRng::RngDefault(rand::thread_rng()),
|
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
|
// write the randomly chosen value and the separator
|
||||||
output
|
output
|
||||||
.write_all(input[r])
|
.write_all(input[r])
|
||||||
.unwrap_or_else(|e| crash!(1, "write failed: {}", e));
|
.map_err_context(|| "write failed".to_string())?;
|
||||||
output
|
output
|
||||||
.write_all(&[opts.sep])
|
.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 we do not allow repeats, remove the chosen value from the input vector
|
||||||
if !opts.repeat {
|
if !opts.repeat {
|
||||||
|
@ -284,6 +283,7 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) {
|
||||||
|
|
||||||
count -= 1;
|
count -= 1;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_range(input_range: &str) -> Result<(usize, usize), String> {
|
fn parse_range(input_range: &str) -> Result<(usize, usize), String> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue