From f856bfc479d300fef8515e11f5410bb3a2588c4f Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 6 Mar 2022 23:39:04 -0500 Subject: [PATCH] dd: move ConversionMode parsing to parseargs mod. Move the code for parsing the `ConversionMode` to use up to the `parseargs` module. This location makes more sense for it because the conversion mode can be determined entirely from the command-line arguments at the time of parsing just like the other parameters. Using an enum for this purpose also eliminates the amount of code we need later on. --- src/uu/dd/src/datastructures.rs | 6 +- src/uu/dd/src/dd.rs | 57 +------------------ src/uu/dd/src/parseargs.rs | 81 ++++++++++++++++++++++++--- src/uu/dd/src/parseargs/unit_tests.rs | 14 +++-- 4 files changed, 85 insertions(+), 73 deletions(-) diff --git a/src/uu/dd/src/datastructures.rs b/src/uu/dd/src/datastructures.rs index 17266ada1..ffcee4cb1 100644 --- a/src/uu/dd/src/datastructures.rs +++ b/src/uu/dd/src/datastructures.rs @@ -33,10 +33,8 @@ pub(crate) enum ConversionMode<'a> { /// Stores all Conv Flags that apply to the input #[derive(Debug, Default, PartialEq)] -pub struct IConvFlags { - pub ctable: Option<&'static ConversionTable>, - pub block: Option, - pub unblock: Option, +pub(crate) struct IConvFlags { + pub mode: Option>, pub swab: bool, pub sync: Option, pub noerror: bool, diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 33135bf02..354e4b261 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -45,7 +45,6 @@ const BUF_INIT_BYTE: u8 = 0xDD; struct Input { src: R, - non_ascii: bool, ibs: usize, print_level: Option, count: Option, @@ -56,7 +55,6 @@ struct Input { impl Input { fn new(matches: &Matches) -> UResult { let ibs = parseargs::parse_ibs(matches)?; - let non_ascii = parseargs::parse_input_non_ascii(matches)?; let print_level = parseargs::parse_status_level(matches)?; let cflags = parseargs::parse_conv_flag_input(matches)?; let iflags = parseargs::parse_iflags(matches)?; @@ -67,7 +65,6 @@ impl Input { let mut i = Self { src: io::stdin(), - non_ascii, ibs, print_level, count, @@ -131,7 +128,6 @@ fn make_linux_iflags(iflags: &IFlags) -> Option { impl Input { fn new(matches: &Matches) -> UResult { let ibs = parseargs::parse_ibs(matches)?; - let non_ascii = parseargs::parse_input_non_ascii(matches)?; let print_level = parseargs::parse_status_level(matches)?; let cflags = parseargs::parse_conv_flag_input(matches)?; let iflags = parseargs::parse_iflags(matches)?; @@ -163,7 +159,6 @@ impl Input { let i = Self { src, - non_ascii, ibs, print_level, count, @@ -605,47 +600,6 @@ impl Write for Output { } } -/// Given the various command-line parameters, determine the conversion mode. -/// -/// The `conv` command-line option can take many different values, -/// each of which may combine with others. For example, `conv=ascii`, -/// `conv=lcase`, `conv=sync`, and so on. The arguments to this -/// function represent the settings of those various command-line -/// parameters. This function translates those settings to a -/// [`ConversionMode`]. -fn conversion_mode( - ctable: Option<&ConversionTable>, - block: Option, - unblock: Option, - non_ascii: bool, - is_sync: bool, -) -> Option { - match (ctable, block, unblock) { - (Some(ct), None, None) => Some(ConversionMode::ConvertOnly(ct)), - (Some(ct), Some(cbs), None) => { - if non_ascii { - Some(ConversionMode::ConvertThenBlock(ct, cbs, is_sync)) - } else { - Some(ConversionMode::BlockThenConvert(ct, cbs, is_sync)) - } - } - (Some(ct), None, Some(cbs)) => { - if non_ascii { - Some(ConversionMode::ConvertThenUnblock(ct, cbs)) - } else { - Some(ConversionMode::UnblockThenConvert(ct, cbs)) - } - } - (None, Some(cbs), None) => Some(ConversionMode::BlockOnly(cbs, is_sync)), - (None, None, Some(cbs)) => Some(ConversionMode::UnblockOnly(cbs)), - (None, None, None) => None, - // The remaining variants should never happen because the - // argument parsing above should result in an error before - // getting to this line of code. - _ => unreachable!(), - } -} - /// Read helper performs read operations common to all dd reads, and dispatches the buffer to relevant helper functions as dictated by the operations requested by the user. fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(ReadStat, Vec)> { // Local Helper Fns ------------------------------------------------- @@ -671,14 +625,7 @@ fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(Read perform_swab(&mut buf); } - let mode = conversion_mode( - i.cflags.ctable, - i.cflags.block, - i.cflags.unblock, - i.non_ascii, - i.cflags.sync.is_some(), - ); - match mode { + match i.cflags.mode { Some(ref mode) => { let buf = conv_block_unblock_helper(buf, mode, &mut rstat); Ok((rstat, buf)) @@ -1129,7 +1076,6 @@ mod tests { src: LazyReader { src: File::open("./test-resources/deadbeef-16.test").unwrap(), }, - non_ascii: false, ibs: 16, print_level: None, count: None, @@ -1176,7 +1122,6 @@ mod tests { src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test") .unwrap(), }, - non_ascii: false, ibs: 521, print_level: None, count: None, diff --git a/src/uu/dd/src/parseargs.rs b/src/uu/dd/src/parseargs.rs index 8f2f10e70..4bc65bc1c 100644 --- a/src/uu/dd/src/parseargs.rs +++ b/src/uu/dd/src/parseargs.rs @@ -535,9 +535,50 @@ fn parse_flag_list>( .collect() } +/// Given the various command-line parameters, determine the conversion mode. +/// +/// The `conv` command-line option can take many different values, +/// each of which may combine with others. For example, `conv=ascii`, +/// `conv=lcase`, `conv=sync`, and so on. The arguments to this +/// function represent the settings of those various command-line +/// parameters. This function translates those settings to a +/// [`ConversionMode`]. +fn conversion_mode( + ctable: Option<&ConversionTable>, + block: Option, + unblock: Option, + non_ascii: bool, + is_sync: bool, +) -> Option { + match (ctable, block, unblock) { + (Some(ct), None, None) => Some(ConversionMode::ConvertOnly(ct)), + (Some(ct), Some(cbs), None) => { + if non_ascii { + Some(ConversionMode::ConvertThenBlock(ct, cbs, is_sync)) + } else { + Some(ConversionMode::BlockThenConvert(ct, cbs, is_sync)) + } + } + (Some(ct), None, Some(cbs)) => { + if non_ascii { + Some(ConversionMode::ConvertThenUnblock(ct, cbs)) + } else { + Some(ConversionMode::UnblockThenConvert(ct, cbs)) + } + } + (None, Some(cbs), None) => Some(ConversionMode::BlockOnly(cbs, is_sync)), + (None, None, Some(cbs)) => Some(ConversionMode::UnblockOnly(cbs)), + (None, None, None) => None, + // The remaining variants should never happen because the + // argument parsing above should result in an error before + // getting to this line of code. + _ => unreachable!(), + } +} + /// Parse Conversion Options (Input Variety) /// Construct and validate a IConvFlags -pub fn parse_conv_flag_input(matches: &Matches) -> Result { +pub(crate) fn parse_conv_flag_input(matches: &Matches) -> Result { let mut iconvflags = IConvFlags::default(); let mut fmt = None; let mut case = None; @@ -546,6 +587,9 @@ pub fn parse_conv_flag_input(matches: &Matches) -> Result { @@ -565,7 +609,7 @@ pub fn parse_conv_flag_input(matches: &Matches) -> Result Result Result match (cbs, iconvflags.unblock) { - (Some(cbs), None) => iconvflags.block = Some(cbs), + ConvFlag::Block => match (cbs, unblock) { + (Some(cbs), None) => block = Some(cbs), (None, _) => return Err(ParseError::BlockUnblockWithoutCBS), (_, Some(_)) => return Err(ParseError::MultipleBlockUnblock), }, - ConvFlag::Unblock => match (cbs, iconvflags.block) { - (Some(cbs), None) => iconvflags.unblock = Some(cbs), + ConvFlag::Unblock => match (cbs, block) { + (Some(cbs), None) => unblock = Some(cbs), (None, _) => return Err(ParseError::BlockUnblockWithoutCBS), (_, Some(_)) => return Err(ParseError::MultipleBlockUnblock), }, @@ -630,7 +674,7 @@ pub fn parse_conv_flag_input(matches: &Matches) -> Result Result