mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
shuf: Move more file operations into main()
This removes the need for some manually duplicated code and keeps shuf_exec() (which is generic) smaller, for less binary bloat and better build times.
This commit is contained in:
parent
f562543b6c
commit
cdd1052cea
1 changed files with 34 additions and 39 deletions
|
@ -100,28 +100,41 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if options.head_count == 0 {
|
let mut output = BufWriter::new(match options.output {
|
||||||
// Do not attempt to read the random source or the input file.
|
None => Box::new(stdout()) as Box<dyn OsWrite>,
|
||||||
// However, we must touch the output file, if given:
|
Some(ref s) => {
|
||||||
if let Some(s) = options.output {
|
let file = File::create(s)
|
||||||
File::create(&s)
|
|
||||||
.map_err_context(|| format!("failed to open {} for writing", s.quote()))?;
|
.map_err_context(|| format!("failed to open {} for writing", s.quote()))?;
|
||||||
|
Box::new(file) as Box<dyn OsWrite>
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if options.head_count == 0 {
|
||||||
|
// In this case we do want to touch the output file but we can quit immediately.
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut rng = match options.random_source {
|
||||||
|
Some(ref r) => {
|
||||||
|
let file = File::open(r)
|
||||||
|
.map_err_context(|| format!("failed to open random source {}", r.quote()))?;
|
||||||
|
WrappedRng::RngFile(rand_read_adapter::ReadRng::new(file))
|
||||||
|
}
|
||||||
|
None => WrappedRng::RngDefault(rand::rng()),
|
||||||
|
};
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
Mode::Echo(args) => {
|
Mode::Echo(args) => {
|
||||||
let mut evec: Vec<&OsStr> = args.iter().map(AsRef::as_ref).collect();
|
let mut evec: Vec<&OsStr> = args.iter().map(AsRef::as_ref).collect();
|
||||||
shuf_exec(&mut evec, options)?;
|
shuf_exec(&mut evec, &options, &mut rng, &mut output)?;
|
||||||
}
|
}
|
||||||
Mode::InputRange(mut range) => {
|
Mode::InputRange(mut range) => {
|
||||||
shuf_exec(&mut range, options)?;
|
shuf_exec(&mut range, &options, &mut rng, &mut output)?;
|
||||||
}
|
}
|
||||||
Mode::Default(filename) => {
|
Mode::Default(filename) => {
|
||||||
let fdata = read_input_file(&filename)?;
|
let fdata = read_input_file(&filename)?;
|
||||||
let mut items = split_seps(&fdata, options.sep);
|
let mut items = split_seps(&fdata, options.sep);
|
||||||
shuf_exec(&mut items, options)?;
|
shuf_exec(&mut items, &options, &mut rng, &mut output)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,46 +431,28 @@ impl Writable for usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shuf_exec(input: &mut impl Shufable, opts: Options) -> UResult<()> {
|
fn shuf_exec(
|
||||||
let mut output = BufWriter::new(match opts.output {
|
input: &mut impl Shufable,
|
||||||
None => Box::new(stdout()) as Box<dyn OsWrite>,
|
opts: &Options,
|
||||||
Some(s) => {
|
rng: &mut WrappedRng,
|
||||||
let file = File::create(&s)
|
output: &mut BufWriter<Box<dyn OsWrite>>,
|
||||||
.map_err_context(|| format!("failed to open {} for writing", s.quote()))?;
|
) -> UResult<()> {
|
||||||
Box::new(file) as Box<dyn OsWrite>
|
let ctx = || "write failed".to_string();
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut rng = match opts.random_source {
|
|
||||||
Some(r) => {
|
|
||||||
let file = File::open(&r)
|
|
||||||
.map_err_context(|| format!("failed to open random source {}", r.quote()))?;
|
|
||||||
WrappedRng::RngFile(rand_read_adapter::ReadRng::new(file))
|
|
||||||
}
|
|
||||||
None => WrappedRng::RngDefault(rand::rng()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if opts.repeat {
|
if opts.repeat {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
return Err(USimpleError::new(1, "no lines to repeat"));
|
return Err(USimpleError::new(1, "no lines to repeat"));
|
||||||
}
|
}
|
||||||
for _ in 0..opts.head_count {
|
for _ in 0..opts.head_count {
|
||||||
let r = input.choose(&mut rng);
|
let r = input.choose(rng);
|
||||||
|
|
||||||
r.write_all_to(&mut output)
|
r.write_all_to(output).map_err_context(ctx)?;
|
||||||
.map_err_context(|| "write failed".to_string())?;
|
output.write_all(&[opts.sep]).map_err_context(ctx)?;
|
||||||
output
|
|
||||||
.write_all(&[opts.sep])
|
|
||||||
.map_err_context(|| "write failed".to_string())?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let shuffled = input.partial_shuffle(&mut rng, opts.head_count);
|
let shuffled = input.partial_shuffle(rng, opts.head_count);
|
||||||
for r in shuffled {
|
for r in shuffled {
|
||||||
r.write_all_to(&mut output)
|
r.write_all_to(output).map_err_context(ctx)?;
|
||||||
.map_err_context(|| "write failed".to_string())?;
|
output.write_all(&[opts.sep]).map_err_context(ctx)?;
|
||||||
output
|
|
||||||
.write_all(&[opts.sep])
|
|
||||||
.map_err_context(|| "write failed".to_string())?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue