Skip to content

Commit 32e1c54

Browse files
Fix "coreutils manpage base64" bug
1 parent 9fa405f commit 32e1c54

File tree

10 files changed

+103
-91
lines changed

10 files changed

+103
-91
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/uu/base32/src/base32.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,23 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
use std::io::{stdin, Read};
6+
pub mod base_common;
77

88
use clap::Command;
99
use uucore::{encoding::Format, error::UResult, help_about, help_usage};
1010

11-
pub mod base_common;
12-
1311
const ABOUT: &str = help_about!("base32.md");
1412
const USAGE: &str = help_usage!("base32.md");
1513

1614
#[uucore::main]
1715
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
1816
let format = Format::Base32;
1917

20-
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
18+
let config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
2119

22-
// Create a reference to stdin so we can return a locked stdin from
23-
// parse_base_cmd_args
24-
let stdin_raw = stdin();
25-
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
20+
let mut input = base_common::get_input(&config)?;
2621

27-
base_common::handle_input(
28-
&mut input,
29-
format,
30-
config.wrap_cols,
31-
config.ignore_garbage,
32-
config.decode,
33-
)
22+
base_common::handle_input(&mut input, format, config)
3423
}
3524

3625
pub fn uu_app() -> Command {

src/uu/base32/src/base_common.rs

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77

88
use clap::{crate_version, Arg, ArgAction, Command};
99
use std::fs::File;
10-
use std::io::{self, ErrorKind, Read, Stdin};
11-
use std::path::Path;
10+
use std::io::{self, ErrorKind, Read};
11+
use std::path::{Path, PathBuf};
1212
use uucore::display::Quotable;
1313
use uucore::encoding::{
14-
for_fast_encode::{BASE32, BASE32HEX, BASE64, BASE64URL, HEXUPPER},
14+
for_base_common::{BASE32, BASE32HEX, BASE64, BASE64URL, HEXUPPER},
1515
Format, Z85Wrapper, BASE2LSBF, BASE2MSBF,
1616
};
1717
use uucore::encoding::{EncodingWrapper, SupportsFastDecodeAndEncode};
@@ -31,7 +31,7 @@ pub struct Config {
3131
pub decode: bool,
3232
pub ignore_garbage: bool,
3333
pub wrap_cols: Option<usize>,
34-
pub to_read: Option<String>,
34+
pub to_read: Option<PathBuf>,
3535
}
3636

3737
pub mod options {
@@ -43,9 +43,10 @@ pub mod options {
4343

4444
impl Config {
4545
pub fn from(options: &clap::ArgMatches) -> UResult<Self> {
46-
let file: Option<String> = match options.get_many::<String>(options::FILE) {
46+
let to_read = match options.get_many::<String>(options::FILE) {
4747
Some(mut values) => {
4848
let name = values.next().unwrap();
49+
4950
if let Some(extra_op) = values.next() {
5051
return Err(UUsageError::new(
5152
BASE_CMD_PARSE_ERROR,
@@ -56,19 +57,22 @@ impl Config {
5657
if name == "-" {
5758
None
5859
} else {
59-
if !Path::exists(Path::new(name)) {
60+
let path = Path::new(name);
61+
62+
if !path.exists() {
6063
return Err(USimpleError::new(
6164
BASE_CMD_PARSE_ERROR,
62-
format!("{}: No such file or directory", name.maybe_quote()),
65+
format!("{}: No such file or directory", path.maybe_quote()),
6366
));
6467
}
65-
Some(name.clone())
68+
69+
Some(path.to_owned())
6670
}
6771
}
6872
None => None,
6973
};
7074

71-
let cols = options
75+
let wrap_cols = options
7276
.get_one::<String>(options::WRAP)
7377
.map(|num| {
7478
num.parse::<usize>().map_err(|_| {
@@ -83,8 +87,8 @@ impl Config {
8387
Ok(Self {
8488
decode: options.get_flag(options::DECODE),
8589
ignore_garbage: options.get_flag(options::IGNORE_GARBAGE),
86-
wrap_cols: cols,
87-
to_read: file,
90+
wrap_cols,
91+
to_read,
8892
})
8993
}
9094
}
@@ -139,42 +143,43 @@ pub fn base_app(about: &'static str, usage: &str) -> Command {
139143
)
140144
}
141145

142-
pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> UResult<Box<dyn Read + 'a>> {
146+
pub fn get_input(config: &Config) -> UResult<Box<dyn Read>> {
143147
match &config.to_read {
144-
Some(name) => {
148+
Some(path_buf) => {
145149
// Do not buffer input, because buffering is handled by `fast_decode` and `fast_encode`
146-
let file_buf =
147-
File::open(Path::new(name)).map_err_context(|| name.maybe_quote().to_string())?;
148-
Ok(Box::new(file_buf))
150+
let file =
151+
File::open(path_buf).map_err_context(|| path_buf.maybe_quote().to_string())?;
152+
153+
Ok(Box::new(file))
154+
}
155+
None => {
156+
let stdin_lock = io::stdin().lock();
157+
158+
Ok(Box::new(stdin_lock))
149159
}
150-
None => Ok(Box::new(stdin_ref.lock())),
151160
}
152161
}
153162

154-
pub fn handle_input<R: Read>(
155-
input: &mut R,
156-
format: Format,
157-
wrap: Option<usize>,
158-
ignore_garbage: bool,
159-
decode: bool,
160-
) -> UResult<()> {
163+
pub fn handle_input<R: Read>(input: &mut R, format: Format, config: Config) -> UResult<()> {
161164
let supports_fast_decode_and_encode = get_supports_fast_decode_and_encode(format);
162165

166+
let supports_fast_decode_and_encode_ref = supports_fast_decode_and_encode.as_ref();
167+
163168
let mut stdout_lock = io::stdout().lock();
164169

165-
if decode {
170+
if config.decode {
166171
fast_decode::fast_decode(
167172
input,
168173
&mut stdout_lock,
169-
supports_fast_decode_and_encode.as_ref(),
170-
ignore_garbage,
174+
supports_fast_decode_and_encode_ref,
175+
config.ignore_garbage,
171176
)
172177
} else {
173178
fast_encode::fast_encode(
174179
input,
175180
&mut stdout_lock,
176-
supports_fast_decode_and_encode.as_ref(),
177-
wrap,
181+
supports_fast_decode_and_encode_ref,
182+
config.wrap_cols,
178183
)
179184
}
180185
}
@@ -423,15 +428,15 @@ pub mod fast_encode {
423428
};
424429

425430
// Start of buffers
426-
// Data that was read from stdin
431+
// Data that was read from `input`
427432
let mut input_buffer = vec![0; INPUT_BUFFER_SIZE];
428433

429434
assert!(!input_buffer.is_empty());
430435

431-
// Data that was read from stdin but has not been encoded yet
436+
// Data that was read from `input` but has not been encoded yet
432437
let mut leftover_buffer = VecDeque::<u8>::new();
433438

434-
// Encoded data that needs to be written to output
439+
// Encoded data that needs to be written to `output`
435440
let mut encoded_buffer = VecDeque::<u8>::new();
436441
// End of buffers
437442

@@ -469,7 +474,7 @@ pub mod fast_encode {
469474

470475
assert!(leftover_buffer.len() < encode_in_chunks_of_size);
471476

472-
// Write all data in `encoded_buffer` to output
477+
// Write all data in `encoded_buffer` to `output`
473478
write_to_output(&mut line_wrapping, &mut encoded_buffer, &mut output, false)?;
474479
}
475480
Err(er) => {
@@ -511,7 +516,7 @@ pub mod fast_decode {
511516

512517
// Start of helper functions
513518
fn alphabet_to_table(alphabet: &[u8], ignore_garbage: bool) -> [bool; 256] {
514-
// If "ignore_garbage" is enabled, all characters outside the alphabet are ignored
519+
// If `ignore_garbage` is enabled, all characters outside the alphabet are ignored
515520
// If it is not enabled, only '\n' and '\r' are ignored
516521
if ignore_garbage {
517522
// Note: "false" here
@@ -618,31 +623,31 @@ pub mod fast_decode {
618623

619624
assert!(decode_in_chunks_of_size > 0);
620625

621-
// Note that it's not worth using "data-encoding"'s ignore functionality if "ignore_garbage" is true, because
626+
// Note that it's not worth using "data-encoding"'s ignore functionality if `ignore_garbage` is true, because
622627
// "data-encoding"'s ignore functionality cannot discard non-ASCII bytes. The data has to be filtered before
623628
// passing it to "data-encoding", so there is no point in doing any filtering in "data-encoding". This also
624629
// allows execution to stay on the happy path in "data-encoding":
625630
// https://github.com/ia0/data-encoding/blob/4f42ad7ef242f6d243e4de90cd1b46a57690d00e/lib/src/lib.rs#L754-L756
626-
// Update: it is not even worth it to use "data-encoding"'s ignore functionality when "ignore_garbage" is
631+
// It is also not worth using "data-encoding"'s ignore functionality when `ignore_garbage` is
627632
// false.
628633
// Note that the alphabet constants above already include the padding characters
629634
// TODO
630635
// Precompute this
631636
let table = alphabet_to_table(alphabet, ignore_garbage);
632637

633638
// Start of buffers
634-
// Data that was read from stdin
639+
// Data that was read from `input`
635640
let mut input_buffer = vec![0; INPUT_BUFFER_SIZE];
636641

637642
assert!(!input_buffer.is_empty());
638643

639-
// Data that was read from stdin but has not been decoded yet
644+
// Data that was read from `input` but has not been decoded yet
640645
let mut leftover_buffer = Vec::<u8>::new();
641646

642647
// Decoded data that needs to be written to `output`
643648
let mut decoded_buffer = Vec::<u8>::new();
644649

645-
// Buffer that will be used when "ignore_garbage" is true, and the chunk read from "input" contains garbage
650+
// Buffer that will be used when `ignore_garbage` is true, and the chunk read from `input` contains garbage
646651
// data
647652
let mut non_garbage_buffer = Vec::<u8>::new();
648653
// End of buffers

src/uu/base64/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ readme.workspace = true
1717
path = "src/base64.rs"
1818

1919
[dependencies]
20+
clap = { workspace = true }
2021
uucore = { workspace = true, features = ["encoding"] }
2122
uu_base32 = { workspace = true }
2223

src/uu/base64/src/base64.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,24 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
use clap::Command;
67
use uu_base32::base_common;
7-
pub use uu_base32::uu_app;
8-
98
use uucore::{encoding::Format, error::UResult, help_about, help_usage};
109

11-
use std::io::{stdin, Read};
12-
1310
const ABOUT: &str = help_about!("base64.md");
1411
const USAGE: &str = help_usage!("base64.md");
1512

1613
#[uucore::main]
1714
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
1815
let format = Format::Base64;
1916

20-
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
17+
let config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
2118

22-
// Create a reference to stdin so we can return a locked stdin from
23-
// parse_base_cmd_args
24-
let stdin_raw = stdin();
25-
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
19+
let mut input = base_common::get_input(&config)?;
20+
21+
base_common::handle_input(&mut input, format, config)
22+
}
2623

27-
base_common::handle_input(
28-
&mut input,
29-
format,
30-
config.wrap_cols,
31-
config.ignore_garbage,
32-
config.decode,
33-
)
24+
pub fn uu_app() -> Command {
25+
base_common::base_app(ABOUT, USAGE)
3426
}

src/uu/basenc/BENCHMARKING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use a benchmarking tool like [hyperfine][0].
1313
hyperfine currently does not measure maximum memory usage. Memory usage can be benchmarked using [poop][2], or
1414
[toybox][3]'s "time" subcommand (both are Linux only).
1515

16-
Next, build the `basenc` binary using the release profile:
16+
Build the `basenc` binary using the release profile:
1717

1818
```Shell
1919
cargo build --package uu_basenc --profile release

src/uu/basenc/src/basenc.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,15 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
//spell-checker:ignore (args) lsbf msbf
6+
// spell-checker:ignore lsbf msbf
77

88
use clap::{Arg, ArgAction, Command};
99
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};
10-
10+
use uucore::error::UClapError;
1111
use uucore::{
1212
encoding::Format,
1313
error::{UResult, UUsageError},
1414
};
15-
16-
use std::io::{stdin, Read};
17-
use uucore::error::UClapError;
18-
1915
use uucore::{help_about, help_usage};
2016

2117
const ABOUT: &str = help_about!("basenc.md");
@@ -81,16 +77,8 @@ fn parse_cmd_args(args: impl uucore::Args) -> UResult<(Config, Format)> {
8177
#[uucore::main]
8278
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
8379
let (config, format) = parse_cmd_args(args)?;
84-
// Create a reference to stdin so we can return a locked stdin from
85-
// parse_base_cmd_args
86-
let stdin_raw = stdin();
87-
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
8880

89-
base_common::handle_input(
90-
&mut input,
91-
format,
92-
config.wrap_cols,
93-
config.ignore_garbage,
94-
config.decode,
95-
)
81+
let mut input = base_common::get_input(&config)?;
82+
83+
base_common::handle_input(&mut input, format, config)
9684
}

src/uucore/src/lib/features/encoding.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use data_encoding::Encoding;
1111
use data_encoding_macro::new_encoding;
1212
use std::collections::VecDeque;
1313

14-
// Re-export for the faster encoding logic
15-
pub mod for_fast_encode {
14+
// Re-export for the faster decoding/encoding logic
15+
pub mod for_base_common {
1616
pub use data_encoding::*;
1717
}
1818

0 commit comments

Comments
 (0)