1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

Merge pull request #7704 from nyurik/optimize-dd

feat: optimize `dd` parsing, bugfix
This commit is contained in:
Yuri Astrakhan 2025-04-14 15:58:11 -04:00 committed by GitHub
parent d37f500bd3
commit c1d2a07c62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 42 additions and 54 deletions

2
Cargo.lock generated
View file

@ -1333,7 +1333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets 0.48.5",
"windows-targets 0.52.6",
]
[[package]]

View file

@ -1397,11 +1397,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().try_get_matches_from(args)?;
let settings: Settings = Parser::new().parse(
&matches
matches
.get_many::<String>(options::OPERANDS)
.unwrap_or_default()
.map(|s| s.as_ref())
.collect::<Vec<_>>()[..],
.unwrap_or_default(),
)?;
let i = match settings.infile {

View file

@ -126,13 +126,19 @@ impl Parser {
Self::default()
}
pub(crate) fn parse(self, operands: &[&str]) -> Result<Settings, ParseError> {
pub(crate) fn parse(
self,
operands: impl IntoIterator<Item: AsRef<str>>,
) -> Result<Settings, ParseError> {
self.read(operands)?.validate()
}
pub(crate) fn read(mut self, operands: &[&str]) -> Result<Self, ParseError> {
pub(crate) fn read(
mut self,
operands: impl IntoIterator<Item: AsRef<str>>,
) -> Result<Self, ParseError> {
for operand in operands {
self.parse_operand(operand)?;
self.parse_operand(operand.as_ref())?;
}
Ok(self)

View file

@ -29,22 +29,14 @@ fn unimplemented_flags_should_error_non_linux() {
"noctty",
"nofollow",
] {
let args = vec![format!("iflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={flag}"));
let arg = format!("iflag={flag}");
if Parser::new().parse([&arg]).is_ok() {
succeeded.push(arg);
}
let args = vec![format!("oflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={flag}"));
let arg = format!("oflag={flag}");
if Parser::new().parse([&arg]).is_ok() {
succeeded.push(arg);
}
}
@ -61,22 +53,14 @@ fn unimplemented_flags_should_error() {
// The following flags are not implemented
for flag in ["cio", "nolinks", "text", "binary"] {
let args = vec![format!("iflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={flag}"));
let arg = format!("iflag={flag}");
if Parser::new().parse([&arg]).is_ok() {
succeeded.push(arg);
}
let args = vec![format!("oflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={flag}"));
let arg = format!("oflag={flag}");
if Parser::new().parse([&arg]).is_ok() {
succeeded.push(arg);
}
}
@ -88,14 +72,14 @@ fn unimplemented_flags_should_error() {
#[test]
fn test_status_level_absent() {
let args = &["if=foo.file", "of=bar.file"];
let args = ["if=foo.file", "of=bar.file"];
assert_eq!(Parser::new().parse(args).unwrap().status, None);
}
#[test]
fn test_status_level_none() {
let args = &["status=none", "if=foo.file", "of=bar.file"];
let args = ["status=none", "if=foo.file", "of=bar.file"];
assert_eq!(
Parser::new().parse(args).unwrap().status,
@ -106,7 +90,7 @@ fn test_status_level_none() {
#[test]
#[allow(clippy::cognitive_complexity)]
fn test_all_top_level_args_no_leading_dashes() {
let args = &[
let args = [
"if=foo.file",
"of=bar.file",
"ibs=10",
@ -181,7 +165,7 @@ fn test_all_top_level_args_no_leading_dashes() {
#[test]
fn test_status_level_progress() {
let args = &["if=foo.file", "of=bar.file", "status=progress"];
let args = ["if=foo.file", "of=bar.file", "status=progress"];
let settings = Parser::new().parse(args).unwrap();
@ -190,7 +174,7 @@ fn test_status_level_progress() {
#[test]
fn test_status_level_noxfer() {
let args = &["if=foo.file", "status=noxfer", "of=bar.file"];
let args = ["if=foo.file", "status=noxfer", "of=bar.file"];
let settings = Parser::new().parse(args).unwrap();
@ -199,7 +183,7 @@ fn test_status_level_noxfer() {
#[test]
fn test_multiple_flags_options() {
let args = &[
let args = [
"iflag=fullblock,count_bytes",
"iflag=skip_bytes",
"oflag=append",
@ -246,7 +230,7 @@ fn test_multiple_flags_options() {
#[test]
fn test_override_multiple_options() {
let args = &[
let args = [
"if=foo.file",
"if=correct.file",
"of=bar.file",
@ -288,31 +272,31 @@ fn test_override_multiple_options() {
#[test]
fn icf_ctable_error() {
let args = &["conv=ascii,ebcdic,ibm"];
let args = ["conv=ascii,ebcdic,ibm"];
assert!(Parser::new().parse(args).is_err());
}
#[test]
fn icf_case_error() {
let args = &["conv=ucase,lcase"];
let args = ["conv=ucase,lcase"];
assert!(Parser::new().parse(args).is_err());
}
#[test]
fn icf_block_error() {
let args = &["conv=block,unblock"];
let args = ["conv=block,unblock"];
assert!(Parser::new().parse(args).is_err());
}
#[test]
fn icf_creat_error() {
let args = &["conv=excl,nocreat"];
let args = ["conv=excl,nocreat"];
assert!(Parser::new().parse(args).is_err());
}
#[test]
fn parse_icf_token_ibm() {
let args = &["conv=ibm"];
let args = ["conv=ibm"];
let settings = Parser::new().parse(args).unwrap();
assert_eq!(
@ -326,7 +310,7 @@ fn parse_icf_token_ibm() {
#[test]
fn parse_icf_tokens_elu() {
let args = &["conv=ebcdic,lcase"];
let args = ["conv=ebcdic,lcase"];
let settings = Parser::new().parse(args).unwrap();
assert_eq!(
@ -340,7 +324,7 @@ fn parse_icf_tokens_elu() {
#[test]
fn parse_icf_tokens_remaining() {
let args = &[
let args = [
"conv=ascii,ucase,block,sparse,swab,sync,noerror,excl,nocreat,notrunc,noerror,fdatasync,fsync",
];
assert_eq!(
@ -369,7 +353,7 @@ fn parse_icf_tokens_remaining() {
#[test]
fn parse_iflag_tokens() {
let args = &["iflag=fullblock,count_bytes,skip_bytes"];
let args = ["iflag=fullblock,count_bytes,skip_bytes"];
assert_eq!(
Parser::new().read(args),
Ok(Parser {
@ -386,7 +370,7 @@ fn parse_iflag_tokens() {
#[test]
fn parse_oflag_tokens() {
let args = &["oflag=append,seek_bytes"];
let args = ["oflag=append,seek_bytes"];
assert_eq!(
Parser::new().read(args),
Ok(Parser {
@ -403,7 +387,7 @@ fn parse_oflag_tokens() {
#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn parse_iflag_tokens_linux() {
let args = &["iflag=direct,directory,dsync,sync,nonblock,noatime,noctty,nofollow"];
let args = ["iflag=direct,directory,dsync,sync,nonblock,noatime,noctty,nofollow"];
assert_eq!(
Parser::new().read(args),
Ok(Parser {
@ -426,7 +410,7 @@ fn parse_iflag_tokens_linux() {
#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn parse_oflag_tokens_linux() {
let args = &["oflag=direct,directory,dsync,sync,nonblock,noatime,noctty,nofollow"];
let args = ["oflag=direct,directory,dsync,sync,nonblock,noatime,noctty,nofollow"];
assert_eq!(
Parser::new().read(args),
Ok(Parser {