diff --git a/.travis.yml b/.travis.yml index 32929a629b4..68d83bf0076 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ env: matrix: allow_failures: + - rust: beta - rust: nightly fast_finish: true include: diff --git a/Cargo.toml b/Cargo.toml index 11ee4081b2e..c4507d9f7d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,15 @@ unix = [ "generic" ] windows = ["generic"] +windows_legacy = [ + "arch", + "nproc", + "sync", + "touch", + "whoami", + + "redox_generic" + ] # Feature "fuchsia" contains the exclusive list of utilities # that can be compiled and run on Fuchsia. Should be built # with --no-default-features when selecting this feature. diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 00000000000..0da0b7af482 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,91 @@ +[config] +default_to_workspace = false + +[config.modify_core_tasks] +namespace = "core" + +[env] +CARGO_MAKE_CARGO_BUILD_TEST_FLAGS = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "", mapping = { "linux" = "--no-default-features --features unix", "windows" = "--no-default-features --features windows" } } + +[tasks.default] +description = "Build and Test" +category = "[project]" +dependencies = [ + "build", + "test-terse", +] + +[tasks.build] +description = "Build" +category = "[project]" +dependencies = [ + "core::pre-build", + "core::build", + "core::post-build", +] + +[tasks.format] +description = "Format" +category = "[project]" +dependencies = [ + "action.format", +] + +[tasks.help] +description = "Help" +category = "[project]" +command = "cargo" +args = [ "make", "--list-all-steps" ] + +[tasks.lint] +description = "Lint report" +category = "[project]" +dependencies = [ + "action-clippy", + "action-fmt_report", +] + +[tasks.test] +description = "Test" +category = "[project]" +dependencies = [ + "core::pre-test", + "core::test", + "core::post-test", +] + +[tasks.test-terse] +description = "Test (with terse/summary output)" +category = "[project]" +dependencies = [ + "core::pre-test", + "action-test_quiet", + "core::post-test", +] + +### actions + +[tasks.action-clippy] +description = "`cargo clippy` lint report" +command = "cargo" +args = ["clippy", "@@split(CARGO_MAKE_CARGO_BUILD_TEST_FLAGS, )"] + +[tasks.action-format] +description = "`cargo fmt`" +command = "cargo" +args = ["fmt"] + +[tasks.action-fmt] +description = "`cargo fmt`" +command = "cargo" +args = ["fmt"] + +[tasks.action-fmt_report] +description = "`cargo fmt` lint report" +command = "cargo" +args = ["fmt", "--", "--check"] + +[tasks.action-test_quiet] +description = "Test (in `--quiet` mode)" +command = "cargo" +args = ["test", "--quiet", "@@split(CARGO_MAKE_CARGO_BUILD_TEST_FLAGS, )"] diff --git a/build.rs b/build.rs index b5b70c01984..12418983912 100644 --- a/build.rs +++ b/build.rs @@ -16,7 +16,7 @@ pub fn main() { if val == "1" && key.starts_with(feature_prefix) { let krate = key[feature_prefix.len()..].to_lowercase(); match krate.as_ref() { - "default" | "unix" | "redox" | "redox_generic" | "fuchsia" | "generic" | "windows" + "default" | "unix" | "redox" | "redox_generic" | "fuchsia" | "generic" | "windows" | "windows_legacy" | "nightly" | "test_unimplemented" => continue, _ => {} } diff --git a/src/cat/cat.rs b/src/cat/cat.rs index f3ea3676b49..0b68c854f1f 100755 --- a/src/cat/cat.rs +++ b/src/cat/cat.rs @@ -38,9 +38,9 @@ static LONG_HELP: &str = ""; #[derive(PartialEq)] enum NumberingMode { - NumberNone, - NumberNonEmpty, - NumberAll, + None, + NonEmpty, + All, } quick_error! { @@ -147,11 +147,11 @@ pub fn uumain(args: Vec) -> i32 { .parse(args); let number_mode = if matches.opt_present("b") { - NumberingMode::NumberNonEmpty + NumberingMode::NonEmpty } else if matches.opt_present("n") { - NumberingMode::NumberAll + NumberingMode::All } else { - NumberingMode::NumberNone + NumberingMode::None }; let show_nonprint = matches.opts_present(&[ @@ -169,7 +169,7 @@ pub fn uumain(args: Vec) -> i32 { } let can_write_fast = !(show_tabs || show_nonprint || show_ends || squeeze_blank - || number_mode != NumberingMode::NumberNone); + || number_mode != NumberingMode::None); let success = if can_write_fast { write_fast(files).is_ok() @@ -357,7 +357,7 @@ fn write_file_lines(file: &str, options: &OutputOptions, state: &mut OutputState if in_buf[pos] == b'\n' { if !state.at_line_start || !options.squeeze_blank || !one_blank_kept { one_blank_kept = true; - if state.at_line_start && options.number == NumberingMode::NumberAll { + if state.at_line_start && options.number == NumberingMode::All { write!(&mut writer, "{0:6}\t", state.line_number)?; state.line_number += 1; } @@ -371,7 +371,7 @@ fn write_file_lines(file: &str, options: &OutputOptions, state: &mut OutputState continue; } one_blank_kept = false; - if state.at_line_start && options.number != NumberingMode::NumberNone { + if state.at_line_start && options.number != NumberingMode::None { write!(&mut writer, "{0:6}\t", state.line_number)?; state.line_number += 1; } @@ -452,11 +452,11 @@ fn write_nonprint_to_end(in_buf: &[u8], writer: &mut W, tab: &[u8]) -> } match byte { 9 => writer.write_all(tab), - 0...8 | 10...31 => writer.write_all(&[b'^', byte + 64]), - 32...126 => writer.write_all(&[byte]), + 0..=8 | 10..=31 => writer.write_all(&[b'^', byte + 64]), + 32..=126 => writer.write_all(&[byte]), 127 => writer.write_all(&[b'^', byte - 64]), - 128...159 => writer.write_all(&[b'M', b'-', b'^', byte - 64]), - 160...254 => writer.write_all(&[b'M', b'-', byte - 128]), + 128..=159 => writer.write_all(&[b'M', b'-', b'^', byte - 64]), + 160..=254 => writer.write_all(&[b'M', b'-', byte - 128]), _ => writer.write_all(&[b'M', b'-', b'^', 63]), }.unwrap(); count += 1; diff --git a/src/chmod/chmod.rs b/src/chmod/chmod.rs index b428285bd75..17e111063f6 100644 --- a/src/chmod/chmod.rs +++ b/src/chmod/chmod.rs @@ -106,7 +106,7 @@ fn sanitize_input(args: &mut Vec) -> Option { } if let Some(second) = args[i].chars().nth(1) { match second { - 'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'...'7' => { + 'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7' => { return Some(args.remove(i)); } _ => {} diff --git a/src/chown/chown.rs b/src/chown/chown.rs index ef6086c2ce4..22d45938a98 100644 --- a/src/chown/chown.rs +++ b/src/chown/chown.rs @@ -395,8 +395,8 @@ impl Chowner { fn wrap_chown>(&self, path: P, meta: &Metadata, follow: bool) -> i32 { use self::Verbosity::*; let mut ret = 0; - let dest_uid = self.dest_uid.unwrap_or(meta.uid()); - let dest_gid = self.dest_gid.unwrap_or(meta.gid()); + let dest_uid = self.dest_uid.unwrap_or_else(|| meta.uid()); + let dest_gid = self.dest_gid.unwrap_or_else(|| meta.gid()); let path = path.as_ref(); if let Err(e) = self.chown(path, dest_uid, dest_gid, follow) { match self.verbosity { diff --git a/src/cksum/build.rs b/src/cksum/build.rs index 37c48db5c6f..00c5c0fb4c3 100644 --- a/src/cksum/build.rs +++ b/src/cksum/build.rs @@ -30,7 +30,7 @@ fn main() { let file = File::create(&Path::new(&out_dir).join("crc_table.rs")).unwrap(); write!( &file, - "const CRC_TABLE: [u32; {}] = {:?};", + "#[allow(clippy::unreadable_literal)]\nconst CRC_TABLE: [u32; {}] = {:?};", CRC_TABLE_LEN, table ).unwrap(); } diff --git a/src/cksum/cksum.rs b/src/cksum/cksum.rs index e03cea4e750..22ebabf2e85 100644 --- a/src/cksum/cksum.rs +++ b/src/cksum/cksum.rs @@ -14,8 +14,6 @@ extern crate uucore; use std::fs::File; use std::io::{self, stdin, BufReader, Read}; -#[cfg(not(windows))] -use std::mem; use std::path::Path; include!(concat!(env!("OUT_DIR"), "/crc_table.rs")); @@ -39,16 +37,10 @@ fn crc_final(mut crc: u32, mut length: usize) -> u32 { !crc } -#[cfg(windows)] fn init_byte_array() -> Vec { vec![0; 1024 * 1024] } -#[cfg(not(windows))] -fn init_byte_array() -> [u8; 1024 * 1024] { - unsafe { mem::uninitialized() } -} - #[inline] fn cksum(fname: &str) -> io::Result<(u32, usize)> { let mut crc = 0u32; diff --git a/src/comm/comm.rs b/src/comm/comm.rs index f9381826bca..1997c27e64a 100644 --- a/src/comm/comm.rs +++ b/src/comm/comm.rs @@ -26,7 +26,7 @@ static LONG_HELP: &str = ""; fn mkdelim(col: usize, opts: &getopts::Matches) -> String { let mut s = String::new(); let delim = match opts.opt_str("output-delimiter") { - Some(d) => d.clone(), + Some(d) => d, None => "\t".to_owned(), }; diff --git a/src/cp/cp.rs b/src/cp/cp.rs index eb220511308..796b5c4b2ce 100644 --- a/src/cp/cp.rs +++ b/src/cp/cp.rs @@ -1,5 +1,7 @@ #![crate_name = "uu_cp"] +#![allow(clippy::missing_safety_doc)] + /* * This file is part of the uutils coreutils package. * @@ -29,18 +31,23 @@ extern crate kernel32; #[cfg(windows)] use kernel32::GetFileInformationByHandle; #[cfg(windows)] -use kernel32::CreateFile2; +use kernel32::CreateFileW; #[cfg(windows)] extern crate winapi; use std::mem; +#[cfg(not(windows))] use std::ffi::CString; +#[cfg(windows)] +use std::ffi::OsStr; use clap::{App, Arg, ArgMatches}; use quick_error::ResultExt; use std::collections::HashSet; use std::fs; use std::io::{stdin, stdout, Write}; use std::io; +#[cfg(windows)] +use std::os::windows::ffi::OsStrExt; use std::path::{Path, PathBuf, StripPrefixError}; use std::str::FromStr; use uucore::fs::{canonicalize, CanonicalizeMode}; @@ -56,6 +63,7 @@ use filetime::FileTime; use std::os::unix::fs::PermissionsExt; #[cfg(target_os = "linux")] +#[allow(clippy::missing_safety_doc)] ioctl!(write ficlone with 0x94, 9; std::os::raw::c_int); quick_error! { @@ -470,7 +478,7 @@ pub fn uumain(args: Vec) -> i32 { let options = crash_if_err!(EXIT_ERR, Options::from_matches(&matches)); let paths: Vec = matches .values_of("paths") - .map(|v| v.map(|p| p.to_string()).collect()) + .map(|v| v.map(std::string::ToString::to_string).collect()) .unwrap_or_default(); let (sources, target) = crash_if_err!(EXIT_ERR, parse_path_args(&paths, &options)); @@ -585,7 +593,7 @@ impl Options { let no_target_dir = matches.is_present(OPT_NO_TARGET_DIRECTORY); let target_dir = matches .value_of(OPT_TARGET_DIRECTORY) - .map(|v| v.to_string()); + .map(std::string::ToString::to_string); // Parse attributes to preserve let preserve_attributes: Vec = if matches.is_present(OPT_PRESERVE) { @@ -712,11 +720,11 @@ fn preserve_hardlinks( { if !source.is_dir() { unsafe { - let src_path = CString::new(source.as_os_str().to_str().unwrap()).unwrap(); let inode: u64; let nlinks: u64; #[cfg(unix)] { + let src_path = CString::new(source.as_os_str().to_str().unwrap()).unwrap(); let mut stat = mem::zeroed(); if libc::lstat(src_path.as_ptr(), &mut stat) < 0 { return Err(format!( @@ -730,11 +738,15 @@ fn preserve_hardlinks( } #[cfg(windows)] { + let src_path: Vec = OsStr::new(source).encode_wide().collect(); + #[allow(deprecated)] let stat = mem::uninitialized(); - let handle = CreateFile2( - src_path.as_ptr() as *const u16, + let handle = CreateFileW( + src_path.as_ptr(), winapi::um::winnt::GENERIC_READ, winapi::um::winnt::FILE_SHARE_READ, + std::ptr::null_mut(), + 0, 0, std::ptr::null_mut(), ); @@ -756,7 +768,7 @@ fn preserve_hardlinks( } } if !(*found_hard_link) && nlinks > 1 { - hard_links.push((dest.clone().to_str().unwrap().to_string(), inode)); + hard_links.push((dest.to_str().unwrap().to_string(), inode)); } } } @@ -938,7 +950,7 @@ impl OverwriteMode { fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResult<()> { let context = &*format!("'{}' -> '{}'", source.display().to_string(), dest.display()); - Ok(match *attribute { + match *attribute { #[cfg(unix)] Attribute::Mode => { let mode = fs::metadata(source).context(context)?.permissions().mode(); @@ -971,10 +983,11 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu } #[cfg(not(unix))] { - return Err(format!("XAttrs are only supported on unix.").into()); + return Err("XAttrs are only supported on unix.".to_string().into()); } } - }) + }; + Ok(()) } #[cfg(not(windows))] @@ -1070,8 +1083,8 @@ fn copy_file(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> { CopyMode::Sparse => return Err(Error::NotImplemented(OPT_SPARSE.to_string())), CopyMode::Update => { if dest.exists() { - let src_metadata = fs::metadata(source.clone())?; - let dest_metadata = fs::metadata(dest.clone())?; + let src_metadata = fs::metadata(source)?; + let dest_metadata = fs::metadata(dest)?; let src_time = src_metadata.modified()?; let dest_time = dest_metadata.modified()?; @@ -1106,7 +1119,7 @@ fn copy_file(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> { fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> { if options.reflink { #[cfg(not(target_os = "linux"))] - return Err(format!("--reflink is only supported on linux").into()); + return Err("--reflink is only supported on linux".to_string().into()); #[cfg(target_os = "linux")] { diff --git a/src/cut/buffer.rs b/src/cut/buffer.rs index 11f48bccb4e..733244a54a4 100644 --- a/src/cut/buffer.rs +++ b/src/cut/buffer.rs @@ -124,7 +124,7 @@ impl self::Bytes::Select for ByteReader { buf_used if bytes < buf_used => { // because the output delimiter should only be placed between // segments check if the byte after bytes is a newline - let buf_slice = &buffer[0..bytes + 1]; + let buf_slice = &buffer[0..=bytes]; match buf_slice.iter().position(|byte| *byte == newline_char) { Some(idx) => (SRes::Newl, idx + 1), diff --git a/src/cut/cut.rs b/src/cut/cut.rs index c6efea47e8e..58bdf59fe03 100644 --- a/src/cut/cut.rs +++ b/src/cut/cut.rs @@ -203,6 +203,7 @@ fn cut_bytes(reader: R, ranges: &[Range], opts: &Options) -> i32 { 0 } +#[allow(clippy::cognitive_complexity)] fn cut_fields_delimiter( reader: R, ranges: &[Range], @@ -252,7 +253,7 @@ fn cut_fields_delimiter( }; } - for _ in 0..high - low + 1 { + for _ in 0..=high - low { if print_delim { crash_if_err!(1, out.write_all(out_delim.as_bytes())); } @@ -288,6 +289,7 @@ fn cut_fields_delimiter( 0 } +#[allow(clippy::cognitive_complexity)] fn cut_fields(reader: R, ranges: &[Range], opts: &FieldOptions) -> i32 { let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' }; if let Some(ref o_delim) = opts.out_delimeter { @@ -488,7 +490,7 @@ pub fn uumain(args: Vec) -> i32 { "a value 2 characters or longer", "--delimiter", "-d" - ).to_owned()) + )) } else { let delim = if delim.is_empty() { "\0".to_owned() @@ -519,25 +521,23 @@ pub fn uumain(args: Vec) -> i32 { } }), (ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => Err( - msg_expects_no_more_than_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)") - .to_owned(), + msg_expects_no_more_than_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)"), ), - _ => Err(msg_expects_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)").to_owned()), + _ => Err(msg_expects_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)")), }; let mode_parse = match mode_parse { Err(_) => mode_parse, Ok(mode) => match mode { Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("delimiter") => Err( - msg_opt_only_usable_if!("printing a sequence of fields", "--delimiter", "-d") - .to_owned(), + msg_opt_only_usable_if!("printing a sequence of fields", "--delimiter", "-d"), ), Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("only-delimited") => { Err(msg_opt_only_usable_if!( "printing a sequence of fields", "--only-delimited", "-s" - ).to_owned()) + )) } _ => Ok(mode), }, diff --git a/src/cut/ranges.rs b/src/cut/ranges.rs index 44edcb9434e..76caff9ceaf 100644 --- a/src/cut/ranges.rs +++ b/src/cut/ranges.rs @@ -53,7 +53,7 @@ impl FromStr for Range { Err(inval) } } - (Some(n), Some(m)) if n.len() == 0 => { + (Some(n), Some(m)) if n.is_empty() => { if let Ok(high) = m.parse::() { if high > 0 { Ok(Range { low: 1, high }) diff --git a/src/dircolors/dircolors.rs b/src/dircolors/dircolors.rs index 864438500b4..31a065b06f6 100644 --- a/src/dircolors/dircolors.rs +++ b/src/dircolors/dircolors.rs @@ -120,7 +120,7 @@ pub fn uumain(args: Vec) -> i32 { Ok(f) => { let fin = BufReader::new(f); result = parse( - fin.lines().filter_map(|l| l.ok()), + fin.lines().filter_map(std::result::Result::ok), out_format, matches.free[0].as_str(), ) diff --git a/src/du/du.rs b/src/du/du.rs index fad2df37199..28e1a8c0320 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -188,17 +188,13 @@ fn du( } } - stats.extend(futures.into_iter().flat_map(|val| val).rev().filter_map( + stats.extend(futures.into_iter().flatten().rev().filter( |stat| { if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path { my_stat.size += stat.size; my_stat.blocks += stat.blocks; } - if options.max_depth == None || depth < options.max_depth.unwrap() { - Some(stat) - } else { - None - } + options.max_depth == None || depth < options.max_depth.unwrap() }, )); stats.push(my_stat); @@ -216,7 +212,7 @@ fn convert_size_human(size: u64, multiplier: u64, _block_size: u64) -> String { } fn convert_size_b(size: u64, _multiplier: u64, _block_size: u64) -> String { - format!("{}", ((size as f64) / (1 as f64)).ceil()) + format!("{}", ((size as f64) / (1_f64)).ceil()) } fn convert_size_k(size: u64, multiplier: u64, _block_size: u64) -> String { @@ -231,6 +227,7 @@ fn convert_size_other(size: u64, _multiplier: u64, block_size: u64) -> String { format!("{}", ((size as f64) / (block_size as f64)).ceil()) } +#[allow(clippy::cognitive_complexity)] pub fn uumain(args: Vec) -> i32 { let syntax = format!( "[OPTION]... [FILE]... @@ -339,7 +336,7 @@ pub fn uumain(args: Vec) -> i32 { }; let convert_size_fn = { if matches.opt_present("human-readable") || matches.opt_present("si") { - convert_size_human + convert_size_human } else if matches.opt_present("b") { convert_size_b } else if matches.opt_present("k") { @@ -389,9 +386,7 @@ Try '{} --help' for more information.", let (_, len) = iter.size_hint(); let len = len.unwrap(); for (index, stat) in iter.enumerate() { - let size = if matches.opt_present("apparent-size") { - stat.size - } else if matches.opt_present("b") { + let size = if matches.opt_present("apparent-size") || matches.opt_present("b") { stat.size } else { // C's stat is such that each block is assume to be 512 bytes diff --git a/src/echo/echo.rs b/src/echo/echo.rs index 1178652e1a2..989d0d71992 100644 --- a/src/echo/echo.rs +++ b/src/echo/echo.rs @@ -43,7 +43,7 @@ fn parse_code( max_digits: u32, bits_per_digit: u32, ) -> Option { - let mut ret = 0x80000000; + let mut ret = 0x8000_0000; for _ in 0..max_digits { match input.peek().and_then(|c| c.to_digit(base)) { Some(n) => ret = (ret << bits_per_digit) | n, diff --git a/src/env/env.rs b/src/env/env.rs index 1d03137a40f..a8c5344c099 100644 --- a/src/env/env.rs +++ b/src/env/env.rs @@ -159,11 +159,11 @@ fn run_env(args: Vec) -> Result<(), i32> { let null = matches.is_present("null"); let files = matches .values_of("file") - .map(|v| v.collect()) + .map(std::iter::Iterator::collect) .unwrap_or_else(|| Vec::with_capacity(0)); let unsets = matches .values_of("unset") - .map(|v| v.collect()) + .map(std::iter::Iterator::collect) .unwrap_or_else(|| Vec::with_capacity(0)); let mut opts = Options { diff --git a/src/expand/expand.rs b/src/expand/expand.rs index b117ecfc322..8d5ba5aa839 100644 --- a/src/expand/expand.rs +++ b/src/expand/expand.rs @@ -169,7 +169,7 @@ fn expand(options: Options) { for file in options.files.into_iter() { let mut fh = open(file); - while match fh.read_until('\n' as u8, &mut buf) { + while match fh.read_until(b'\n', &mut buf) { Ok(s) => s > 0, Err(_) => buf.is_empty(), } { diff --git a/src/expr/expr.rs b/src/expr/expr.rs index f0e124d428c..1298137fb96 100644 --- a/src/expr/expr.rs +++ b/src/expr/expr.rs @@ -80,7 +80,7 @@ fn maybe_handle_help_or_version(args: &[String]) -> bool { fn print_help() { //! The following is taken from GNU coreutils' "expr --help" output. - print!( + println!( r#"Usage: expr EXPRESSION or: expr OPTION @@ -131,8 +131,7 @@ Environment variables: * EXPR_DEBUG_TOKENS=1 dump expression's tokens * EXPR_DEBUG_RPN=1 dump expression represented in reverse polish notation * EXPR_DEBUG_SYA_STEP=1 dump each parser step - * EXPR_DEBUG_AST=1 dump expression represented abstract syntax tree -"# + * EXPR_DEBUG_AST=1 dump expression represented abstract syntax tree"# ); } diff --git a/src/expr/syntax_tree.rs b/src/expr/syntax_tree.rs index 66b467bf6ea..d003d61ae5d 100644 --- a/src/expr/syntax_tree.rs +++ b/src/expr/syntax_tree.rs @@ -68,9 +68,9 @@ impl ASTNode { fn new_node(token_idx: usize, op_type: &str, operands: OperandsList) -> Box { Box::new(ASTNode::Node { - token_idx: token_idx, + token_idx, op_type: op_type.into(), - operands: operands, + operands, }) } fn new_leaf(token_idx: usize, value: &str) -> Box { @@ -158,7 +158,7 @@ impl ASTNode { } } pub fn operand_values(&self) -> Result, String> { - if let &ASTNode::Node { ref operands, .. } = self { + if let ASTNode::Node { ref operands, .. } = *self { let mut out = Vec::with_capacity(operands.len()); for operand in operands { match operand.evaluate() { @@ -219,6 +219,7 @@ fn maybe_dump_ast(result: &Result, String>) { } } +#[allow(clippy::ptr_arg)] fn maybe_dump_rpn(rpn: &TokenStack) { use std::env; if let Ok(debug_var) = env::var("EXPR_DEBUG_RPN") { @@ -298,17 +299,18 @@ fn push_token_to_either_stack( op_stack: &mut TokenStack, ) -> Result<(), String> { let result = match *token { - Token::Value { .. } => Ok(out_stack.push((token_idx, token.clone()))), + Token::Value { .. } => { out_stack.push((token_idx, token.clone())); Ok(()) }, Token::InfixOp { .. } => if op_stack.is_empty() { - Ok(op_stack.push((token_idx, token.clone()))) + op_stack.push((token_idx, token.clone())); + Ok(()) } else { push_op_to_stack(token_idx, token, out_stack, op_stack) }, - Token::PrefixOp { .. } => Ok(op_stack.push((token_idx, token.clone()))), + Token::PrefixOp { .. } => { op_stack.push((token_idx, token.clone())); Ok(()) }, - Token::ParOpen => Ok(op_stack.push((token_idx, token.clone()))), + Token::ParOpen => { op_stack.push((token_idx, token.clone())); Ok(()) }, Token::ParClose => move_till_match_paren(out_stack, op_stack), }; @@ -316,6 +318,7 @@ fn push_token_to_either_stack( result } +#[allow(clippy::ptr_arg)] fn maybe_dump_shunting_yard_step( token_idx: usize, token: &Token, @@ -341,15 +344,15 @@ fn push_op_to_stack( out_stack: &mut TokenStack, op_stack: &mut TokenStack, ) -> Result<(), String> { - if let &Token::InfixOp { + if let Token::InfixOp { precedence: prec, left_assoc: la, .. - } = token + } = *token { loop { match op_stack.last() { - None => return Ok(op_stack.push((token_idx, token.clone()))), + None => { op_stack.push((token_idx, token.clone())); return Ok(()) }, Some(&(_, Token::ParOpen)) => { op_stack.push((token_idx, token.clone())); @@ -487,10 +490,7 @@ fn prefix_operator_index(values: &[String]) -> Result { let haystack = &values[0]; let needles = &values[1]; - let mut current_idx = 0; - for ch_h in haystack.chars() { - current_idx += 1; - + for (current_idx, ch_h) in haystack.chars().enumerate() { for ch_n in needles.chars() { if ch_n == ch_h { return Ok(current_idx.to_string()); diff --git a/src/expr/tokens.rs b/src/expr/tokens.rs index 5684b0bed10..ba17edb8f0d 100644 --- a/src/expr/tokens.rs +++ b/src/expr/tokens.rs @@ -58,10 +58,7 @@ impl Token { } fn is_a_number(&self) -> bool { match *self { - Token::Value { ref value, .. } => match value.parse::() { - Ok(_) => true, - Err(_) => false, - }, + Token::Value { ref value, .. } => value.parse::().is_ok(), _ => false, } } diff --git a/src/factor/build.rs b/src/factor/build.rs index 6e336841561..d1e73d5a27c 100644 --- a/src/factor/build.rs +++ b/src/factor/build.rs @@ -131,8 +131,8 @@ fn test_inverter() { #[test] fn test_generator() { - let prime_10001 = Sieve::primes().skip(10000).next(); - assert_eq!(prime_10001, Some(104743)); + let prime_10001 = Sieve::primes().skip(10_000).next(); + assert_eq!(prime_10001, Some(104_743)); } const MAX_WIDTH: usize = 102; @@ -149,5 +149,6 @@ const PREAMBLE: &'static str = r##"/* // Please do not edit by hand. Instead, modify and // re-run src/factor/gen_tables.rs. -pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ +#[allow(clippy::unreadable_literal)] +pub const P_INVS_U64: &[(u64, u64, u64)] = &[ "##; diff --git a/src/factor/factor.rs b/src/factor/factor.rs index 2f5d5bb2f7f..ba39f27e103 100644 --- a/src/factor/factor.rs +++ b/src/factor/factor.rs @@ -53,6 +53,7 @@ fn gcd(mut a: u64, mut b: u64) -> u64 { } fn rho_pollard_find_divisor(num: u64) -> u64 { + #![allow(clippy::many_single_char_names)] let range = Uniform::new(1, num); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let mut x = range.sample(&mut rng); @@ -154,7 +155,7 @@ fn print_factors(num: u64) { } fn print_factors_str(num_str: &str) { - if let Err(e) = num_str.parse::().and_then(|x| Ok(print_factors(x))) { + if let Err(e) = num_str.parse::().and_then(|x| { print_factors(x); Ok(()) }) { show_warning!("{}: {}", num_str, e); } } diff --git a/src/factor/numeric.rs b/src/factor/numeric.rs index 0cce6093a8f..b6c4c954387 100644 --- a/src/factor/numeric.rs +++ b/src/factor/numeric.rs @@ -125,7 +125,7 @@ pub fn is_prime(num: u64) -> bool { // These witnesses detect all composites up to at least 2^64. // Discovered by Jim Sinclair, according to http://miller-rabin.appspot.com - let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; + let witnesses = [2, 325, 9_375, 28_178, 450_775, 9_780_504, 1_795_265_022]; !witnesses .iter() .any(|&wit| witness(wit % num, exponent, num)) diff --git a/src/fmt/fmt.rs b/src/fmt/fmt.rs index a81ad2cf545..39167b9d3ea 100644 --- a/src/fmt/fmt.rs +++ b/src/fmt/fmt.rs @@ -57,6 +57,7 @@ pub struct FmtOptions { tabwidth: usize, } +#[allow(clippy::cognitive_complexity)] pub fn uumain(args: Vec) -> i32 { let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) .optflag("c", "crown-margin", "First and second line of paragraph may have different indentations, in which case the first line's indentation is preserved, and each subsequent line's indentation matches the second line.") diff --git a/src/fmt/parasplit.rs b/src/fmt/parasplit.rs index 5ffe4593e9e..de973472999 100644 --- a/src/fmt/parasplit.rs +++ b/src/fmt/parasplit.rs @@ -164,24 +164,24 @@ impl<'a> Iterator for FileLines<'a> { // emit a blank line // Err(true) indicates that this was a linebreak, // which is important to know when detecting mail headers - if n.chars().all(|c| c.is_whitespace()) { + if n.chars().all(char::is_whitespace) { return Some(Line::NoFormatLine("".to_owned(), true)); } // if this line does not match the prefix, // emit the line unprocessed and iterate again let (pmatch, poffset) = self.match_prefix(&n[..]); - if !pmatch { - return Some(Line::NoFormatLine(n, false)); - } else if n[poffset + self.opts.prefix.len()..] - .chars() - .all(|c| c.is_whitespace()) - { + if !pmatch + || // if the line matches the prefix, but is blank after, // don't allow lines to be combined through it (that is, // treat it like a blank line, except that since it's // not truly blank we will not allow mail headers on the // following line) + n[poffset + self.opts.prefix.len()..] + .chars() + .all(char::is_whitespace) + { return Some(Line::NoFormatLine(n, false)); } @@ -363,13 +363,12 @@ impl<'a> Iterator for ParagraphStream<'a> { } } else if !second_done { // now we have enough info to handle crown margin and tagged mode - if prefix_len != fl.prefix_len || pfxind_end != fl.pfxind_end { - // in both crown and tagged modes we require that prefix_len is the same - break; - } else if self.opts.tagged && indent_len - 4 == fl.indent_len - && indent_end == fl.indent_end - { + if // in both crown and tagged modes we require that prefix_len is the same + prefix_len != fl.prefix_len || pfxind_end != fl.pfxind_end + || // in tagged mode, indent has to be *different* on following lines + self.opts.tagged && indent_len - 4 == fl.indent_len && indent_end == fl.indent_end + { break; } else { // this is part of the same paragraph, get the indent info from this line @@ -436,7 +435,7 @@ impl<'a> ParaWords<'a> { fn create_words(&mut self) { if self.para.mail_header { // no extra spacing for mail headers; always exactly 1 space - // safe to trim_left on every line of a mail header, since the + // safe to trim_start on every line of a mail header, since the // first line is guaranteed not to have any spaces self.words.extend( self.para diff --git a/src/fold/fold.rs b/src/fold/fold.rs index f4a26f4e4ad..083dd8df653 100644 --- a/src/fold/fold.rs +++ b/src/fold/fold.rs @@ -110,8 +110,8 @@ fn fold_file(mut file: BufReader, bytes: bool, spaces: bool, width: let slice = { let slice = &line[i..i + width]; if spaces && i + width < len { - match slice.rfind(|ch: char| ch.is_whitespace()) { - Some(m) => &slice[..m + 1], + match slice.rfind(char::is_whitespace) { + Some(m) => &slice[..=m], None => slice, } } else { @@ -154,7 +154,7 @@ fn fold_file(mut file: BufReader, bytes: bool, spaces: bool, width: _ => 1, } }); - (&slice[0..m + 1], routput, ncount) + (&slice[0..=m], routput, ncount) } None => (slice, "", 0), } diff --git a/src/hashsum/hashsum.rs b/src/hashsum/hashsum.rs index f32f3e3076c..ea8063403ec 100644 --- a/src/hashsum/hashsum.rs +++ b/src/hashsum/hashsum.rs @@ -48,6 +48,7 @@ fn is_custom_binary(program: &str) -> bool { } } +#[allow(clippy::cognitive_complexity)] fn detect_algo( program: &str, matches: &getopts::Matches, @@ -96,7 +97,7 @@ fn detect_algo( }, _ => { { - let mut set_or_crash = |n, val, bits| -> () { + let mut set_or_crash = |n, val, bits| { if alg.is_some() { crash!(1, "You cannot combine multiple hash algorithms!") }; @@ -367,6 +368,8 @@ Compute and check message digests.", print!("{}", opts.usage(&msg)); } +#[allow(clippy::cognitive_complexity)] +#[allow(clippy::too_many_arguments)] fn hashsum( algoname: &str, mut digest: Box, @@ -442,7 +445,7 @@ fn hashsum( let f = safe_unwrap!(File::open(ck_filename)); let mut ckf = BufReader::new(Box::new(f) as Box); let real_sum = safe_unwrap!(digest_reader( - &mut digest, + &mut *digest, &mut ckf, binary_check, output_bits @@ -459,7 +462,7 @@ fn hashsum( } } } else { - let sum = safe_unwrap!(digest_reader(&mut digest, &mut file, binary, output_bits)); + let sum = safe_unwrap!(digest_reader(&mut *digest, &mut file, binary, output_bits)); if tag { println!("{} ({}) = {}", algoname, filename, sum); } else { @@ -468,11 +471,11 @@ fn hashsum( } } if !status { - if bad_format == 1 { - show_warning!("{} line is improperly formatted", bad_format); - } else if bad_format > 1 { - show_warning!("{} lines are improperly formatted", bad_format); - } + match bad_format.cmp(&1) { + std::cmp::Ordering::Equal => show_warning!("{} line is improperly formatted", bad_format), + std::cmp::Ordering::Greater => show_warning!("{} lines are improperly formatted", bad_format), + _ => {} + }; if failed > 0 { show_warning!("{} computed checksum did NOT match", failed); } @@ -482,7 +485,7 @@ fn hashsum( } fn digest_reader<'a, T: Read>( - digest: &mut Box, + digest: &mut (dyn Digest + 'a), reader: &mut BufReader, binary: bool, output_bits: usize, diff --git a/src/hostname/hostname.rs b/src/hostname/hostname.rs index 7808b6c38c0..7c79af072e5 100644 --- a/src/hostname/hostname.rs +++ b/src/hostname/hostname.rs @@ -43,8 +43,10 @@ const SUMMARY: &str = "Print or set the system's host name."; const LONG_HELP: &str = ""; pub fn uumain(args: Vec) -> i32 { + #![allow(clippy::let_and_return)] #[cfg(windows)] unsafe { + #[allow(deprecated)] let mut data = std::mem::uninitialized(); if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 { eprintln!("Failed to start Winsock 2.2"); @@ -162,7 +164,7 @@ fn xgethostname() -> io::Result { name.push(0); } - Ok(CStr::from_bytes_with_nul(&name[..null_pos + 1]) + Ok(CStr::from_bytes_with_nul(&name[..=null_pos]) .unwrap() .to_string_lossy() .into_owned()) diff --git a/src/id/id.rs b/src/id/id.rs index 0b87fb5ec79..c8bd4f47643 100644 --- a/src/id/id.rs +++ b/src/id/id.rs @@ -30,14 +30,14 @@ macro_rules! cstr2cow { #[cfg(not(target_os = "linux"))] mod audit { - pub use std::mem::uninitialized; - use super::libc::{c_int, c_uint, dev_t, pid_t, uid_t, uint64_t}; + use super::libc::{c_int, c_uint, dev_t, pid_t, uid_t}; pub type au_id_t = uid_t; pub type au_asid_t = pid_t; pub type au_event_t = c_uint; pub type au_emod_t = c_uint; pub type au_class_t = c_int; + pub type au_flag_t = u64; #[repr(C)] pub struct au_mask { @@ -58,7 +58,7 @@ mod audit { pub ai_mask: au_mask_t, // Audit masks. pub ai_termid: au_tid_addr_t, // Terminal ID. pub ai_asid: au_asid_t, // Audit session ID. - pub ai_flags: uint64_t, // Audit session flags + pub ai_flags: au_flag_t, // Audit session flags } pub type c_auditinfo_addr_t = c_auditinfo_addr; @@ -67,8 +67,8 @@ mod audit { } } -static SYNTAX: &'static str = "[OPTION]... [USER]"; -static SUMMARY: &'static str = "Print user and group information for the specified USER,\n or (when USER omitted) for the current user."; +static SYNTAX: &str = "[OPTION]... [USER]"; +static SUMMARY: &str = "Print user and group information for the specified USER,\n or (when USER omitted) for the current user."; pub fn uumain(args: Vec) -> i32 { let mut opts = new_coreopts!(SYNTAX, SUMMARY, ""); @@ -117,7 +117,7 @@ pub fn uumain(args: Vec) -> i32 { println!( "{}", if nflag { - entries::gid2grp(id).unwrap_or(id.to_string()) + entries::gid2grp(id).unwrap_or_else(|_| id.to_string()) } else { id.to_string() } @@ -132,7 +132,7 @@ pub fn uumain(args: Vec) -> i32 { println!( "{}", if nflag { - entries::uid2usr(id).unwrap_or(id.to_string()) + entries::uid2usr(id).unwrap_or_else(|_| id.to_string()) } else { id.to_string() } @@ -146,7 +146,7 @@ pub fn uumain(args: Vec) -> i32 { if nflag { possible_pw .map(|p| p.belongs_to()) - .unwrap_or(entries::get_groups().unwrap()) + .unwrap_or_else(|| entries::get_groups().unwrap()) .iter() .map(|&id| entries::gid2grp(id).unwrap()) .collect::>() @@ -154,7 +154,7 @@ pub fn uumain(args: Vec) -> i32 { } else { possible_pw .map(|p| p.belongs_to()) - .unwrap_or(entries::get_groups().unwrap()) + .unwrap_or_else(|| entries::get_groups().unwrap()) .iter() .map(|&id| id.to_string()) .collect::>() @@ -238,7 +238,7 @@ fn pretty(possible_pw: Option) { #[cfg(any(target_os = "macos", target_os = "freebsd"))] fn pline(possible_uid: Option) { - let uid = possible_uid.unwrap_or(getuid()); + let uid = possible_uid.unwrap_or_else(getuid); let pw = Passwd::locate(uid).unwrap(); println!( @@ -258,7 +258,7 @@ fn pline(possible_uid: Option) { #[cfg(target_os = "linux")] fn pline(possible_uid: Option) { - let uid = possible_uid.unwrap_or(getuid()); + let uid = possible_uid.unwrap_or_else(getuid); let pw = Passwd::locate(uid).unwrap(); println!( @@ -278,7 +278,8 @@ fn auditid() {} #[cfg(not(target_os = "linux"))] fn auditid() { - let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { audit::uninitialized() }; + #[allow(deprecated)] + let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { std::mem::uninitialized() }; let address = &mut auditinfo as *mut audit::c_auditinfo_addr_t; if unsafe { audit::getaudit(address) } < 0 { println!("couldn't retrieve information"); diff --git a/src/install/install.rs b/src/install/install.rs index 4d7aeb61184..b99e93ace87 100644 --- a/src/install/install.rs +++ b/src/install/install.rs @@ -74,7 +74,8 @@ pub fn uumain(args: Vec) -> i32 { }; let paths: Vec = { - fn string_to_path<'a>(s: &'a String) -> &'a Path { + #[allow(clippy::ptr_arg)] + fn string_to_path(s: &String) -> &Path { Path::new(s) }; let to_owned = |p: &Path| p.to_owned(); @@ -244,8 +245,8 @@ fn behaviour(matches: &getopts::Matches) -> Result { }; Ok(Behaviour { - main_function: main_function, - specified_mode: specified_mode, + main_function, + specified_mode, suffix: backup_suffix, verbose: matches.opt_present("v"), }) @@ -259,7 +260,7 @@ fn behaviour(matches: &getopts::Matches) -> Result { /// Returns an integer intended as a program return code. /// fn directory(paths: &[PathBuf], b: Behaviour) -> i32 { - if paths.len() < 1 { + if paths.is_empty() { println!("{} with -d requires at least one argument.", NAME); 1 } else { @@ -297,7 +298,7 @@ fn directory(paths: &[PathBuf], b: Behaviour) -> i32 { /// Test if the path is a a new file path that can be /// created immediately fn is_new_file_path(path: &Path) -> bool { - path.is_file() || !path.exists() && path.parent().map(|p| p.is_dir()).unwrap_or(true) + path.is_file() || !path.exists() && path.parent().map(std::path::Path::is_dir).unwrap_or(true) } /// Perform an install, given a list of paths and behaviour. diff --git a/src/join/join.rs b/src/join/join.rs index 9915e51300d..7ae82fe6ea8 100755 --- a/src/join/join.rs +++ b/src/join/join.rs @@ -186,7 +186,7 @@ impl Spec { let file_num = match chars.next() { Some('0') => { // Must be all alone without a field specifier. - if let None = chars.next() { + if chars.next().is_none() { return Spec::Key; } @@ -260,9 +260,9 @@ impl<'a> State<'a> { }; State { - key: key, + key, file_name: name, - file_num: file_num, + file_num, print_unpaired: print_unpaired == file_num, lines: f.lines(), seq: Vec::new(), @@ -294,7 +294,7 @@ impl<'a> State<'a> { } } - return None; + None } /// Print lines in the buffers as headers. @@ -317,9 +317,9 @@ impl<'a> State<'a> { for line1 in &self.seq { for line2 in &other.seq { if repr.uses_format() { - repr.print_format(|spec| match spec { - &Spec::Key => key, - &Spec::Field(file_num, field_num) => { + repr.print_format(|spec| match *spec { + Spec::Key => key, + Spec::Field(file_num, field_num) => { if file_num == self.file_num { return line1.get_field(field_num); } @@ -423,9 +423,9 @@ impl<'a> State<'a> { fn print_line(&self, line: &Line, repr: &Repr) { if repr.uses_format() { - repr.print_format(|spec| match spec { - &Spec::Key => line.get_field(self.key), - &Spec::Field(file_num, field_num) => if file_num == self.file_num { + repr.print_format(|spec| match *spec { + Spec::Key => line.get_field(self.key), + Spec::Field(file_num, field_num) => if file_num == self.file_num { line.get_field(field_num) } else { None diff --git a/src/kill/kill.rs b/src/kill/kill.rs index 739efb8df8a..3d73f9093b0 100644 --- a/src/kill/kill.rs +++ b/src/kill/kill.rs @@ -58,7 +58,7 @@ pub fn uumain(args: Vec) -> i32 { return kill( &matches .opt_str("signal") - .unwrap_or(obs_signal.unwrap_or("9".to_owned())), + .unwrap_or_else(|| obs_signal.unwrap_or_else(|| "9".to_owned())), matches.free, ) } @@ -74,7 +74,7 @@ fn handle_obsolete(mut args: Vec) -> (Vec, Option) { while i < args.len() { // this is safe because slice is valid when it is referenced let slice = &args[i].clone(); - if slice.chars().next().unwrap() == '-' && slice.len() > 1 + if slice.starts_with('-') && slice.len() > 1 && slice.chars().nth(1).unwrap().is_digit(10) { let val = &slice[1..]; @@ -107,7 +107,7 @@ fn table() { //TODO: obtain max signal width here if (idx + 1) % 7 == 0 { - println!(""); + println!(); } } } @@ -133,7 +133,7 @@ fn print_signals() { pos += signal.name.len(); print!("{}", signal.name); if idx > 0 && pos > 73 { - println!(""); + println!(); pos = 0; } else { pos += 1; diff --git a/src/ln/ln.rs b/src/ln/ln.rs index 263c4de10af..f5f5ddf5333 100644 --- a/src/ln/ln.rs +++ b/src/ln/ln.rs @@ -159,7 +159,7 @@ pub fn uumain(args: Vec) -> i32 { } fn exec(files: &[PathBuf], settings: &Settings) -> i32 { - if files.len() == 0 { + if files.is_empty() { show_error!( "missing file operand\nTry '{} --help' for more information.", NAME @@ -201,7 +201,7 @@ fn exec(files: &[PathBuf], settings: &Settings) -> i32 { ); return 1; } - assert!(files.len() != 0); + assert!(!files.is_empty()); match link(&files[0], &files[1], settings) { Ok(_) => 0, @@ -295,7 +295,7 @@ fn link(src: &PathBuf, dst: &PathBuf, settings: &Settings) -> Result<()> { print!("'{}' -> '{}'", dst.display(), src.display()); match backup_path { Some(path) => println!(" (backup: '{}')", path.display()), - None => println!(""), + None => println!(), } } Ok(()) diff --git a/src/ls/ls.rs b/src/ls/ls.rs index 1d9de943c86..56acc97dcaa 100644 --- a/src/ls/ls.rs +++ b/src/ls/ls.rs @@ -14,12 +14,15 @@ extern crate termsize; extern crate time; extern crate unicode_width; extern crate number_prefix; -extern crate isatty; -use isatty::stdout_isatty; use number_prefix::{Standalone, Prefixed, decimal_prefix}; use term_grid::{Cell, Direction, Filling, Grid, GridOptions}; use time::{strftime, Timespec}; +#[cfg(unix)] +extern crate isatty; +#[cfg(unix)] +use isatty::stdout_isatty; + #[cfg(unix)] #[macro_use] extern crate lazy_static; @@ -60,12 +63,12 @@ static DEFAULT_COLORS: &str = "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do #[cfg(unix)] lazy_static! { - static ref LS_COLORS: String = std::env::var("LS_COLORS").unwrap_or(DEFAULT_COLORS.to_string()); + static ref LS_COLORS: String = std::env::var("LS_COLORS").unwrap_or_else(|_| DEFAULT_COLORS.to_string()); static ref COLOR_MAP: HashMap<&'static str, &'static str> = { - let codes = LS_COLORS.split(":"); + let codes = LS_COLORS.split(':'); let mut map = HashMap::new(); for c in codes { - let p: Vec<_> = c.split("=").collect(); + let p: Vec<_> = c.split('=').collect(); if p.len() == 2 { map.insert(p[0], p[1]); } @@ -171,7 +174,7 @@ fn list(options: getopts::Matches) { let locs: Vec = if options.free.is_empty() { vec![String::from(".")] } else { - options.free.iter().cloned().collect() + options.free.to_vec() }; let mut files = Vec::::new(); @@ -277,20 +280,18 @@ fn max(lhs: usize, rhs: usize) -> usize { fn should_display(entry: &DirEntry, options: &getopts::Matches) -> bool { let ffi_name = entry.file_name(); let name = ffi_name.to_string_lossy(); - if !options.opt_present("a") && !options.opt_present("A") { - if name.starts_with('.') { - return false; - } + if !options.opt_present("a") && !options.opt_present("A") && name.starts_with('.') { + return false; } if options.opt_present("B") && name.ends_with('~') { return false; } - return true; + true } fn enter_directory(dir: &PathBuf, options: &getopts::Matches) { - let mut entries = - safe_unwrap!(fs::read_dir(dir).and_then(|e| e.collect::, _>>())); + let mut entries: Vec<_> = + safe_unwrap!(fs::read_dir(dir).and_then(std::iter::Iterator::collect)); entries.retain(|e| should_display(e, options)); @@ -316,7 +317,7 @@ fn enter_directory(dir: &PathBuf, options: &getopts::Matches) { fn get_metadata(entry: &PathBuf, options: &getopts::Matches) -> std::io::Result { if options.opt_present("L") { - entry.metadata().or(entry.symlink_metadata()) + entry.metadata().or_else(|_| entry.symlink_metadata()) } else { entry.symlink_metadata() } @@ -336,14 +337,14 @@ fn display_dir_entry_size(entry: &PathBuf, options: &getopts::Matches) -> (usize fn pad_left(string: String, count: usize) -> String { if count > string.len() { let pad = count - string.len(); - let pad = String::from_utf8(vec![' ' as u8; pad]).unwrap(); + let pad = String::from_utf8(vec![b' '; pad]).unwrap(); format!("{}{}", pad, string) } else { string } } -fn display_items(items: &Vec, strip: Option<&Path>, options: &getopts::Matches) { +fn display_items(items: &[PathBuf], strip: Option<&Path>, options: &getopts::Matches) { if options.opt_present("long") || options.opt_present("numeric-uid-gid") { let (mut max_links, mut max_size) = (1, 1); for item in items { @@ -454,7 +455,7 @@ fn display_uname(metadata: &Metadata, options: &getopts::Matches) -> String { if options.opt_present("numeric-uid-gid") { metadata.uid().to_string() } else { - entries::uid2usr(metadata.uid()).unwrap_or(metadata.uid().to_string()) + entries::uid2usr(metadata.uid()).unwrap_or_else(|_| metadata.uid().to_string()) } } @@ -463,7 +464,7 @@ fn display_group(metadata: &Metadata, options: &getopts::Matches) -> String { if options.opt_present("numeric-uid-gid") { metadata.gid().to_string() } else { - entries::gid2grp(metadata.gid()).unwrap_or(metadata.gid().to_string()) + entries::gid2grp(metadata.gid()).unwrap_or_else(|_| metadata.gid().to_string()) } } @@ -533,7 +534,7 @@ fn get_file_name(name: &Path, strip: Option<&Path>) -> String { Some(prefix) => name.strip_prefix(prefix).unwrap_or(name), None => name, }; - if name.as_os_str().len() == 0 { + if name.as_os_str().is_empty() { name = Path::new("."); } name.to_string_lossy().into_owned() @@ -601,6 +602,7 @@ macro_rules! has { } #[cfg(unix)] +#[allow(clippy::cognitive_complexity)] fn display_file_name( path: &Path, strip: Option<&Path>, @@ -697,7 +699,7 @@ fn display_file_name( Cell { contents: name, - width: width, + width, } } diff --git a/src/mkdir/mkdir.rs b/src/mkdir/mkdir.rs index c3bc0107e3e..2f37b240074 100644 --- a/src/mkdir/mkdir.rs +++ b/src/mkdir/mkdir.rs @@ -55,16 +55,15 @@ pub fn uumain(args: Vec) -> i32 { // Translate a ~str in octal form to u16, default to 755 // Not tested on Windows let mode_match = matches.opts_str(&["mode".to_owned()]); - let mode: u16 = if mode_match.is_some() { - let m = mode_match.unwrap(); - let res: Option = u16::from_str_radix(&m, 8).ok(); - if res.is_some() { - res.unwrap() - } else { - crash!(1, "no mode given"); - } - } else { - 0o755 as u16 + let mode: u16 = match mode_match { + Some(m) => { + let res: Option = u16::from_str_radix(&m, 8).ok(); + match res { + Some(r) => r, + _ => crash!(1, "no mode given") + } + }, + _ => 0o755 as u16 }; let dirs = matches.free; @@ -76,7 +75,7 @@ pub fn uumain(args: Vec) -> i32 { fn print_help(opts: &getopts::Options) { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); print!( "{}", @@ -128,7 +127,7 @@ fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 { use fs::{Permissions, set_permissions}; use std::os::unix::fs::{PermissionsExt}; - let mode = Permissions::from_mode(mode as u32); + let mode = Permissions::from_mode(u32::from(mode)); if let Err(err) = set_permissions(path, mode) { show_error!( diff --git a/src/mkfifo/mkfifo.rs b/src/mkfifo/mkfifo.rs index df101278715..58d59cb1f77 100644 --- a/src/mkfifo/mkfifo.rs +++ b/src/mkfifo/mkfifo.rs @@ -76,8 +76,9 @@ Create a FIFO with the given name.", let mut exit_status = 0; for f in &matches.free { let err = unsafe { + let name = CString::new(f.as_bytes()).unwrap(); mkfifo( - CString::new(f.as_bytes()).unwrap().as_ptr(), + name.as_ptr(), mode as libc::mode_t, ) }; diff --git a/src/mknod/mknod.rs b/src/mknod/mknod.rs index 0efd7cc92e7..8429d741a72 100644 --- a/src/mknod/mknod.rs +++ b/src/mknod/mknod.rs @@ -31,7 +31,7 @@ const MODE_RW_UGO: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_ #[inline(always)] fn makedev(maj: u64, min: u64) -> dev_t { // pick up from - ((min & 0xff) | ((maj & 0xfff) << 8) | (((min & !0xff)) << 12) | (((maj & !0xfff)) << 32)) + ((min & 0xff) | ((maj & 0xfff) << 8) | ((min & !0xff) << 12) | ((maj & !0xfff) << 32)) as dev_t } @@ -45,6 +45,7 @@ fn _makenod(path: CString, mode: mode_t, dev: dev_t) -> i32 { unsafe { libc::mknod(path.as_ptr(), mode, dev) } } +#[allow(clippy::cognitive_complexity)] pub fn uumain(args: Vec) -> i32 { let mut opts = Options::new(); diff --git a/src/mktemp/mktemp.rs b/src/mktemp/mktemp.rs index 7c65d3e41a0..a35e3bfba9b 100644 --- a/src/mktemp/mktemp.rs +++ b/src/mktemp/mktemp.rs @@ -179,14 +179,14 @@ pub fn dry_exec(mut tmpdir: PathBuf, prefix: &str, rand: usize, suffix: &str) -> rand::thread_rng().fill(bytes); for byte in bytes.iter_mut() { *byte = match *byte % 62 { - v @ 0...9 => (v + '0' as u8), - v @ 10...35 => (v - 10 + 'a' as u8), - v @ 36...61 => (v - 36 + 'A' as u8), + v @ 0..=9 => (v + b'0'), + v @ 10..=35 => (v - 10 + b'a'), + v @ 36..=61 => (v - 36 + b'A'), _ => unreachable!(), } } } - tmpdir.push(String::from(buf)); + tmpdir.push(buf); println!("{}", tmpdir.display()); 0 } diff --git a/src/more/more.rs b/src/more/more.rs index 3a121fada75..334be558b20 100644 --- a/src/more/more.rs +++ b/src/more/more.rs @@ -146,7 +146,7 @@ fn more(matches: getopts::Matches) { if sz == 0 { break; } - stdout().write(&buffer[0..sz]).unwrap(); + stdout().write_all(&buffer[0..sz]).unwrap(); for byte in std::io::stdin().bytes() { match byte.unwrap() { b' ' => break, @@ -164,5 +164,5 @@ fn more(matches: getopts::Matches) { } reset_term(&mut term); - println!(""); + println!(); } diff --git a/src/mv/mv.rs b/src/mv/mv.rs index b6e6b6870a3..5f96a5f1c1b 100644 --- a/src/mv/mv.rs +++ b/src/mv/mv.rs @@ -124,7 +124,7 @@ pub fn uumain(args: Vec) -> i32 { }; let paths: Vec = { - fn strip_slashes<'a>(p: &'a Path) -> &'a Path { + fn strip_slashes(p: &Path) -> &Path { p.components().as_path() } let to_owned = |p: &Path| p.to_owned(); @@ -202,12 +202,10 @@ fn determine_backup_suffix(backup_mode: BackupMode, matches: &getopts::Matches) ); } } + } else if let (Ok(s), BackupMode::SimpleBackup) = (env::var("SIMPLE_BACKUP_SUFFIX"), backup_mode) { + s } else { - if let (Ok(s), BackupMode::SimpleBackup) = (env::var("SIMPLE_BACKUP_SUFFIX"), backup_mode) { - s - } else { - "~".to_owned() - } + "~".to_owned() } } @@ -361,11 +359,9 @@ fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> { fs::rename(to, p)?; } - if b.update { - if fs::metadata(from)?.modified()? <= fs::metadata(to)?.modified()? - { - return Ok(()); - } + if b.update && fs::metadata(from)?.modified()? <= fs::metadata(to)?.modified()? + { + return Ok(()); } } @@ -387,7 +383,7 @@ fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> { print!("‘{}’ -> ‘{}’", from.display(), to.display()); match backup_path { Some(path) => println!(" (backup: ‘{}’)", path.display()), - None => println!(""), + None => println!(), } } Ok(()) @@ -430,8 +426,8 @@ fn existing_backup_path(path: &PathBuf, suffix: &str) -> PathBuf { fn is_empty_dir(path: &PathBuf) -> bool { match fs::read_dir(path) { Ok(contents) => { - return contents.peekable().peek().is_none(); + contents.peekable().peek().is_none() }, - Err(_e) => { return false; } + Err(_e) => { false } } } diff --git a/src/nice/nice.rs b/src/nice/nice.rs index e76165a8e0e..0fb8bf45dc5 100644 --- a/src/nice/nice.rs +++ b/src/nice/nice.rs @@ -120,7 +120,7 @@ process).", .map(|x| CString::new(x.as_bytes()).unwrap()) .collect(); let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect(); - args.push(0 as *const c_char); + args.push(std::ptr::null::()); unsafe { execvp(args[0], args.as_mut_ptr()); } diff --git a/src/nl/nl.rs b/src/nl/nl.rs index 6359b4b93a6..e24d4f0b85f 100644 --- a/src/nl/nl.rs +++ b/src/nl/nl.rs @@ -58,6 +58,7 @@ pub struct Settings { // 2. Number only nonempty lines // 3. Don't number any lines at all // 4. Number all lines that match a basic regular expression. +#[allow(clippy::enum_variant_names)] enum NumberingStyle { NumberForAll, NumberForNonEmpty, @@ -272,7 +273,7 @@ fn nl(reader: &mut BufReader, settings: &Settings) { if matched_groups > 0 { // The current line is a section delimiter, so we output // a blank line. - println!(""); + println!(); // However the line does not count as a blank line, so we // reset the counter used for --join-blank-lines. empty_line_count = 0; @@ -333,10 +334,9 @@ fn nl(reader: &mut BufReader, settings: &Settings) { // way, start counting empties from zero once more. empty_line_count = 0; // A line number is to be printed. - let mut w: usize = 0; - if settings.number_width > line_no_width { - w = settings.number_width - line_no_width; - } + let w = if settings.number_width > line_no_width { + settings.number_width - line_no_width + } else { 0 }; let fill: String = repeat(fill_char).take(w).collect(); match settings.number_format { NumberFormat::Left => println!( @@ -364,7 +364,7 @@ fn pass_regex(line: &str, re: ®ex::Regex) -> bool { } fn pass_nonempty(line: &str, _: ®ex::Regex) -> bool { - line.len() > 0 + !line.is_empty() } fn pass_none(_: &str, _: ®ex::Regex) -> bool { diff --git a/src/nohup/nohup.rs b/src/nohup/nohup.rs index d9d7de6a376..b71c16fb575 100644 --- a/src/nohup/nohup.rs +++ b/src/nohup/nohup.rs @@ -71,7 +71,7 @@ pub fn uumain(args: Vec) -> i32 { unsafe { signal(SIGHUP, SIG_IGN) }; - if unsafe { _vprocmgr_detach_from_console(0) } != std::ptr::null() { + if unsafe { !_vprocmgr_detach_from_console(0).is_null() } { crash!(2, "Cannot detach from console") }; @@ -105,10 +105,8 @@ fn replace_fds() { } } - if is_stderr_interactive() { - if unsafe { dup2(1, 2) } != 2 { - crash!(2, "Cannot replace STDERR: {}", Error::last_os_error()) - } + if is_stderr_interactive() && unsafe { dup2(1, 2) } != 2 { + crash!(2, "Cannot replace STDERR: {}", Error::last_os_error()) } } diff --git a/src/nproc/nproc.rs b/src/nproc/nproc.rs index 6a35520cd87..0b7d48ceb60 100644 --- a/src/nproc/nproc.rs +++ b/src/nproc/nproc.rs @@ -115,12 +115,10 @@ fn num_cpus_all() -> usize { // In some situation, /proc and /sys are not mounted, and sysconf returns 1. // However, we want to guarantee that `nproc --all` >= `nproc`. num_cpus::get() + } else if nprocs > 0 { + nprocs as usize } else { - if nprocs > 0 { - nprocs as usize - } else { - 1 - } + 1 } } diff --git a/src/numfmt/numfmt.rs b/src/numfmt/numfmt.rs index 3c34d4a19ae..32e3731dba5 100644 --- a/src/numfmt/numfmt.rs +++ b/src/numfmt/numfmt.rs @@ -21,15 +21,15 @@ static VERSION: &str = env!("CARGO_PKG_VERSION"); const IEC_BASES: [f64; 10] = [ //premature optimization 1., - 1024., - 1048576., - 1073741824., - 1099511627776., - 1125899906842624., - 1152921504606846976., - 1180591620717411303424., - 1208925819614629174706176., - 1237940039285380274899124224., + 1_024., + 1_048_576., + 1_073_741_824., + 1_099_511_627_776., + 1_125_899_906_842_624., + 1_152_921_504_606_846_976., + 1_180_591_620_717_411_303_424., + 1_208_925_819_614_629_174_706_176., + 1_237_940_039_285_380_274_899_124_224., ]; type Result = std::result::Result; @@ -78,7 +78,7 @@ impl fmt::Display for DisplayableSuffix { } fn parse_suffix(s: String) -> Result<(f64, Option)> { - let with_i = s.ends_with("i"); + let with_i = s.ends_with('i'); let mut iter = s.chars(); if with_i { iter.next_back(); @@ -92,7 +92,7 @@ fn parse_suffix(s: String) -> Result<(f64, Option)> { Some('E') => Ok(Some((RawSuffix::E, with_i))), Some('Z') => Ok(Some((RawSuffix::Z, with_i))), Some('Y') => Ok(Some((RawSuffix::Y, with_i))), - Some('0'...'9') => Ok(None), + Some('0'..='9') => Ok(None), _ => Err("Failed to parse suffix"), }?; @@ -251,13 +251,13 @@ fn parse_options(args: &Matches) -> Result { }?; Ok(NumfmtOptions { - transform: transform, - padding: padding, - header: header, + transform, + padding, + header, }) } -fn handle_args(args: &Vec, options: NumfmtOptions) -> Result<()> { +fn handle_args(args: &[String], options: NumfmtOptions) -> Result<()> { for l in args { println!("{}", format_string(l.clone(), &options)?) } @@ -276,7 +276,8 @@ fn handle_stdin(options: NumfmtOptions) -> Result<()> { for l in lines { l.map_err(|e| e.to_string()).and_then(|l| { let l = format_string(l, &options)?; - Ok(println!("{}", l)) + println!("{}", l); + Ok(()) })? } Ok(()) @@ -315,10 +316,10 @@ pub fn uumain(args: Vec) -> i32 { let matches = opts.parse(&args[1..]).unwrap(); if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {0} [STRING]... [OPTION]...", NAME); - println!(""); + println!(); print!( "{}", opts.usage("Convert numbers from/to human-readable strings") @@ -353,7 +354,7 @@ pub fn uumain(args: Vec) -> i32 { let options = parse_options(&matches).unwrap(); - if matches.free.len() == 0 { + if matches.free.is_empty() { handle_stdin(options).unwrap() } else { handle_args(&matches.free, options).unwrap() diff --git a/src/od/formatteriteminfo.rs b/src/od/formatteriteminfo.rs index 29d5cb6d9c0..946106fc7ce 100644 --- a/src/od/formatteriteminfo.rs +++ b/src/od/formatteriteminfo.rs @@ -31,16 +31,16 @@ impl Eq for FormatWriter {} impl fmt::Debug for FormatWriter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &FormatWriter::IntWriter(ref p) => { + match *self { + FormatWriter::IntWriter(ref p) => { f.write_str("IntWriter:")?; fmt::Pointer::fmt(p, f) } - &FormatWriter::FloatWriter(ref p) => { + FormatWriter::FloatWriter(ref p) => { f.write_str("FloatWriter:")?; fmt::Pointer::fmt(p, f) } - &FormatWriter::MultibyteWriter(ref p) => { + FormatWriter::MultibyteWriter(ref p) => { f.write_str("MultibyteWriter:")?; fmt::Pointer::fmt(&(*p as *const ()), f) } diff --git a/src/od/inputdecoder.rs b/src/od/inputdecoder.rs index cd4a0feecc6..50a4c081b92 100644 --- a/src/od/inputdecoder.rs +++ b/src/od/inputdecoder.rs @@ -43,12 +43,12 @@ impl<'a, I> InputDecoder<'a, I> { } // fast but uninitialized InputDecoder { - input: input, + input, data: bytes, reserved_peek_length: peek_length, used_normal_length: 0, used_peek_length: 0, - byte_order: byte_order, + byte_order, } } } @@ -133,9 +133,9 @@ impl<'a> MemoryDecoder<'a> { /// Returns a u8/u16/u32/u64 from the internal buffer at position `start`. pub fn read_uint(&self, start: usize, byte_size: usize) -> u64 { match byte_size { - 1 => self.data[start] as u64, - 2 => self.byte_order.read_u16(&self.data[start..start + 2]) as u64, - 4 => self.byte_order.read_u32(&self.data[start..start + 4]) as u64, + 1 => u64::from(self.data[start]), + 2 => u64::from(self.byte_order.read_u16(&self.data[start..start + 2])), + 4 => u64::from(self.byte_order.read_u32(&self.data[start..start + 4])), 8 => self.byte_order.read_u64(&self.data[start..start + 8]), _ => panic!("Invalid byte_size: {}", byte_size), } @@ -147,7 +147,7 @@ impl<'a> MemoryDecoder<'a> { 2 => f64::from(f16::from_bits( self.byte_order.read_u16(&self.data[start..start + 2]), )), - 4 => self.byte_order.read_f32(&self.data[start..start + 4]) as f64, + 4 => f64::from(self.byte_order.read_f32(&self.data[start..start + 4])), 8 => self.byte_order.read_f64(&self.data[start..start + 8]), _ => panic!("Invalid byte_size: {}", byte_size), } diff --git a/src/od/inputoffset.rs b/src/od/inputoffset.rs index 102f1656b84..8f3030edfce 100644 --- a/src/od/inputoffset.rs +++ b/src/od/inputoffset.rs @@ -21,9 +21,9 @@ impl InputOffset { /// creates a new `InputOffset` using the provided values. pub fn new(radix: Radix, byte_pos: usize, label: Option) -> InputOffset { InputOffset { - radix: radix, - byte_pos: byte_pos, - label: label, + radix, + byte_pos, + label, } } @@ -58,7 +58,7 @@ impl InputOffset { /// both `Radix::NoPrefix` was set and no label (--traditional) is used. pub fn print_final_offset(&self) { if self.radix != Radix::NoPrefix || self.label.is_some() { - print!("{}\n", self.format_byte_offset()); + println!("{}", self.format_byte_offset()); } } } diff --git a/src/od/multifilereader.rs b/src/od/multifilereader.rs index b53216cabb9..b0fb34b8d94 100644 --- a/src/od/multifilereader.rs +++ b/src/od/multifilereader.rs @@ -36,7 +36,7 @@ impl<'b> MultifileReader<'b> { fn next_file(&mut self) { // loop retries with subsequent files if err - normally 'loops' once loop { - if self.ni.len() == 0 { + if self.ni.is_empty() { self.curr_file = None; break; } diff --git a/src/od/od.rs b/src/od/od.rs index 03fd0d55ab4..9ed0d395324 100644 --- a/src/od/od.rs +++ b/src/od/od.rs @@ -224,7 +224,7 @@ impl OdOptions { let formats = match parse_format_flags(&args) { Ok(f) => f, Err(e) => { - return Err(format!("{}", e)); + return Err(e); } }; @@ -260,7 +260,7 @@ impl OdOptions { Some(s) => { let st = s.into_bytes(); if st.len() != 1 { - return Err(format!("Radix must be one of [d, o, n, x]")); + return Err("Radix must be one of [d, o, n, x]".to_string()); } else { let radix: char = *(st.get(0).expect("byte string of length 1 lacks a 0th elem")) as char; @@ -269,22 +269,22 @@ impl OdOptions { 'x' => Radix::Hexadecimal, 'o' => Radix::Octal, 'n' => Radix::NoPrefix, - _ => return Err(format!("Radix must be one of [d, o, n, x]")), + _ => return Err("Radix must be one of [d, o, n, x]".to_string()), } } } }; Ok(OdOptions { - byte_order: byte_order, - skip_bytes: skip_bytes, - read_bytes: read_bytes, - label: label, - input_strings: input_strings, - formats: formats, - line_bytes: line_bytes, - output_duplicates: output_duplicates, - radix: radix, + byte_order, + skip_bytes, + read_bytes, + label, + input_strings, + formats, + line_bytes, + output_duplicates, + radix, }) } } @@ -469,7 +469,7 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &Output // lines of multi-format rasters. print!("{:>width$}", "", width = prefix.chars().count()); } - print!("{}\n", output_text); + println!("{}", output_text); } } @@ -478,7 +478,7 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &Output /// `skip_bytes` is the number of bytes skipped from the input /// `read_bytes` is an optional limit to the number of bytes to read fn open_input_peek_reader<'a>( - input_strings: &'a Vec, + input_strings: &'a [String], skip_bytes: usize, read_bytes: Option, ) -> PeekReader>> { @@ -493,6 +493,5 @@ fn open_input_peek_reader<'a>( let mf = MultifileReader::new(inputs); let pr = PartialReader::new(mf, skip_bytes, read_bytes); - let input = PeekReader::new(pr); - input + PeekReader::new(pr) } diff --git a/src/od/output_info.rs b/src/od/output_info.rs index eaf46296ce0..edcccd91351 100644 --- a/src/od/output_info.rs +++ b/src/od/output_info.rs @@ -69,11 +69,11 @@ impl OutputInfo { OutputInfo { byte_size_line: line_bytes, - print_width_line: print_width_line, - byte_size_block: byte_size_block, - print_width_block: print_width_block, - spaced_formatters: spaced_formatters, - output_duplicates: output_duplicates, + print_width_line, + byte_size_block, + print_width_block, + spaced_formatters, + output_duplicates, } } diff --git a/src/od/parse_formats.rs b/src/od/parse_formats.rs index f8c3659f000..36ce3604ef1 100644 --- a/src/od/parse_formats.rs +++ b/src/od/parse_formats.rs @@ -15,8 +15,8 @@ impl ParsedFormatterItemInfo { add_ascii_dump: bool, ) -> ParsedFormatterItemInfo { ParsedFormatterItemInfo { - formatter_item_info: formatter_item_info, - add_ascii_dump: add_ascii_dump, + formatter_item_info, + add_ascii_dump, } } } @@ -100,14 +100,14 @@ fn od_argument_with_option(ch: char) -> bool { /// arguments with parameters like -w16 can only appear at the end: -fvoxw16 /// parameters of -t/--format specify 1 or more formats. /// if -- appears on the commandline, parsing should stop. -pub fn parse_format_flags(args: &Vec) -> Result, String> { +pub fn parse_format_flags(args: &[String]) -> Result, String> { let mut formats = Vec::new(); // args[0] is the name of the binary - let mut arg_iter = args.iter().skip(1); + let arg_iter = args.iter().skip(1); let mut expect_type_string = false; - while let Some(arg) = arg_iter.next() { + for arg in arg_iter { if expect_type_string { match parse_type_string(arg) { Ok(v) => formats.extend(v.into_iter()), @@ -128,10 +128,10 @@ pub fn parse_format_flags(args: &Vec) -> Result) -> Result { decimal_size.push(d); - return true; + true } _ => false, } @@ -266,13 +264,13 @@ fn is_format_dump_char(ch: Option, show_ascii_dump: &mut bool) -> bool { match ch { Some('z') => { *show_ascii_dump = true; - return true; + true } _ => false, } } -fn parse_type_string(params: &String) -> Result, String> { +fn parse_type_string(params: &str) -> Result, String> { let mut formats = Vec::new(); let mut chars = params.chars(); diff --git a/src/od/parse_inputs.rs b/src/od/parse_inputs.rs index b1ab1742770..b777b8e1603 100644 --- a/src/od/parse_inputs.rs +++ b/src/od/parse_inputs.rs @@ -14,7 +14,7 @@ impl CommandLineOpts for Matches { self.free.clone() } fn opts_present(&self, opts: &[&str]) -> bool { - self.opts_present(&opts.iter().map(|s| s.to_string()).collect::>()) + self.opts_present(&opts.iter().map(|s| (*s).to_string()).collect::>()) } } @@ -52,28 +52,23 @@ pub fn parse_inputs(matches: &dyn CommandLineOpts) -> Result { - // if there is just 1 input (stdin), an offset must start with '+' - if input_strings.len() == 1 && input_strings[0].starts_with("+") { - return Ok(CommandLineInputs::FileAndOffset(("-".to_string(), n, None))); - } - if input_strings.len() == 2 { - return Ok(CommandLineInputs::FileAndOffset(( - input_strings[0].clone(), - n, - None, - ))); - } + if let Ok(n) = offset { + // if there is just 1 input (stdin), an offset must start with '+' + if input_strings.len() == 1 && input_strings[0].starts_with('+') { + return Ok(CommandLineInputs::FileAndOffset(("-".to_string(), n, None))); } - _ => { - // if it cannot be parsed, it is considered a filename + if input_strings.len() == 2 { + return Ok(CommandLineInputs::FileAndOffset(( + input_strings[0].clone(), + n, + None, + ))); } } } } - if input_strings.len() == 0 { + if input_strings.is_empty() { input_strings.push("-".to_string()); } Ok(CommandLineInputs::FileNames(input_strings)) @@ -131,13 +126,13 @@ pub fn parse_inputs_traditional(input_strings: Vec) -> Result Result { +pub fn parse_offset_operand(s: &str) -> Result { let mut start = 0; let mut len = s.len(); let mut radix = 8; let mut multiply = 1; - if s.starts_with("+") { + if s.starts_with('+') { start += 1; } @@ -145,11 +140,11 @@ pub fn parse_offset_operand(s: &String) -> Result { start += 2; radix = 16; } else { - if s[start..len].ends_with("b") { + if s[start..len].ends_with('b') { len -= 1; multiply = 512; } - if s[start..len].ends_with(".") { + if s[start..len].ends_with('.') { len -= 1; radix = 10; } @@ -177,7 +172,7 @@ mod tests { fn new(inputs: Vec<&'a str>, option_names: Vec<&'a str>) -> MockOptions<'a> { MockOptions { inputs: inputs.iter().map(|s| s.to_string()).collect::>(), - option_names: option_names, + option_names, } } } diff --git a/src/od/parse_nrofbytes.rs b/src/od/parse_nrofbytes.rs index c934de9c5b7..d2ba1527bea 100644 --- a/src/od/parse_nrofbytes.rs +++ b/src/od/parse_nrofbytes.rs @@ -1,4 +1,4 @@ -pub fn parse_number_of_bytes(s: &String) -> Result { +pub fn parse_number_of_bytes(s: &str) -> Result { let mut start = 0; let mut len = s.len(); let mut radix = 10; @@ -7,7 +7,7 @@ pub fn parse_number_of_bytes(s: &String) -> Result { if s.starts_with("0x") || s.starts_with("0X") { start = 2; radix = 16; - } else if s.starts_with("0") { + } else if s.starts_with('0') { radix = 8; } diff --git a/src/od/partialreader.rs b/src/od/partialreader.rs index 42bca6428f0..d8e2310d25b 100644 --- a/src/od/partialreader.rs +++ b/src/od/partialreader.rs @@ -22,9 +22,9 @@ impl PartialReader { /// to `None` if there should be no limit. pub fn new(inner: R, skip: usize, limit: Option) -> Self { PartialReader { - inner: inner, - skip: skip, - limit: limit, + inner, + skip, + limit, } } } diff --git a/src/od/peekreader.rs b/src/od/peekreader.rs index 825335f20fd..10428a77f7e 100644 --- a/src/od/peekreader.rs +++ b/src/od/peekreader.rs @@ -41,7 +41,7 @@ impl PeekReader { /// Create a new `PeekReader` wrapping `inner` pub fn new(inner: R) -> Self { PeekReader { - inner: inner, + inner, temp_buffer: Vec::new(), } } @@ -61,7 +61,7 @@ impl PeekReader { fn write_to_tempbuffer(&mut self, bytes: &[u8]) { // if temp_buffer is not empty, data has to be inserted in front let org_buffer: Vec<_> = self.temp_buffer.drain(..).collect(); - self.temp_buffer.write(bytes).unwrap(); + self.temp_buffer.write_all(bytes).unwrap(); self.temp_buffer.extend(org_buffer); } } diff --git a/src/od/prn_char.rs b/src/od/prn_char.rs index 4caf068fa13..58ad323ef55 100644 --- a/src/od/prn_char.rs +++ b/src/od/prn_char.rs @@ -30,7 +30,7 @@ fn format_item_a(p: u64) -> String { format!("{:>4}", A_CHRS.get(b as usize).unwrap_or(&"??")) } -static C_CHRS: [&'static str; 128] = [ +static C_CHRS: [&str; 128] = [ "\\0", "001", "002", "003", "004", "005", "006", "\\a", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "016", "017", "020", "021", "022", "023", "024", "025", "026", "027", "030", "031", "032", "033", "034", "035", "036", "037", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", diff --git a/src/od/prn_float.rs b/src/od/prn_float.rs index 19ba3cca396..99e259b200a 100644 --- a/src/od/prn_float.rs +++ b/src/od/prn_float.rs @@ -48,7 +48,7 @@ fn format_flo32(f: f32) -> String { // subnormal numbers will be normal as f64, so will print with a wrong precision format!("{:width$e}", f, width = width) // subnormal numbers } else { - format_float(f as f64, width, precision) + format_float(f64::from(f), width, precision) } } @@ -72,7 +72,7 @@ fn format_float(f: f64, width: usize, precision: usize) -> String { let r = 10f64.powi(l); if (f > 0.0 && r > f) || (f < 0.0 && -r < f) { // fix precision error - l = l - 1; + l -= 1; } if l >= 0 && l <= (precision as i32 - 1) { diff --git a/src/paste/paste.rs b/src/paste/paste.rs index bffe0b96fee..59e4762ee03 100644 --- a/src/paste/paste.rs +++ b/src/paste/paste.rs @@ -60,7 +60,7 @@ FILE, separated by TABs, to standard output.", println!("{} {}", NAME, VERSION); } else { let serial = matches.opt_present("serial"); - let delimiters = matches.opt_str("delimiters").unwrap_or("\t".to_owned()); + let delimiters = matches.opt_str("delimiters").unwrap_or_else(|| "\t".to_owned()); paste(matches.free, serial, delimiters); } diff --git a/src/pathchk/pathchk.rs b/src/pathchk/pathchk.rs index 8159c24c931..83d30f5d221 100644 --- a/src/pathchk/pathchk.rs +++ b/src/pathchk/pathchk.rs @@ -86,11 +86,10 @@ pub fn uumain(args: Vec) -> i32 { 0 } _ => { - let mut res = true; - if matches.free.len() == 0 { + let mut res = if matches.free.is_empty() { show_error!("missing operand\nTry {} --help for more information", NAME); - res = false; - } + false + } else { true }; // free strings are path operands // FIXME: TCS, seems inefficient and overly verbose (?) for p in matches.free { @@ -189,7 +188,7 @@ fn check_extra(path: &[String]) -> bool { } } // path length - if path.join("/").len() == 0 { + if path.join("/").is_empty() { writeln!(&mut std::io::stderr(), "empty file name"); return false; } @@ -230,7 +229,7 @@ fn check_default(path: &[String]) -> bool { } // check whether a path is or if other problems arise -fn check_searchable(path: &String) -> bool { +fn check_searchable(path: &str) -> bool { // we use lstat, just like the original implementation match fs::symlink_metadata(path) { Ok(_) => true, @@ -244,12 +243,12 @@ fn check_searchable(path: &String) -> bool { } // check for a hyphen at the beginning of a path segment -fn no_leading_hyphen(path_segment: &String) -> bool { +fn no_leading_hyphen(path_segment: &str) -> bool { !path_segment.starts_with('-') } // check whether a path segment contains only valid (read: portable) characters -fn check_portable_chars(path_segment: &String) -> bool { +fn check_portable_chars(path_segment: &str) -> bool { let valid_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-".to_string(); for ch in path_segment.chars() { if !valid_str.contains(ch) { diff --git a/src/pinky/pinky.rs b/src/pinky/pinky.rs index 0edf3e0f2a8..f604846d530 100644 --- a/src/pinky/pinky.rs +++ b/src/pinky/pinky.rs @@ -125,13 +125,13 @@ The utmp file will be {}", } let pk = Pinky { - include_idle: include_idle, - include_heading: include_heading, - include_fullname: include_fullname, - include_project: include_project, - include_plan: include_plan, - include_home_and_shell: include_home_and_shell, - include_where: include_where, + include_idle, + include_heading, + include_fullname, + include_project, + include_plan, + include_home_and_shell, + include_where, names: matches.free, }; @@ -254,7 +254,7 @@ impl Pinky { let ut_host = ut.host(); let mut res = ut_host.splitn(2, ':'); let host = match res.next() { - Some(_) => ut.canon_host().unwrap_or(ut_host.clone()), + Some(_) => ut.canon_host().unwrap_or_else(|_| ut_host.clone()), None => ut_host.clone(), }; match res.next() { @@ -263,7 +263,7 @@ impl Pinky { } } - println!(""); + println!(); } fn print_heading(&self) { @@ -279,7 +279,7 @@ impl Pinky { if self.include_where { print!(" Where"); } - println!(""); + println!(); } fn short_pinky(&self) -> IOResult<()> { @@ -290,10 +290,8 @@ impl Pinky { if ut.is_user_process() { if self.names.is_empty() { self.print_entry(&ut) - } else { - if self.names.iter().any(|n| n.as_str() == ut.user()) { + } else if self.names.iter().any(|n| n.as_str() == ut.user()) { self.print_entry(&ut); - } } } } @@ -325,7 +323,7 @@ impl Pinky { read_to_console(f); } } - println!(""); + println!(); } else { println!(" ???"); } diff --git a/src/printf/cli.rs b/src/printf/cli.rs index e69cdf3c9f5..a6d185017ac 100644 --- a/src/printf/cli.rs +++ b/src/printf/cli.rs @@ -1,5 +1,4 @@ //! stdio convenience fns -#[allow(unused_must_use)] use std::io::{stderr, stdout, Write}; use std::env; @@ -18,7 +17,7 @@ pub fn err_msg(msg: &str) { // by default stdout only flushes // to console when a newline is passed. #[allow(unused_must_use)] -pub fn flush_char(c: &char) { +pub fn flush_char(c: char) { print!("{}", c); stdout().flush(); } diff --git a/src/printf/memo.rs b/src/printf/memo.rs index e006f22b5b8..226178e4bb2 100644 --- a/src/printf/memo.rs +++ b/src/printf/memo.rs @@ -25,26 +25,22 @@ fn warn_excess_args(first_arg: &str) { } impl Memo { - pub fn new(pf_string: &String, pf_args_it: &mut Peekable>) -> Memo { + pub fn new(pf_string: &str, pf_args_it: &mut Peekable>) -> Memo { let mut pm = Memo { tokens: Vec::new() }; let mut tmp_token: Option>; let mut it = put_back_n(pf_string.chars()); let mut has_sub = false; loop { tmp_token = UnescapedText::from_it(&mut it, pf_args_it); - match tmp_token { - Some(x) => pm.tokens.push(x), - None => {} + if let Some(x) = tmp_token { + pm.tokens.push(x); } tmp_token = Sub::from_it(&mut it, pf_args_it); - match tmp_token { - Some(x) => { - if !has_sub { - has_sub = true; - } - pm.tokens.push(x); + if let Some(x) = tmp_token { + if !has_sub { + has_sub = true; } - None => {} + pm.tokens.push(x); } if let Some(x) = it.next() { it.put_back(x); @@ -74,9 +70,9 @@ impl Memo { tkn.print(pf_args_it); } } - pub fn run_all(pf_string: &String, pf_args: &[String]) { + pub fn run_all(pf_string: &str, pf_args: &[String]) { let mut arg_it = pf_args.iter().peekable(); - let pm = Memo::new(pf_string, &mut arg_it); + let pm = Memo::new(&pf_string.to_string(), &mut arg_it); loop { if arg_it.peek().is_none() { break; diff --git a/src/printf/printf.rs b/src/printf/printf.rs index 1842f883128..05b4b94640a 100644 --- a/src/printf/printf.rs +++ b/src/printf/printf.rs @@ -282,7 +282,7 @@ pub fn uumain(args: Vec) -> i32 { ); return 1; } - let ref formatstr = args[1]; + let formatstr = &args[1]; if formatstr == "--help" { print!("{} {}", LONGHELP_LEAD, LONGHELP_BODY); @@ -292,5 +292,5 @@ pub fn uumain(args: Vec) -> i32 { let printf_args = &args[2..]; memo::Memo::run_all(formatstr, printf_args); } - return 0; + 0 } diff --git a/src/printf/tokenize/mod.rs b/src/printf/tokenize/mod.rs index 0570b74896d..dfcdeb095eb 100644 --- a/src/printf/tokenize/mod.rs +++ b/src/printf/tokenize/mod.rs @@ -1,4 +1,5 @@ pub mod token; pub mod sub; pub mod unescaped_text; +#[allow(clippy::module_inception)] mod num_format; diff --git a/src/printf/tokenize/num_format/formatters/base_conv/mod.rs b/src/printf/tokenize/num_format/formatters/base_conv/mod.rs index e2b8f0b0ada..f288e95cc82 100644 --- a/src/printf/tokenize/num_format/formatters/base_conv/mod.rs +++ b/src/printf/tokenize/num_format/formatters/base_conv/mod.rs @@ -1,9 +1,9 @@ -pub fn arrnum_int_mult(arr_num: &Vec, basenum: u8, base_ten_int_fact: u8) -> Vec { +pub fn arrnum_int_mult(arr_num: &[u8], basenum: u8, base_ten_int_fact: u8) -> Vec { let mut carry: u16 = 0; let mut rem: u16; let mut new_amount: u16; - let fact: u16 = base_ten_int_fact as u16; - let base: u16 = basenum as u16; + let fact: u16 = u16::from(base_ten_int_fact); + let base: u16 = u16::from(basenum); let mut ret_rev: Vec = Vec::new(); let mut it = arr_num.iter().rev(); @@ -11,7 +11,7 @@ pub fn arrnum_int_mult(arr_num: &Vec, basenum: u8, base_ten_int_fact: u8) -> let i = it.next(); match i { Some(u) => { - new_amount = ((u.clone() as u16) * fact) + carry; + new_amount = (u16::from(*u) * fact) + carry; rem = new_amount % base; carry = (new_amount - rem) / base; ret_rev.push(rem as u8) @@ -26,7 +26,8 @@ pub fn arrnum_int_mult(arr_num: &Vec, basenum: u8, base_ten_int_fact: u8) -> } } } - let ret: Vec = ret_rev.iter().rev().map(|x| x.clone()).collect(); + #[allow(clippy::map_clone)] + let ret: Vec = ret_rev.iter().rev().map(|x| *x).collect(); ret } @@ -41,12 +42,12 @@ pub struct DivOut<'a> { pub remainder: Remainder<'a>, } -pub fn arrnum_int_div_step<'a>( - rem_in: Remainder<'a>, +pub fn arrnum_int_div_step( + rem_in: Remainder, radix_in: u8, base_ten_int_divisor: u8, after_decimal: bool, -) -> DivOut<'a> { +) -> DivOut { let mut rem_out = Remainder { position: rem_in.position, replace: Vec::new(), @@ -54,8 +55,8 @@ pub fn arrnum_int_div_step<'a>( }; let mut bufferval: u16 = 0; - let base: u16 = radix_in as u16; - let divisor: u16 = base_ten_int_divisor as u16; + let base: u16 = u16::from(radix_in); + let divisor: u16 = u16::from(base_ten_int_divisor); let mut traversed = 0; let mut quotient = 0; @@ -64,9 +65,9 @@ pub fn arrnum_int_div_step<'a>( let mut it_f = refd_vals.iter(); loop { let u = match it_replace.next() { - Some(u_rep) => u_rep.clone() as u16, + Some(u_rep) => u16::from(*u_rep), None => match it_f.next() { - Some(u_orig) => u_orig.clone() as u16, + Some(u_orig) => u16::from(*u_orig), None => { if !after_decimal { break; @@ -86,8 +87,7 @@ pub fn arrnum_int_div_step<'a>( Vec::new() } else { let remainder_as_arrnum = unsigned_to_arrnum(bufferval); - let remainder_as_base_arrnum = base_conv_vec(&remainder_as_arrnum, 10, radix_in); - remainder_as_base_arrnum + base_conv_vec(&remainder_as_arrnum, 10, radix_in) }; rem_out.position += 1 + (traversed - rem_out.replace.len()); break; @@ -96,7 +96,7 @@ pub fn arrnum_int_div_step<'a>( } } DivOut { - quotient: quotient, + quotient, remainder: rem_out, } } @@ -164,11 +164,11 @@ pub fn arrnum_int_div_step<'a>( // ArrFloatDivOut { quotient: quotient, remainder: remainder } // } // -pub fn arrnum_int_add(arrnum: &Vec, basenum: u8, base_ten_int_term: u8) -> Vec { - let mut carry: u16 = base_ten_int_term as u16; +pub fn arrnum_int_add(arrnum: &[u8], basenum: u8, base_ten_int_term: u8) -> Vec { + let mut carry: u16 = u16::from(base_ten_int_term); let mut rem: u16; let mut new_amount: u16; - let base: u16 = basenum as u16; + let base: u16 = u16::from(basenum); let mut ret_rev: Vec = Vec::new(); let mut it = arrnum.iter().rev(); @@ -176,7 +176,7 @@ pub fn arrnum_int_add(arrnum: &Vec, basenum: u8, base_ten_int_term: u8) -> V let i = it.next(); match i { Some(u) => { - new_amount = (u.clone() as u16) + carry; + new_amount = u16::from(*u) + carry; rem = new_amount % base; carry = (new_amount - rem) / base; ret_rev.push(rem as u8) @@ -191,23 +191,24 @@ pub fn arrnum_int_add(arrnum: &Vec, basenum: u8, base_ten_int_term: u8) -> V } } } - let ret: Vec = ret_rev.iter().rev().map(|x| x.clone()).collect(); + #[allow(clippy::map_clone)] + let ret: Vec = ret_rev.iter().rev().map(|x| *x).collect(); ret } -pub fn base_conv_vec(src: &Vec, radix_src: u8, radix_dest: u8) -> Vec { +pub fn base_conv_vec(src: &[u8], radix_src: u8, radix_dest: u8) -> Vec { let mut result: Vec = Vec::new(); result.push(0); for i in src { result = arrnum_int_mult(&result, radix_dest, radix_src); - result = arrnum_int_add(&result, radix_dest, i.clone()); + result = arrnum_int_add(&result, radix_dest, *i); } result } pub fn unsigned_to_arrnum(src: u16) -> Vec { let mut result: Vec = Vec::new(); - let mut src_tmp: u16 = src.clone(); + let mut src_tmp: u16 = src; while src_tmp > 0 { result.push((src_tmp % 10) as u8); src_tmp /= 10; @@ -218,24 +219,22 @@ pub fn unsigned_to_arrnum(src: u16) -> Vec { // temporary needs-improvement-function #[allow(unused_variables)] -pub fn base_conv_float(src: &Vec, radix_src: u8, radix_dest: u8) -> f64 { +pub fn base_conv_float(src: &[u8], radix_src: u8, radix_dest: u8) -> f64 { // it would require a lot of addl code // to implement this for arbitrary string input. // until then, the below operates as an outline // of how it would work. let mut result: Vec = Vec::new(); result.push(0); - let mut factor: f64 = 1.; - let radix_src_float: f64 = radix_src as f64; - let mut i = 0; - let mut r: f64 = 0 as f64; - for u in src { + let mut factor: f64 = 1_f64; + let radix_src_float: f64 = f64::from(radix_src); + let mut r: f64 = 0_f64; + for (i, u) in src.iter().enumerate() { if i > 15 { break; } - i += 1; factor /= radix_src_float; - r += factor * (u.clone() as f64) + r += factor * f64::from(*u) } r } @@ -243,6 +242,7 @@ pub fn base_conv_float(src: &Vec, radix_src: u8, radix_dest: u8) -> f64 { pub fn str_to_arrnum(src: &str, radix_def_src: &dyn RadixDef) -> Vec { let mut intermed_in: Vec = Vec::new(); for c in src.chars() { + #[allow(clippy::single_match)] match radix_def_src.from_char(c) { Some(u) => { intermed_in.push(u); @@ -253,9 +253,10 @@ pub fn str_to_arrnum(src: &str, radix_def_src: &dyn RadixDef) -> Vec { intermed_in } -pub fn arrnum_to_str(src: &Vec, radix_def_dest: &dyn RadixDef) -> String { +pub fn arrnum_to_str(src: &[u8], radix_def_dest: &dyn RadixDef) -> String { let mut str_out = String::new(); for u in src.iter() { + #[allow(clippy::single_match)] match radix_def_dest.from_u8(u.clone()) { Some(c) => { str_out.push(c); @@ -288,9 +289,9 @@ pub trait RadixDef { } pub struct RadixTen; -const ZERO_ASC: u8 = '0' as u8; -const UPPER_A_ASC: u8 = 'A' as u8; -const LOWER_A_ASC: u8 = 'a' as u8; +const ZERO_ASC: u8 = b'0'; +const UPPER_A_ASC: u8 = b'A'; +const LOWER_A_ASC: u8 = b'a'; impl RadixDef for RadixTen { fn get_max(&self) -> u8 { @@ -298,13 +299,13 @@ impl RadixDef for RadixTen { } fn from_char(&self, c: char) -> Option { match c { - '0'...'9' => Some(c as u8 - ZERO_ASC), + '0'..='9' => Some(c as u8 - ZERO_ASC), _ => None, } } fn from_u8(&self, u: u8) -> Option { match u { - 0...9 => Some((ZERO_ASC + u) as char), + 0..=9 => Some((ZERO_ASC + u) as char), _ => None, } } @@ -316,16 +317,16 @@ impl RadixDef for RadixHex { } fn from_char(&self, c: char) -> Option { match c { - '0'...'9' => Some(c as u8 - ZERO_ASC), - 'A'...'F' => Some(c as u8 + 10 - UPPER_A_ASC), - 'a'...'f' => Some(c as u8 + 10 - LOWER_A_ASC), + '0'..='9' => Some(c as u8 - ZERO_ASC), + 'A'..='F' => Some(c as u8 + 10 - UPPER_A_ASC), + 'a'..='f' => Some(c as u8 + 10 - LOWER_A_ASC), _ => None, } } fn from_u8(&self, u: u8) -> Option { match u { - 0...9 => Some((ZERO_ASC + u) as char), - 10...15 => Some((UPPER_A_ASC + (u - 10)) as char), + 0..=9 => Some((ZERO_ASC + u) as char), + 10..=15 => Some((UPPER_A_ASC + (u - 10)) as char), _ => None, } } diff --git a/src/printf/tokenize/num_format/formatters/cninetyninehexfloatf.rs b/src/printf/tokenize/num_format/formatters/cninetyninehexfloatf.rs index 9d226818ce3..72dc13af243 100644 --- a/src/printf/tokenize/num_format/formatters/cninetyninehexfloatf.rs +++ b/src/printf/tokenize/num_format/formatters/cninetyninehexfloatf.rs @@ -60,7 +60,7 @@ fn get_primitive_hex( Some(pos) => (&str_in[..pos], &str_in[pos + 1..]), None => (&str_in[..], "0"), }; - if first_segment_raw.len() == 0 { + if first_segment_raw.is_empty() { first_segment_raw = "0"; } // convert to string, hexifying if input is in dec. diff --git a/src/printf/tokenize/num_format/formatters/decf.rs b/src/printf/tokenize/num_format/formatters/decf.rs index 46de17290ad..2cbb3f69600 100644 --- a/src/printf/tokenize/num_format/formatters/decf.rs +++ b/src/printf/tokenize/num_format/formatters/decf.rs @@ -53,23 +53,20 @@ impl Formatter for Decf { Some(*field.field_char == 'G'), ); // strip trailing zeroes - match f_sci.post_decimal.clone() { - Some(ref post_dec) => { - let mut i = post_dec.len(); - { - let mut it = post_dec.chars(); - while let Some(c) = it.next_back() { - if c != '0' { - break; - } - i -= 1; + if let Some(ref post_dec) = f_sci.post_decimal.clone() { + let mut i = post_dec.len(); + { + let mut it = post_dec.chars(); + while let Some(c) = it.next_back() { + if c != '0' { + break; } + i -= 1; } - if i != post_dec.len() { - f_sci.post_decimal = Some(String::from(&post_dec[0..i])); - } } - None => {} + if i != post_dec.len() { + f_sci.post_decimal = Some(String::from(&post_dec[0..i])); + } } let f_fl = get_primitive_dec( inprefix, diff --git a/src/printf/tokenize/num_format/formatters/float_common.rs b/src/printf/tokenize/num_format/formatters/float_common.rs index 0b4a54b30b0..b5fc98d924b 100644 --- a/src/printf/tokenize/num_format/formatters/float_common.rs +++ b/src/printf/tokenize/num_format/formatters/float_common.rs @@ -27,12 +27,10 @@ fn has_enough_digits( } else { false //undecidable without converting } - } else { - if hex_input { + } else if hex_input { ((((string_position - 1) - starting_position) * 9) / 8 >= limit) - } else { + } else { ((string_position - 1) - starting_position >= limit) - } } } @@ -47,7 +45,7 @@ impl FloatAnalysis { // this fn assumes // the input string // has no leading spaces or 0s - let mut str_it = get_it_at(inprefix.offset, str_in); + let str_it = get_it_at(inprefix.offset, str_in); let mut ret = FloatAnalysis { len_important: 0, decimal_pos: None, @@ -62,12 +60,12 @@ impl FloatAnalysis { }; let mut i = 0; let mut pos_before_first_nonzero_after_decimal: Option = None; - while let Some(c) = str_it.next() { + for c in str_it { match c { - e @ '0'...'9' | e @ 'A'...'F' | e @ 'a'...'f' => { + e @ '0'..='9' | e @ 'A'..='F' | e @ 'a'..='f' => { if !hex_input { match e { - '0'...'9' => {} + '0'..='9' => {} _ => { warn_incomplete_conv(str_in); break; @@ -160,7 +158,7 @@ fn _round_str_from(in_str: &str, position: usize) -> (String, bool) { '9' => { rev.push('0'); } - e @ _ => { + e => { rev.push(((e as u8) + 1) as char); finished_in_dec = true; break; @@ -182,23 +180,20 @@ fn round_terminal_digit( if position < after_dec.len() { let digit_at_pos: char; { - digit_at_pos = (&after_dec[position..position + 1]) + digit_at_pos = (&after_dec[position..=position]) .chars() .next() .expect(""); } - match digit_at_pos { - '5'...'9' => { - let (new_after_dec, finished_in_dec) = _round_str_from(&after_dec, position); - if finished_in_dec { - return (before_dec, new_after_dec); - } else { - let (new_before_dec, _) = _round_str_from(&before_dec, before_dec.len()); - return (new_before_dec, new_after_dec); - } - // TODO + if let '5'..='9' = digit_at_pos { + let (new_after_dec, finished_in_dec) = _round_str_from(&after_dec, position); + if finished_in_dec { + return (before_dec, new_after_dec); + } else { + let (new_before_dec, _) = _round_str_from(&before_dec, before_dec.len()); + return (new_before_dec, new_after_dec); } - _ => {} + // TODO } } (before_dec, after_dec) @@ -225,7 +220,7 @@ pub fn get_primitive_dec( Some(pos) => (&str_in[..pos], &str_in[pos + 1..]), None => (&str_in[..], "0"), }; - if first_segment_raw.len() == 0 { + if first_segment_raw.is_empty() { first_segment_raw = "0"; } // convert to string, de_hexifying if input is in hex. @@ -251,16 +246,16 @@ pub fn get_primitive_dec( } else { match first_segment.chars().next() { Some('0') => { - let mut it = second_segment.chars().enumerate(); + let it = second_segment.chars().enumerate(); let mut m: isize = 0; let mut pre = String::from("0"); let mut post = String::from("0"); - while let Some((i, c)) = it.next() { + for (i, c) in it { match c { '0' => {} _ => { - m = ((i as isize) + 1) * -1; - pre = String::from(&second_segment[i..i + 1]); + m = -((i as isize) + 1); + pre = String::from(&second_segment[i..=i]); post = String::from(&second_segment[i + 1..]); break; } @@ -299,11 +294,8 @@ pub fn get_primitive_dec( pub fn primitive_to_str_common(prim: &FormatPrimitive, field: &FormatField) -> String { let mut final_str = String::new(); - match prim.prefix { - Some(ref prefix) => { - final_str.push_str(&prefix); - } - None => {} + if let Some(ref prefix) = prim.prefix { + final_str.push_str(&prefix); } match prim.pre_decimal { Some(ref pre_decimal) => { @@ -319,7 +311,7 @@ pub fn primitive_to_str_common(prim: &FormatPrimitive, field: &FormatField) -> S let decimal_places = field.second_field.unwrap_or(6); match prim.post_decimal { Some(ref post_decimal) => { - if post_decimal.len() > 0 && decimal_places > 0 { + if !post_decimal.is_empty() && decimal_places > 0 { final_str.push('.'); let len_avail = post_decimal.len() as u32; @@ -346,11 +338,8 @@ pub fn primitive_to_str_common(prim: &FormatPrimitive, field: &FormatField) -> S ); } } - match prim.suffix { - Some(ref suffix) => { - final_str.push_str(suffix); - } - None => {} + if let Some(ref suffix) = prim.suffix { + final_str.push_str(suffix); } final_str diff --git a/src/printf/tokenize/num_format/formatters/intf.rs b/src/printf/tokenize/num_format/formatters/intf.rs index 498df3fc2ed..35cd8711dd1 100644 --- a/src/printf/tokenize/num_format/formatters/intf.rs +++ b/src/printf/tokenize/num_format/formatters/intf.rs @@ -66,7 +66,7 @@ impl Intf { let c_opt = str_it.next(); if let Some(c) = c_opt { match c { - '0'...'9' | 'a'...'f' | 'A'...'F' => { + '0'..='9' | 'a'..='f' | 'A'..='F' => { if ret.len_digits == 0 && c == '0' { ret.is_zero = true; } else if ret.is_zero { @@ -76,7 +76,7 @@ impl Intf { if ret.len_digits == max_sd_in { if let Some(next_ch) = str_it.next() { match next_ch { - '0'...'9' => { + '0'..='9' => { ret.past_max = true; } _ => { @@ -216,13 +216,12 @@ impl Formatter for Intf { if convert_hints.check_past_max || decr_from_max || radix_mismatch { // radix of in and out is the same. let segment = String::from(&str_in[begin..end]); - let m = Intf::conv_from_segment( + Intf::conv_from_segment( &segment, inprefix.radix_in.clone(), *field.field_char, inprefix.sign, - ); - m + ) } else { // otherwise just do a straight string copy. let mut fmt_prim: FormatPrimitive = Default::default(); @@ -242,26 +241,20 @@ impl Formatter for Intf { } fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String { let mut finalstr: String = String::new(); - match prim.prefix { - Some(ref prefix) => { - finalstr.push_str(&prefix); - } - None => {} + if let Some(ref prefix) = prim.prefix { + finalstr.push_str(&prefix); } // integral second fields is zero-padded minimum-width // which gets handled before general minimum-width match prim.pre_decimal { Some(ref pre_decimal) => { - match field.second_field { - Some(min) => { - let mut i = min; - let len = pre_decimal.len() as u32; - while i > len { - finalstr.push('0'); - i -= 1; - } + if let Some(min) = field.second_field { + let mut i = min; + let len = pre_decimal.len() as u32; + while i > len { + finalstr.push('0'); + i -= 1; } - None => {} } finalstr.push_str(&pre_decimal); } diff --git a/src/printf/tokenize/num_format/num_format.rs b/src/printf/tokenize/num_format/num_format.rs index ba9c78d8518..b0a4a3f4b1f 100644 --- a/src/printf/tokenize/num_format/num_format.rs +++ b/src/printf/tokenize/num_format/num_format.rs @@ -11,7 +11,7 @@ use super::formatters::cninetyninehexfloatf::CninetyNineHexFloatf; use super::formatters::scif::Scif; use super::formatters::decf::Decf; -pub fn warn_expected_numeric(pf_arg: &String) { +pub fn warn_expected_numeric(pf_arg: &str) { // important: keep println here not print cli::err_msg(&format!("{}: expected a numeric value", pf_arg)); } @@ -21,15 +21,12 @@ pub fn warn_expected_numeric(pf_arg: &String) { fn warn_char_constant_ign(remaining_bytes: Vec) { match env::var("POSIXLY_CORRECT") { Ok(_) => {} - Err(e) => match e { - env::VarError::NotPresent => { - cli::err_msg(&format!( - "warning: {:?}: character(s) following character \ - constant have been ignored", - &*remaining_bytes - )); - } - _ => {} + Err(e) => if let env::VarError::NotPresent = e { + cli::err_msg(&format!( + "warning: {:?}: character(s) following character \ + constant have been ignored", + &*remaining_bytes + )); }, } } @@ -46,13 +43,13 @@ fn get_provided(str_in_opt: Option<&String>) -> Option { if let Some(qchar) = byte_it.next() { match qchar { C_S_QUOTE | C_D_QUOTE => { - return Some(match byte_it.next() { + Some(match byte_it.next() { Some(second_byte) => { let mut ignored: Vec = Vec::new(); - while let Some(cont) = byte_it.next() { + for cont in byte_it { ignored.push(cont); } - if ignored.len() > 0 { + if !ignored.is_empty() { warn_char_constant_ign(ignored); } second_byte as u8 @@ -63,11 +60,11 @@ fn get_provided(str_in_opt: Option<&String>) -> Option { warn_expected_numeric(&so_far); 0 as u8 } - }); + }) } // first byte is not quote _ => { - return None; + None } // no first byte } } else { @@ -83,26 +80,19 @@ fn get_provided(str_in_opt: Option<&String>) -> Option { // a base, // and an offset for index after all // initial spacing, sign, base prefix, and leading zeroes -fn get_inprefix(str_in: &String, field_type: &FieldType) -> InPrefix { +fn get_inprefix(str_in: &str, field_type: &FieldType) -> InPrefix { let mut str_it = str_in.chars(); let mut ret = InPrefix { radix_in: Base::Ten, sign: 1, offset: 0, }; - let mut topchar = str_it.next().clone(); + let mut topchar = str_it.next(); // skip spaces and ensure topchar is the first non-space char // (or None if none exists) - loop { - match topchar { - Some(' ') => { - ret.offset += 1; - topchar = str_it.next(); - } - _ => { - break; - } - } + while let Some(' ') = topchar { + ret.offset += 1; + topchar = str_it.next(); } // parse sign match topchar { @@ -143,13 +133,10 @@ fn get_inprefix(str_in: &String, field_type: &FieldType) -> InPrefix { ret.radix_in = Base::Hex; do_clean_lead_zeroes = true; } - e @ '0'...'9' => { + e @ '0'..='9' => { ret.offset += 1; - match *field_type { - FieldType::Intf => { - ret.radix_in = Base::Octal; - } - _ => {} + if let FieldType::Intf = *field_type { + ret.radix_in = Base::Octal; } if e == '0' { do_clean_lead_zeroes = true; @@ -159,7 +146,7 @@ fn get_inprefix(str_in: &String, field_type: &FieldType) -> InPrefix { } if do_clean_lead_zeroes { let mut first = true; - while let Some(ch_zero) = str_it.next() { + for ch_zero in str_it { // see notes on offset above: // this is why the offset for octals and decimals // that reach this branch is 1 even though @@ -203,7 +190,7 @@ fn get_inprefix(str_in: &String, field_type: &FieldType) -> InPrefix { // if it is a numeric field, passing the field details // and an iterator to the argument pub fn num_format(field: &FormatField, in_str_opt: Option<&String>) -> Option { - let fchar = field.field_char.clone(); + let fchar = field.field_char; // num format mainly operates by further delegating to one of // several Formatter structs depending on the field diff --git a/src/printf/tokenize/sub.rs b/src/printf/tokenize/sub.rs index cc0b1d3f23a..3e538c5180f 100644 --- a/src/printf/tokenize/sub.rs +++ b/src/printf/tokenize/sub.rs @@ -15,12 +15,12 @@ use super::num_format::format_field::{FieldType, FormatField}; use super::num_format::num_format; // use std::collections::HashSet; -fn err_conv(sofar: &String) { +fn err_conv(sofar: &str) { cli::err_msg(&format!("%{}: invalid conversion specification", sofar)); exit(cli::EXIT_ERR); } -fn convert_asterisk_arg_int(asterisk_arg: &String) -> isize { +fn convert_asterisk_arg_int(asterisk_arg: &str) -> isize { // this is a costly way to parse the // args used for asterisk values into integers // from various bases. Actually doing it correctly @@ -32,11 +32,11 @@ fn convert_asterisk_arg_int(asterisk_arg: &String) -> isize { let field_info = FormatField { min_width: Some(0), second_field: Some(0), - orig: asterisk_arg, + orig: &asterisk_arg.to_string(), field_type: &field_type, field_char: &field_char, }; - num_format::num_format(&field_info, Some(asterisk_arg)) + num_format::num_format(&field_info, Some(&asterisk_arg.to_string())) .unwrap() .parse::() .unwrap() @@ -80,11 +80,11 @@ impl Sub { } }; Sub { - min_width: min_width, - second_field: second_field, - field_char: field_char, - field_type: field_type, - orig: orig, + min_width, + second_field, + field_char, + field_type, + orig, } } } @@ -177,10 +177,10 @@ impl SubParser { // divide substitution from %([0-9]+)?(.[0-9+])?([a-zA-Z]) // into min_width, second_field, field_char - while let Some(ch) = it.next() { + for ch in it { self.text_so_far.push(ch); match ch as char { - '-' | '*' | '0'...'9' => { + '-' | '*' | '0'..='9' => { if !self.past_decimal { if self.min_width_is_asterisk || self.specifiers_found { err_conv(&self.text_so_far); @@ -190,7 +190,7 @@ impl SubParser { } match self.min_width_tmp.as_mut() { Some(x) => { - if (ch == '-' || ch == '*') && x.len() > 0 { + if (ch == '-' || ch == '*') && !x.is_empty() { err_conv(&self.text_so_far); } if ch == '*' { @@ -213,7 +213,7 @@ impl SubParser { } match self.second_field_tmp.as_mut() { Some(x) => { - if ch == '*' && x.len() > 0 { + if ch == '*' && !x.is_empty() { err_conv(&self.text_so_far); } if ch == '*' { @@ -252,7 +252,7 @@ impl SubParser { } } } - if !self.field_char.is_some() { + if self.field_char.is_none() { err_conv(&self.text_so_far); } let field_char_retrieved = self.field_char.unwrap(); @@ -262,13 +262,10 @@ impl SubParser { self.validate_field_params(field_char_retrieved); // if the dot is provided without a second field // printf interprets it as 0. - match self.second_field_tmp.as_mut() { - Some(x) => { - if x.len() == 0 { - self.min_width_tmp = Some(String::from("0")); - } + if let Some(x) = self.second_field_tmp.as_mut() { + if x.is_empty() { + self.min_width_tmp = Some(String::from("0")); } - _ => {} } true @@ -292,8 +289,8 @@ impl SubParser { } } } else { - n_ch.map(|x| it.put_back(x)); - preface.map(|x| it.put_back(x)); + if let Some(x) = n_ch { it.put_back(x) }; + if let Some(x) = preface { it.put_back(x) }; false } } @@ -390,39 +387,36 @@ impl token::Token for Sub { num_format::num_format(&field, pf_arg) } }; - match pre_min_width_opt { + if let Some(pre_min_width) = pre_min_width_opt { // if have a string, print it, ensuring minimum width is met. - Some(pre_min_width) => { - print!( - "{}", - match field.min_width { - Some(min_width) => { - let diff: isize = - min_width.abs() as isize - pre_min_width.len() as isize; - if diff > 0 { - let mut final_str = String::new(); - // definitely more efficient ways - // to do this. - let pad_before = min_width > 0; - if !pad_before { - final_str.push_str(&pre_min_width); - } - for _ in 0..diff { - final_str.push(' '); - } - if pad_before { - final_str.push_str(&pre_min_width); - } - final_str - } else { - pre_min_width + print!( + "{}", + match field.min_width { + Some(min_width) => { + let diff: isize = + min_width.abs() as isize - pre_min_width.len() as isize; + if diff > 0 { + let mut final_str = String::new(); + // definitely more efficient ways + // to do this. + let pad_before = min_width > 0; + if !pad_before { + final_str.push_str(&pre_min_width); } + for _ in 0..diff { + final_str.push(' '); + } + if pad_before { + final_str.push_str(&pre_min_width); + } + final_str + } else { + pre_min_width } - None => pre_min_width, } - ); - } - None => {} + None => pre_min_width, + } + ); } } } diff --git a/src/printf/tokenize/token.rs b/src/printf/tokenize/token.rs index 78009dd91de..2e0cdd81283 100644 --- a/src/printf/tokenize/token.rs +++ b/src/printf/tokenize/token.rs @@ -1,6 +1,5 @@ //! Traits and enums dealing with Tokenization of printf Format String use itertools::PutBackN; -#[allow(unused_must_use)] use std::iter::Peekable; use std::slice::Iter; use std::str::Chars; diff --git a/src/printf/tokenize/unescaped_text.rs b/src/printf/tokenize/unescaped_text.rs index 2ccbf56fcad..c2b6eca9e60 100644 --- a/src/printf/tokenize/unescaped_text.rs +++ b/src/printf/tokenize/unescaped_text.rs @@ -60,11 +60,10 @@ impl UnescapedText { // dropped-in as a replacement. fn validate_iec(val: u32, eight_word: bool) { let mut preface = 'u'; - let mut leading_zeros = 4; - if eight_word { + let leading_zeros = if eight_word { preface = 'U'; - leading_zeros = 8; - } + 8 + } else { 4 }; let err_msg = format!( "invalid universal character name {0}{1:02$x}", preface, val, leading_zeros @@ -85,14 +84,14 @@ impl UnescapedText { None => '\\', }; match ch { - '0'...'9' | 'x' => { + '0'..='9' | 'x' => { let min_len = 1; let mut max_len = 2; let mut base = 16; let ignore = false; match ch { 'x' => {} - e @ '0'...'9' => { + e @ '0'..='9' => { max_len = 3; base = 8; // in practice, gnu coreutils printf @@ -120,7 +119,7 @@ impl UnescapedText { byte_vec.push(ch as u8); } } - e @ _ => { + e => { // only for hex and octal // is byte encoding specified. // otherwise, why not leave the door open @@ -191,7 +190,7 @@ impl UnescapedText { // lazy branch eval // remember this fn could be called // many times in a single exec through %b - cli::flush_char(&ch); + cli::flush_char(ch); tmp_str.push(ch); } '\\' => { @@ -202,7 +201,7 @@ impl UnescapedText { // on non hex or octal escapes is costly // then we can make it faster/more complex // with as-necessary draining. - if tmp_str.len() > 0 { + if !tmp_str.is_empty() { new_vec.extend(tmp_str.bytes()); tmp_str = String::new(); } @@ -211,7 +210,7 @@ impl UnescapedText { x if x == '%' && !subs_mode => { if let Some(follow) = it.next() { if follow == '%' { - cli::flush_char(&ch); + cli::flush_char(ch); tmp_str.push(ch); } else { it.put_back(follow); @@ -224,18 +223,19 @@ impl UnescapedText { } } _ => { - cli::flush_char(&ch); + cli::flush_char(ch); tmp_str.push(ch); } } } - if tmp_str.len() > 0 { + if !tmp_str.is_empty() { new_vec.extend(tmp_str.bytes()); } } - match addchar { - true => Some(Box::new(new_text)), - false => None, + if addchar { + Some(Box::new(new_text)) + } else { + None } } } diff --git a/src/ptx/ptx.rs b/src/ptx/ptx.rs index 8573b65ab7f..9e7573c253f 100644 --- a/src/ptx/ptx.rs +++ b/src/ptx/ptx.rs @@ -189,14 +189,12 @@ fn read_input(input_files: &[String], config: &Config) -> HashMap String { Some(x) => (x.start(), x.end()), None => (0, 0), }; - format!("{}", &line[beg..end]) + line[beg..end].to_string() } else { String::new() } diff --git a/src/pwd/pwd.rs b/src/pwd/pwd.rs index e4658989dc4..c43fcf3869f 100644 --- a/src/pwd/pwd.rs +++ b/src/pwd/pwd.rs @@ -29,7 +29,7 @@ pub fn absolute_path(path: &Path) -> io::Result { path_buf .as_path() .to_string_lossy() - .trim_left_matches(r"\\?\"), + .trim_start_matches(r"\\?\"), ).to_path_buf(); Ok(path_buf) diff --git a/src/readlink/readlink.rs b/src/readlink/readlink.rs index b4971e27fe0..170fff6d3b2 100644 --- a/src/readlink/readlink.rs +++ b/src/readlink/readlink.rs @@ -70,18 +70,13 @@ pub fn uumain(args: Vec) -> i32 { let silent = matches.opt_present("silent") || matches.opt_present("quiet"); let verbose = matches.opt_present("verbose"); - let mut can_mode = CanonicalizeMode::None; - if matches.opt_present("canonicalize") { - can_mode = CanonicalizeMode::Normal; - } - - if matches.opt_present("canonicalize-existing") { - can_mode = CanonicalizeMode::Existing; - } - - if matches.opt_present("canonicalize-missing") { - can_mode = CanonicalizeMode::Missing; - } + let can_mode = if matches.opt_present("canonicalize") { + CanonicalizeMode::Normal + } else if matches.opt_present("canonicalize-existing") { + CanonicalizeMode::Existing + } else if matches.opt_present("canonicalize-missing") { + CanonicalizeMode::Missing + } else { CanonicalizeMode::None }; let files = matches.free; if files.is_empty() { @@ -139,7 +134,7 @@ fn show(path: &PathBuf, no_newline: bool, use_zero: bool) { fn show_usage(opts: &getopts::Options) { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage: {0} [OPTION]... [FILE]...", NAME); print!("Print value of a symbolic link or canonical file name"); print!("{}", opts.usage("")); diff --git a/src/realpath/realpath.rs b/src/realpath/realpath.rs index 80e6052daef..5238040221b 100644 --- a/src/realpath/realpath.rs +++ b/src/realpath/realpath.rs @@ -136,12 +136,12 @@ fn version() { fn show_usage(opts: &getopts::Options) { version(); - println!(""); + println!(); println!("Usage:"); println!(" {} [-s|--strip] [-z|--zero] FILENAME...", NAME); println!(" {} -V|--version", NAME); println!(" {} -h|--help", NAME); - println!(""); + println!(); print!("{}", opts.usage( "Convert each FILENAME to the absolute path.\n\ All the symbolic links will be resolved, resulting path will contain no special components like '.' or '..'.\n\ diff --git a/src/relpath/relpath.rs b/src/relpath/relpath.rs index 8e0bb401217..b2ed8c251bd 100644 --- a/src/relpath/relpath.rs +++ b/src/relpath/relpath.rs @@ -108,12 +108,12 @@ fn version() { fn show_usage(opts: &getopts::Options) { version(); - println!(""); + println!(); println!("Usage:"); println!(" {} [-d DIR] TO [FROM]", NAME); println!(" {} -V|--version", NAME); println!(" {} -h|--help", NAME); - println!(""); + println!(); print!( "{}", opts.usage( diff --git a/src/rm/rm.rs b/src/rm/rm.rs index 8c2fc08ba18..34b9adb98b2 100644 --- a/src/rm/rm.rs +++ b/src/rm/rm.rs @@ -26,9 +26,9 @@ use walkdir::{DirEntry, WalkDir}; #[derive(Eq, PartialEq, Clone, Copy)] enum InteractiveMode { - InteractiveNone, - InteractiveOnce, - InteractiveAlways, + None, + Once, + Always, } struct Options { @@ -84,20 +84,20 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); + println!(); println!("{}", opts.usage("Remove (unlink) the FILE(s).")); println!("By default, rm does not remove directories. Use the --recursive (-r)"); println!("option to remove each listed directory, too, along with all of its contents"); - println!(""); + println!(); println!("To remove a file whose name starts with a '-', for example '-foo',"); println!("use one of these commands:"); println!("rm -- -foo"); - println!(""); + println!(); println!("rm ./-foo"); - println!(""); + println!(); println!("Note that if you use rm to remove a file, it might be possible to recover"); println!("some of its contents, given sufficient expertise and/or time. For greater"); println!("assurance that the contents are truly unrecoverable, consider using shred."); @@ -109,21 +109,21 @@ pub fn uumain(args: Vec) -> i32 { return 1; } else { let options = Options { - force: force, + force, interactive: { if matches.opt_present("i") { - InteractiveMode::InteractiveAlways + InteractiveMode::Always } else if matches.opt_present("I") { - InteractiveMode::InteractiveOnce + InteractiveMode::Once } else if matches.opt_present("interactive") { match &matches.opt_str("interactive").unwrap()[..] { - "none" => InteractiveMode::InteractiveNone, - "once" => InteractiveMode::InteractiveOnce, - "always" => InteractiveMode::InteractiveAlways, + "none" => InteractiveMode::None, + "once" => InteractiveMode::Once, + "always" => InteractiveMode::Always, val => crash!(1, "Invalid argument to interactive ({})", val), } } else { - InteractiveMode::InteractiveNone + InteractiveMode::None } }, one_fs: matches.opt_present("one-file-system"), @@ -132,7 +132,7 @@ pub fn uumain(args: Vec) -> i32 { dir: matches.opt_present("dir"), verbose: matches.opt_present("verbose"), }; - if options.interactive == InteractiveMode::InteractiveOnce + if options.interactive == InteractiveMode::Once && (options.recursive || matches.free.len() > 3) { let msg = if options.recursive { @@ -192,7 +192,7 @@ fn handle_dir(path: &Path, options: &Options) -> bool { let is_root = path.has_root() && path.parent().is_none(); if options.recursive && (!is_root || !options.preserve_root) { - if options.interactive != InteractiveMode::InteractiveAlways { + if options.interactive != InteractiveMode::Always { // we need the extra crate because apparently fs::remove_dir_all() does not function // correctly on Windows if let Err(e) = remove_dir_all(path) { @@ -225,24 +225,22 @@ fn handle_dir(path: &Path, options: &Options) -> bool { } } else if options.dir && (!is_root || !options.preserve_root) { had_err = remove_dir(path, options).bitor(had_err); + } else if options.recursive { + show_error!("could not remove directory '{}'", path.display()); + had_err = true; } else { - if options.recursive { - show_error!("could not remove directory '{}'", path.display()); - had_err = true; - } else { - show_error!( - "could not remove directory '{}' (did you mean to pass '-r'?)", - path.display() - ); - had_err = true; - } + show_error!( + "could not remove directory '{}' (did you mean to pass '-r'?)", + path.display() + ); + had_err = true; } had_err } fn remove_dir(path: &Path, options: &Options) -> bool { - let response = if options.interactive == InteractiveMode::InteractiveAlways { + let response = if options.interactive == InteractiveMode::Always { prompt_file(path, true) } else { true @@ -263,7 +261,7 @@ fn remove_dir(path: &Path, options: &Options) -> bool { } fn remove_file(path: &Path, options: &Options) -> bool { - let response = if options.interactive == InteractiveMode::InteractiveAlways { + let response = if options.interactive == InteractiveMode::Always { prompt_file(path, false) } else { true @@ -299,7 +297,7 @@ fn prompt(msg: &str) -> bool { let stdin = stdin(); let mut stdin = stdin.lock(); - match stdin.read_until('\n' as u8, &mut buf) { + match stdin.read_until(b'\n', &mut buf) { Ok(x) if x > 0 => match buf[0] { b'y' | b'Y' => true, _ => false, diff --git a/src/seq/seq.rs b/src/seq/seq.rs index 4bdbbf370a3..18295583dea 100644 --- a/src/seq/seq.rs +++ b/src/seq/seq.rs @@ -22,7 +22,7 @@ struct SeqOptions { } fn parse_float(mut s: &str) -> Result { - if s.starts_with("+") { + if s.starts_with('+') { s = &s[1..]; } match s.parse() { @@ -41,106 +41,103 @@ fn escape_sequences(s: &str) -> String { fn parse_options(args: Vec, options: &mut SeqOptions) -> Result, i32> { let mut seq_args = vec![]; let mut iter = args.into_iter().skip(1); - loop { - match iter.next() { - Some(arg) => match &arg[..] { - "--help" | "-h" => { - print_help(); - return Err(0); - } - "--version" | "-V" => { - print_version(); - return Err(0); + while let Some(arg) = iter.next() { + match &arg[..] { + "--help" | "-h" => { + print_help(); + return Err(0); + } + "--version" | "-V" => { + print_version(); + return Err(0); + } + "-s" | "--separator" => match iter.next() { + Some(sep) => options.separator = sep, + None => { + show_error!("expected a separator after {}", arg); + return Err(1); } - "-s" | "--separator" => match iter.next() { - Some(sep) => options.separator = sep, - None => { - show_error!("expected a separator after {}", arg); - return Err(1); - } - }, - "-t" | "--terminator" => match iter.next() { - Some(term) => options.terminator = Some(term), - None => { - show_error!("expected a terminator after '{}'", arg); - return Err(1); - } - }, - "-w" | "--widths" => options.widths = true, - "--" => { - seq_args.extend(iter); - break; + }, + "-t" | "--terminator" => match iter.next() { + Some(term) => options.terminator = Some(term), + None => { + show_error!("expected a terminator after '{}'", arg); + return Err(1); } - _ => { - if arg.len() > 1 && arg.chars().next().unwrap() == '-' { - let argptr: *const String = &arg; // escape from the borrow checker - let mut chiter = unsafe { &(*argptr)[..] }.chars().skip(1); - let mut ch = ' '; - while match chiter.next() { - Some(m) => { - ch = m; - true + }, + "-w" | "--widths" => options.widths = true, + "--" => { + seq_args.extend(iter); + break; + } + _ => { + if arg.len() > 1 && arg.starts_with('-') { + let argptr: *const String = &arg; // escape from the borrow checker + let mut chiter = unsafe { &(*argptr)[..] }.chars().skip(1); + let mut ch = ' '; + while match chiter.next() { + Some(m) => { + ch = m; + true + } + None => false, + } { + match ch { + 'h' => { + print_help(); + return Err(0); } - None => false, - } { - match ch { - 'h' => { - print_help(); - return Err(0); - } - 'V' => { - print_version(); - return Err(0); - } - 's' => match iter.next() { - Some(sep) => { - options.separator = sep; - let next = chiter.next(); - if next.is_some() { - show_error!( - "unexpected character ('{}')", - next.unwrap() - ); - return Err(1); - } - } - None => { - show_error!("expected a separator after {}", arg); + 'V' => { + print_version(); + return Err(0); + } + 's' => match iter.next() { + Some(sep) => { + options.separator = sep; + let next = chiter.next(); + if let Some(n) = next { + show_error!( + "unexpected character ('{}')", + n + ); return Err(1); } - }, - 't' => match iter.next() { - Some(term) => { - options.terminator = Some(term); - let next = chiter.next(); - if next.is_some() { - show_error!( - "unexpected character ('{}')", - next.unwrap() - ); - return Err(1); - } - } - None => { - show_error!("expected a terminator after {}", arg); + } + None => { + show_error!("expected a separator after {}", arg); + return Err(1); + } + }, + 't' => match iter.next() { + Some(term) => { + options.terminator = Some(term); + let next = chiter.next(); + if let Some(n) = next { + show_error!( + "unexpected character ('{}')", + n + ); return Err(1); } - }, - 'w' => options.widths = true, - _ => { - seq_args.push(arg); - break; } + None => { + show_error!("expected a terminator after {}", arg); + return Err(1); + } + }, + 'w' => options.widths = true, + _ => { + seq_args.push(arg); + break; } } - } else { - seq_args.push(arg); } + } else { + seq_args.push(arg); } - }, - None => break, - } - } + } + }; + }; Ok(seq_args) } @@ -189,11 +186,11 @@ pub fn uumain(args: Vec) -> i32 { Ok(m) => m, Err(f) => return f, }; - if free.len() < 1 || free.len() > 3 { + if free.is_empty() || free.len() > 3 { crash!( 1, "too {} operands.\nTry '{} --help' for more information.", - if free.len() < 1 { "few" } else { "many" }, + if free.is_empty() { "few" } else { "many" }, NAME ); } @@ -233,7 +230,7 @@ pub fn uumain(args: Vec) -> i32 { }; let last = { let slice = &free[free.len() - 1][..]; - padding = cmp::max(padding, slice.find('.').unwrap_or(slice.len())); + padding = cmp::max(padding, slice.find('.').unwrap_or_else(|| slice.len())); match parse_float(slice) { Ok(n) => n, Err(s) => { @@ -272,6 +269,7 @@ fn done_printing(next: f64, step: f64, last: f64) -> bool { } } +#[allow(clippy::too_many_arguments)] fn print_seq( first: f64, step: f64, diff --git a/src/shred/shred.rs b/src/shred/shred.rs index 65005b91606..e38b0d3df22 100644 --- a/src/shred/shred.rs +++ b/src/shred/shred.rs @@ -31,7 +31,7 @@ const BLOCK_SIZE: usize = 512; const NAMESET: &str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_."; // Patterns as shown in the GNU coreutils shred implementation -const PATTERNS: [&'static [u8]; 22] = [ +const PATTERNS: [&[u8]; 22] = [ b"\x00", b"\xFF", b"\x55", @@ -76,7 +76,7 @@ impl FilenameGenerator { indices.push(0); } FilenameGenerator { - name_len: name_len, + name_len, nameset_indices: RefCell::new(indices), exhausted: Cell::new(false), } @@ -137,12 +137,12 @@ impl<'a> BytesGenerator<'a> { }; BytesGenerator { - total_bytes: total_bytes, + total_bytes, bytes_generated: Cell::new(0u64), block_size: BLOCK_SIZE, - exact: exact, - gen_type: gen_type, - rng: rng, + exact, + gen_type, + rng, } } } @@ -290,7 +290,7 @@ fn show_help(opts: &getopts::Options) { println!("Delete FILE(s) if --remove (-u) is specified. The default is not to remove"); println!("the files because it is common to operate on device files like /dev/hda,"); println!("and those files usually should not be removed."); - println!(""); + println!(); println!( "CAUTION: Note that {} relies on a very important assumption:", NAME @@ -302,20 +302,20 @@ fn show_help(opts: &getopts::Options) { NAME ); println!("not effective, or is not guaranteed to be effective in all file system modes:"); - println!(""); + println!(); println!("* log-structured or journaled file systems, such as those supplied with"); println!("AIX and Solaris (and JFS, ReiserFS, XFS, Ext3, etc.)"); - println!(""); + println!(); println!("* file systems that write redundant data and carry on even if some writes"); println!("fail, such as RAID-based file systems"); - println!(""); + println!(); println!("* file systems that make snapshots, such as Network Appliance's NFS server"); - println!(""); + println!(); println!("* file systems that cache in temporary locations, such as NFS"); println!("version 3 clients"); - println!(""); + println!(); println!("* compressed file systems"); - println!(""); + println!(); println!("In the case of ext3 file systems, the above disclaimer applies"); println!( "(and {} is thus of limited effectiveness) only in data=journal mode,", @@ -329,7 +329,7 @@ fn show_help(opts: &getopts::Options) { println!("Ext3 journaling modes can be changed by adding the data=something option"); println!("to the mount options for a particular file system in the /etc/fstab file,"); println!("as documented in the mount man page (man mount)."); - println!(""); + println!(); println!("In addition, file system backups and remote mirrors may contain copies"); println!("of the file that cannot be removed, and that will allow a shredded file"); println!("to be recovered later."); @@ -338,9 +338,7 @@ fn show_help(opts: &getopts::Options) { // TODO: Add support for all postfixes here up to and including EiB // http://www.gnu.org/software/coreutils/manual/coreutils.html#Block-size fn get_size(size_str_opt: Option) -> Option { - if size_str_opt.is_none() { - return None; - } + size_str_opt.as_ref()?; let mut size_str = size_str_opt.as_ref().unwrap().clone(); // Immutably look at last character of size string @@ -371,8 +369,8 @@ fn get_size(size_str_opt: Option) -> Option { Some(coeff * unit) } -fn pass_name(pass_type: &PassType) -> String { - match *pass_type { +fn pass_name(pass_type: PassType) -> String { + match pass_type { PassType::Random => String::from("random"), PassType::Pattern(bytes) => { let mut s: String = String::new(); @@ -426,8 +424,8 @@ fn wipe_file( pass_sequence.push(PassType::Pattern(*p)); } } - for i in 0..remainder { - pass_sequence.push(PassType::Pattern(PATTERNS[i])); + for pattern in PATTERNS.iter().take(remainder) { + pass_sequence.push(PassType::Pattern(pattern)); } rand::thread_rng().shuffle(&mut pass_sequence[..]); // randomize the order of application @@ -453,7 +451,7 @@ fn wipe_file( for (i, pass_type) in pass_sequence.iter().enumerate() { if verbose { - let pass_name: String = pass_name(pass_type); + let pass_name: String = pass_name(*pass_type); if total_passes.to_string().len() == 1 { println!( "{}: {}: pass {}/{} ({})... ", @@ -520,7 +518,7 @@ fn wipe_name(orig_path: &Path, verbose: bool) -> Option { let mut last_path: PathBuf = PathBuf::from(orig_path); - for length in (1..file_name_len + 1).rev() { + for length in (1..=file_name_len).rev() { for name in FilenameGenerator::new(length) { let new_path: PathBuf = orig_path.with_file_name(name); // We don't want the filename to already exist (don't overwrite) @@ -572,11 +570,8 @@ fn do_remove(path: &Path, orig_filename: &str, verbose: bool) -> Result<(), io:: } let renamed_path: Option = wipe_name(&path, verbose); - match renamed_path { - Some(rp) => { - fs::remove_file(rp)?; - } - None => (), + if let Some(rp) = renamed_path { + fs::remove_file(rp)?; } if verbose { diff --git a/src/shuf/shuf.rs b/src/shuf/shuf.rs index ee0d1c91c7b..571813005f7 100644 --- a/src/shuf/shuf.rs +++ b/src/shuf/shuf.rs @@ -123,14 +123,14 @@ With no FILE, or when FILE is -, read standard input.", let mut evec = matches .free .iter() - .map(|a| a.as_bytes()) + .map(std::string::String::as_bytes) .collect::>(); find_seps(&mut evec, sep); shuf_bytes(&mut evec, repeat, count, sep, output, random); } Mode::InputRange((b, e)) => { let rvec = (b..e).map(|x| format!("{}", x)).collect::>(); - let mut rvec = rvec.iter().map(|a| a.as_bytes()).collect::>(); + let mut rvec = rvec.iter().map(std::string::String::as_bytes).collect::>(); shuf_bytes(&mut rvec, repeat, count, sep, output, random); } Mode::Default => { @@ -156,9 +156,8 @@ fn read_input_file(filename: &str) -> Vec { }); let mut data = Vec::new(); - match file.read_to_end(&mut data) { - Err(e) => crash!(1, "failed reading '{}': {}", filename, e), - Ok(_) => (), + if let Err(e) = file.read_to_end(&mut data) { + crash!(1, "failed reading '{}': {}", filename, e) }; data @@ -228,7 +227,6 @@ fn shuf_bytes( len >>= 1; len_mod <<= 1; } - drop(len); let mut count = count; while count > 0 && !input.is_empty() { diff --git a/src/sort/sort.rs b/src/sort/sort.rs index 81ea58a26f4..2259bea0cb2 100644 --- a/src/sort/sort.rs +++ b/src/sort/sort.rs @@ -49,7 +49,7 @@ struct Settings { unique: bool, check: bool, ignore_case: bool, - compare_fns: Vec Ordering>, + compare_fns: Vec Ordering>, } impl Default for Settings { @@ -106,20 +106,17 @@ impl<'a> FileMerger<'a> { fn new(settings: &'a Settings) -> FileMerger<'a> { FileMerger { heap: BinaryHeap::new(), - settings: settings, + settings, } } fn push_file(&mut self, mut lines: Lines>>) { - match lines.next() { - Some(Ok(next_line)) => { - let mergeable_file = MergeableFile { - lines: lines, - current_line: next_line, - settings: &self.settings, - }; - self.heap.push(mergeable_file); - } - _ => {} + if let Some(Ok(next_line)) = lines.next() { + let mergeable_file = MergeableFile { + lines, + current_line: next_line, + settings: &self.settings, + }; + self.heap.push(mergeable_file); } } } @@ -254,13 +251,13 @@ With no FILE, or when FILE is -, read standard input.", SortMode::HumanNumeric => human_numeric_size_compare, SortMode::Month => month_compare, SortMode::Version => version_compare, - SortMode::Default => String::cmp, + SortMode::Default => default_compare, }); if !settings.stable { match settings.mode { SortMode::Default => {} - _ => settings.compare_fns.push(String::cmp), + _ => settings.compare_fns.push(default_compare), } } @@ -302,12 +299,10 @@ fn exec(files: Vec, settings: &Settings) -> i32 { } else { print_sorted(file_merger, &settings.outfile) } + } else if settings.unique { + print_sorted(lines.iter().dedup(), &settings.outfile) } else { - if settings.unique { - print_sorted(lines.iter().dedup(), &settings.outfile) - } else { - print_sorted(lines.iter(), &settings.outfile) - } + print_sorted(lines.iter(), &settings.outfile) } 0 @@ -337,14 +332,14 @@ fn exec_check_file(lines: Lines>>, settings: &Settings) // line, no matter what our merging function does. if let Some(_last_line_or_next_error) = errors.next() { println!("sort: disorder in line {}", first_error_index); - return 1; + 1 } else { // first "error" was actually the last line. - return 0; + 0 } } else { // unwrapped_lines was empty. Empty files are defined to be sorted. - return 0; + 0 } } @@ -352,13 +347,13 @@ fn sort_by(lines: &mut Vec, settings: &Settings) { lines.sort_by(|a, b| compare_by(a, b, &settings)) } -fn compare_by(a: &String, b: &String, settings: &Settings) -> Ordering { +fn compare_by(a: &str, b: &str, settings: &Settings) -> Ordering { // Convert to uppercase if necessary let (a_upper, b_upper): (String, String); let (a, b) = if settings.ignore_case { a_upper = a.to_uppercase(); b_upper = b.to_uppercase(); - (&a_upper, &b_upper) + (&*a_upper, &*b_upper) } else { (a, b) }; @@ -373,7 +368,7 @@ fn compare_by(a: &String, b: &String, settings: &Settings) -> Ordering { } } } - return Ordering::Equal; + Ordering::Equal } /// Parse the beginning string into an f64, returning -inf instead of NaN on errors. @@ -395,10 +390,15 @@ fn permissive_f64_parse(a: &str) -> f64 { } } +fn default_compare(a: &str, b: &str) -> Ordering { + a.cmp(b) +} + /// Compares two floating point numbers, with errors being assumed to be -inf. /// Stops coercing at the first whitespace char, so 1e2 will parse as 100 but /// 1,000 will parse as -inf. -fn numeric_compare(a: &String, b: &String) -> Ordering { +fn numeric_compare(a: &str, b: &str) -> Ordering { + #![allow(clippy::comparison_chain)] let fa = permissive_f64_parse(a); let fb = permissive_f64_parse(b); // f64::cmp isn't implemented because NaN messes with it @@ -412,7 +412,7 @@ fn numeric_compare(a: &String, b: &String) -> Ordering { } } -fn human_numeric_convert(a: &String) -> f64 { +fn human_numeric_convert(a: &str) -> f64 { let int_iter = a.chars(); let suffix_iter = a.chars(); let int_str: String = int_iter.take_while(|c| c.is_numeric()).collect(); @@ -434,9 +434,11 @@ fn human_numeric_convert(a: &String) -> f64 { /// Compare two strings as if they are human readable sizes. /// AKA 1M > 100k -fn human_numeric_size_compare(a: &String, b: &String) -> Ordering { +fn human_numeric_size_compare(a: &str, b: &str) -> Ordering { + #![allow(clippy::comparison_chain)] let fa = human_numeric_convert(a); let fb = human_numeric_convert(b); + // f64::cmp isn't implemented (due to NaN issues); implement directly instead if fa > fb { Ordering::Greater } else if fa < fb { @@ -464,7 +466,7 @@ enum Month { } /// Parse the beginning string into a Month, returning Month::Unknown on errors. -fn month_parse(line: &String) -> Month { +fn month_parse(line: &str) -> Month { match line.split_whitespace() .next() .unwrap() @@ -487,13 +489,15 @@ fn month_parse(line: &String) -> Month { } } -fn month_compare(a: &String, b: &String) -> Ordering { +fn month_compare(a: &str, b: &str) -> Ordering { month_parse(a).cmp(&month_parse(b)) } -fn version_compare(a: &String, b: &String) -> Ordering { +fn version_compare(a: &str, b: &str) -> Ordering { + #![allow(clippy::comparison_chain)] let ver_a = Version::parse(a); let ver_b = Version::parse(b); + // Version::cmp is not implemented; implement comparison directly if ver_a > ver_b { Ordering::Greater } else if ver_a < ver_b { @@ -520,12 +524,9 @@ where for line in iter { let str = format!("{}\n", line); - match file.write_all(str.as_bytes()) { - Err(e) => { - show_error!("sort: {0}", e.to_string()); - panic!("Write failed"); - } - Ok(_) => (), + if let Err(e) = file.write_all(str.as_bytes()) { + show_error!("sort: {0}", e.to_string()); + panic!("Write failed"); } } } diff --git a/src/split/split.rs b/src/split/split.rs index 8104f8a0814..d867c773b30 100644 --- a/src/split/split.rs +++ b/src/split/split.rs @@ -108,16 +108,13 @@ size is 1000, and default PREFIX is 'x'. With no INPUT, or when INPUT is settings.strategy_param = "1000".to_owned(); let strategies = vec!["b", "C", "l"]; for e in &strategies { - match matches.opt_str(*e) { - Some(a) => { - if settings.strategy == "l" { - settings.strategy = (*e).to_owned(); - settings.strategy_param = a; - } else { - crash!(1, "{}: cannot split in more than one way", NAME) - } + if let Some(a) = matches.opt_str(*e) { + if settings.strategy == "l" { + settings.strategy = (*e).to_owned(); + settings.strategy_param = a; + } else { + crash!(1, "{}: cannot split in more than one way", NAME) } - None => {} } } @@ -159,15 +156,15 @@ struct LineSplitter { } impl LineSplitter { - fn new(settings: &Settings) -> Box { + fn new(settings: &Settings) -> LineSplitter { let n = match settings.strategy_param.parse() { Ok(a) => a, Err(e) => crash!(1, "invalid number of lines: {}", e), }; - Box::new(LineSplitter { + LineSplitter { saved_lines_to_write: n, lines_to_write: n, - }) as Box + } } } @@ -190,11 +187,11 @@ struct ByteSplitter { } impl ByteSplitter { - fn new(settings: &Settings) -> Box { + fn new(settings: &Settings) -> ByteSplitter { let mut strategy_param: Vec = settings.strategy_param.chars().collect(); let suffix = strategy_param.pop().unwrap(); let multiplier = match suffix { - '0'...'9' => 1usize, + '0'..='9' => 1usize, 'b' => 512usize, 'k' => 1024usize, 'm' => 1024usize * 1024usize, @@ -216,12 +213,12 @@ impl ByteSplitter { Err(e) => crash!(1, "invalid number of bytes: {}", e), } }; - Box::new(ByteSplitter { + ByteSplitter { saved_bytes_to_write: n * multiplier, bytes_to_write: n * multiplier, break_on_line_end: settings.strategy == "b", require_whole_line: false, - }) as Box + } } } @@ -248,6 +245,7 @@ impl Splitter for ByteSplitter { } // (1, 3) -> "aab" +#[allow(clippy::many_single_char_names)] fn str_prefix(i: usize, width: usize) -> String { let mut c = "".to_owned(); let mut n = i; @@ -263,6 +261,7 @@ fn str_prefix(i: usize, width: usize) -> String { } // (1, 3) -> "001" +#[allow(clippy::many_single_char_names)] fn num_prefix(i: usize, width: usize) -> String { let mut c = "".to_owned(); let mut n = i; @@ -293,8 +292,8 @@ fn split(settings: &Settings) -> i32 { }); let mut splitter: Box = match settings.strategy.as_ref() { - "l" => LineSplitter::new(settings), - "b" | "C" => ByteSplitter::new(settings), + "l" => Box::new(LineSplitter::new(settings)), + "b" | "C" => Box::new(ByteSplitter::new(settings)), a => crash!(1, "strategy {} not supported", a), }; diff --git a/src/stat/fsext.rs b/src/stat/fsext.rs index b76451740e5..2f7d79e07a3 100644 --- a/src/stat/fsext.rs +++ b/src/stat/fsext.rs @@ -24,17 +24,17 @@ impl BirthTime for Metadata { fn pretty_birth(&self) -> String { self.created() .ok() - .and_then(|t| t.elapsed().ok()) - .map(|e| pretty_time(e.as_secs() as i64, e.subsec_nanos() as i64)) - .unwrap_or("-".to_owned()) + .and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()) + .map(|e| pretty_time(e.as_secs() as i64, i64::from(e.subsec_nanos()))) + .unwrap_or_else(|| "-".to_owned()) } fn birth(&self) -> String { self.created() .ok() - .and_then(|t| t.elapsed().ok()) + .and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok()) .map(|e| format!("{}", e.as_secs())) - .unwrap_or("0".to_owned()) + .unwrap_or_else(|| "0".to_owned()) } } @@ -46,6 +46,8 @@ macro_rules! has { } pub fn pretty_time(sec: i64, nsec: i64) -> String { + // sec == seconds since UNIX_EPOCH + // nsec == nanoseconds since (UNIX_EPOCH + sec) let tm = time::at(Timespec::new(sec, nsec as i32)); let res = time::strftime("%Y-%m-%d %H:%M:%S.%f %z", &tm).unwrap(); if res.ends_with(" -0000") { @@ -135,7 +137,7 @@ pub fn pretty_access(mode: mode_t) -> String { result } -use std::mem::{self, transmute}; +use std::mem; use std::path::Path; use std::borrow::Cow; use std::ffi::CString; @@ -217,8 +219,8 @@ impl FsMeta for Sstatfs { // struct statvfs, containing an unsigned long f_fsid #[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "linux"))] fn fsid(&self) -> u64 { - let f_fsid: &[u32; 2] = unsafe { transmute(&self.f_fsid) }; - (f_fsid[0] as u64) << 32 | f_fsid[1] as u64 + let f_fsid: &[u32; 2] = unsafe { &*(&self.f_fsid as *const uucore::libc::fsid_t as *const [u32; 2]) }; + (u64::from(f_fsid[0])) << 32 | u64::from(f_fsid[1]) } #[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "linux")))] fn fsid(&self) -> u64 { @@ -258,131 +260,131 @@ where let errno = IOError::last_os_error().raw_os_error().unwrap_or(0); Err(CString::from_raw(strerror(errno)) .into_string() - .unwrap_or("Unknown Error".to_owned())) + .unwrap_or_else(|_| "Unknown Error".to_owned())) + } } } } - } Err(e) => Err(e.description().to_owned()), } } pub fn pretty_fstype<'a>(fstype: i64) -> Cow<'a, str> { match fstype { - 0x61636673 => "acfs".into(), + 0x6163_6673 => "acfs".into(), 0xADF5 => "adfs".into(), 0xADFF => "affs".into(), - 0x5346414F => "afs".into(), - 0x09041934 => "anon-inode FS".into(), - 0x61756673 => "aufs".into(), + 0x5346_414F => "afs".into(), + 0x0904_1934 => "anon-inode FS".into(), + 0x6175_6673 => "aufs".into(), 0x0187 => "autofs".into(), - 0x42465331 => "befs".into(), - 0x62646576 => "bdevfs".into(), - 0x1BADFACE => "bfs".into(), - 0xCAFE4A11 => "bpf_fs".into(), - 0x42494E4D => "binfmt_misc".into(), - 0x9123683E => "btrfs".into(), - 0x73727279 => "btrfs_test".into(), - 0x00C36400 => "ceph".into(), - 0x0027E0EB => "cgroupfs".into(), - 0xFF534D42 => "cifs".into(), - 0x73757245 => "coda".into(), - 0x012FF7B7 => "coh".into(), - 0x62656570 => "configfs".into(), - 0x28CD3D45 => "cramfs".into(), - 0x453DCD28 => "cramfs-wend".into(), - 0x64626720 => "debugfs".into(), + 0x4246_5331 => "befs".into(), + 0x6264_6576 => "bdevfs".into(), + 0x1BAD_FACE => "bfs".into(), + 0xCAFE_4A11 => "bpf_fs".into(), + 0x4249_4E4D => "binfmt_misc".into(), + 0x9123_683E => "btrfs".into(), + 0x7372_7279 => "btrfs_test".into(), + 0x00C3_6400 => "ceph".into(), + 0x0027_E0EB => "cgroupfs".into(), + 0xFF53_4D42 => "cifs".into(), + 0x7375_7245 => "coda".into(), + 0x012F_F7B7 => "coh".into(), + 0x6265_6570 => "configfs".into(), + 0x28CD_3D45 => "cramfs".into(), + 0x453D_CD28 => "cramfs-wend".into(), + 0x6462_6720 => "debugfs".into(), 0x1373 => "devfs".into(), 0x1CD1 => "devpts".into(), 0xF15F => "ecryptfs".into(), - 0xDE5E81E4 => "efivarfs".into(), - 0x00414A53 => "efs".into(), + 0xDE5E_81E4 => "efivarfs".into(), + 0x0041_4A53 => "efs".into(), 0x5DF5 => "exofs".into(), 0x137D => "ext".into(), 0xEF53 => "ext2/ext3".into(), 0xEF51 => "ext2".into(), - 0xF2F52010 => "f2fs".into(), + 0xF2F5_2010 => "f2fs".into(), 0x4006 => "fat".into(), - 0x19830326 => "fhgfs".into(), - 0x65735546 => "fuseblk".into(), - 0x65735543 => "fusectl".into(), - 0x0BAD1DEA => "futexfs".into(), - 0x01161970 => "gfs/gfs2".into(), - 0x47504653 => "gpfs".into(), + 0x1983_0326 => "fhgfs".into(), + 0x6573_5546 => "fuseblk".into(), + 0x6573_5543 => "fusectl".into(), + 0x0BAD_1DEA => "futexfs".into(), + 0x0116_1970 => "gfs/gfs2".into(), + 0x4750_4653 => "gpfs".into(), 0x4244 => "hfs".into(), 0x482B => "hfs+".into(), 0x4858 => "hfsx".into(), - 0x00C0FFEE => "hostfs".into(), - 0xF995E849 => "hpfs".into(), - 0x958458F6 => "hugetlbfs".into(), - 0x11307854 => "inodefs".into(), - 0x013111A8 => "ibrix".into(), - 0x2BAD1DEA => "inotifyfs".into(), + 0x00C0_FFEE => "hostfs".into(), + 0xF995_E849 => "hpfs".into(), + 0x9584_58F6 => "hugetlbfs".into(), + 0x1130_7854 => "inodefs".into(), + 0x0131_11A8 => "ibrix".into(), + 0x2BAD_1DEA => "inotifyfs".into(), 0x9660 => "isofs".into(), 0x4004 => "isofs".into(), 0x4000 => "isofs".into(), 0x07C0 => "jffs".into(), 0x72B6 => "jffs2".into(), - 0x3153464A => "jfs".into(), - 0x6B414653 => "k-afs".into(), - 0xC97E8168 => "logfs".into(), - 0x0BD00BD0 => "lustre".into(), - 0x5346314D => "m1fs".into(), + 0x3153_464A => "jfs".into(), + 0x6B41_4653 => "k-afs".into(), + 0xC97E_8168 => "logfs".into(), + 0x0BD0_0BD0 => "lustre".into(), + 0x5346_314D => "m1fs".into(), 0x137F => "minix".into(), 0x138F => "minix (30 char.)".into(), 0x2468 => "minix v2".into(), 0x2478 => "minix v2 (30 char.)".into(), 0x4D5A => "minix3".into(), - 0x19800202 => "mqueue".into(), + 0x1980_0202 => "mqueue".into(), 0x4D44 => "msdos".into(), 0x564C => "novell".into(), 0x6969 => "nfs".into(), - 0x6E667364 => "nfsd".into(), + 0x6E66_7364 => "nfsd".into(), 0x3434 => "nilfs".into(), - 0x6E736673 => "nsfs".into(), - 0x5346544E => "ntfs".into(), + 0x6E73_6673 => "nsfs".into(), + 0x5346_544E => "ntfs".into(), 0x9FA1 => "openprom".into(), - 0x7461636F => "ocfs2".into(), - 0x794C7630 => "overlayfs".into(), - 0xAAD7AAEA => "panfs".into(), - 0x50495045 => "pipefs".into(), - 0x7C7C6673 => "prl_fs".into(), + 0x7461_636F => "ocfs2".into(), + 0x794C_7630 => "overlayfs".into(), + 0xAAD7_AAEA => "panfs".into(), + 0x5049_5045 => "pipefs".into(), + 0x7C7C_6673 => "prl_fs".into(), 0x9FA0 => "proc".into(), - 0x6165676C => "pstorefs".into(), + 0x6165_676C => "pstorefs".into(), 0x002F => "qnx4".into(), - 0x68191122 => "qnx6".into(), - 0x858458F6 => "ramfs".into(), - 0x52654973 => "reiserfs".into(), + 0x6819_1122 => "qnx6".into(), + 0x8584_58F6 => "ramfs".into(), + 0x5265_4973 => "reiserfs".into(), 0x7275 => "romfs".into(), - 0x67596969 => "rpc_pipefs".into(), - 0x73636673 => "securityfs".into(), - 0xF97CFF8C => "selinux".into(), - 0x43415D53 => "smackfs".into(), + 0x6759_6969 => "rpc_pipefs".into(), + 0x7363_6673 => "securityfs".into(), + 0xF97C_FF8C => "selinux".into(), + 0x4341_5D53 => "smackfs".into(), 0x517B => "smb".into(), - 0xFE534D42 => "smb2".into(), - 0xBEEFDEAD => "snfs".into(), - 0x534F434B => "sockfs".into(), - 0x73717368 => "squashfs".into(), - 0x62656572 => "sysfs".into(), - 0x012FF7B6 => "sysv2".into(), - 0x012FF7B5 => "sysv4".into(), - 0x01021994 => "tmpfs".into(), - 0x74726163 => "tracefs".into(), - 0x24051905 => "ubifs".into(), - 0x15013346 => "udf".into(), - 0x00011954 => "ufs".into(), - 0x54190100 => "ufs".into(), + 0xFE53_4D42 => "smb2".into(), + 0xBEEF_DEAD => "snfs".into(), + 0x534F_434B => "sockfs".into(), + 0x7371_7368 => "squashfs".into(), + 0x6265_6572 => "sysfs".into(), + 0x012F_F7B6 => "sysv2".into(), + 0x012F_F7B5 => "sysv4".into(), + 0x0102_1994 => "tmpfs".into(), + 0x7472_6163 => "tracefs".into(), + 0x2405_1905 => "ubifs".into(), + 0x1501_3346 => "udf".into(), + 0x0001_1954 => "ufs".into(), + 0x5419_0100 => "ufs".into(), 0x9FA2 => "usbdevfs".into(), - 0x01021997 => "v9fs".into(), - 0xBACBACBC => "vmhgfs".into(), - 0xA501FCF5 => "vxfs".into(), - 0x565A4653 => "vzfs".into(), - 0x53464846 => "wslfs".into(), - 0xABBA1974 => "xenfs".into(), - 0x012FF7B4 => "xenix".into(), - 0x58465342 => "xfs".into(), - 0x012FD16D => "xia".into(), - 0x2FC12FC1 => "zfs".into(), + 0x0102_1997 => "v9fs".into(), + 0xBACB_ACBC => "vmhgfs".into(), + 0xA501_FCF5 => "vxfs".into(), + 0x565A_4653 => "vzfs".into(), + 0x5346_4846 => "wslfs".into(), + 0xABBA_1974 => "xenfs".into(), + 0x012F_F7B4 => "xenix".into(), + 0x5846_5342 => "xfs".into(), + 0x012F_D16D => "xia".into(), + 0x2FC1_2FC1 => "zfs".into(), other => format!("UNKNOWN ({:#x})", other).into(), } } diff --git a/src/stat/stat.rs b/src/stat/stat.rs index 7b65c7a24ec..cf8ea151795 100644 --- a/src/stat/stat.rs +++ b/src/stat/stat.rs @@ -85,10 +85,10 @@ macro_rules! print_adjusted { } } -static NAME: &'static str = "stat"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &str = "stat"; +static VERSION: &str = env!("CARGO_PKG_VERSION"); -const MOUNT_INFO: &'static str = "/etc/mtab"; +const MOUNT_INFO: &str = "/etc/mtab"; pub const F_ALTER: u8 = 1; pub const F_ZERO: u8 = 1 << 1; pub const F_LEFT: u8 = 1 << 2; @@ -133,12 +133,12 @@ impl ScanUtil for str { let mut chars = self.chars(); let mut i = 0; match chars.next() { - Some('-') | Some('+') | Some('0'...'9') => i += 1, + Some('-') | Some('+') | Some('0'..='9') => i += 1, _ => return None, } - while let Some(c) = chars.next() { + for c in chars { match c { - '0'...'9' => i += 1, + '0'..='9' => i += 1, _ => break, } } @@ -155,10 +155,10 @@ impl ScanUtil for str { 16 => 2, _ => return None, }; - let mut chars = self.chars().enumerate(); + let chars = self.chars().enumerate(); let mut res = 0_u32; let mut offset = 0_usize; - while let Some((i, c)) = chars.next() { + for (i, c) in chars { if i >= count { break; } @@ -183,7 +183,7 @@ impl ScanUtil for str { } } -pub fn group_num<'a>(s: &'a str) -> Cow<'a, str> { +pub fn group_num(s: &str) -> Cow { assert!(s.chars().all(char::is_numeric)); if s.len() < 4 { return s.into(); @@ -209,6 +209,7 @@ pub struct Stater { default_dev_tokens: Vec, } +#[allow(clippy::cognitive_complexity)] fn print_it(arg: &str, otype: OutputType, flag: u8, width: usize, precision: i32) { // If the precision is given as just '.', the precision is taken to be zero. // A negative precision is taken as if the precision were omitted. @@ -369,12 +370,9 @@ impl Stater { let mut precision = -1_i32; let mut j = i; - match fmtstr[j..].scan_num::() { - Some((field_width, offset)) => { - width = field_width; - j += offset; - } - None => (), + if let Some((field_width, offset)) = fmtstr[j..].scan_num::() { + width = field_width; + j += offset; } check_bound!(fmtstr, bound, old, j); @@ -396,9 +394,9 @@ impl Stater { i = j; tokens.push(Token::Directive { - width: width, - flag: flag, - precision: precision, + width, + flag, + precision, format: chars[i], }) } @@ -422,7 +420,7 @@ impl Stater { tokens.push(Token::Char('x')); } } - '0'...'7' => { + '0'..='7' => { let (c, offset) = fmtstr[i..].scan_char(8).unwrap(); tokens.push(Token::Char(c)); i += offset - 1; @@ -458,7 +456,7 @@ impl Stater { let fmtstr = if matches.opt_present("printf") { matches.opt_str("printf").expect("Invalid format string") } else { - matches.opt_str("format").unwrap_or("".to_owned()) + matches.opt_str("format").unwrap_or_else(|| "".to_owned()) }; let use_printf = matches.opt_present("printf"); @@ -478,12 +476,12 @@ impl Stater { None } else { let reader = BufReader::new( - File::open(MOUNT_INFO).expect(&format!("Failed to read {}", MOUNT_INFO)), + File::open(MOUNT_INFO).unwrap_or_else(|_| panic!("Failed to read {}", MOUNT_INFO)), ); let mut mount_list = reader .lines() - .filter_map(|s| s.ok()) - .filter_map(|line| line.split_whitespace().nth(1).map(|s| s.to_owned())) + .filter_map(std::result::Result::ok) + .filter_map(|line| line.split_whitespace().nth(1).map(std::borrow::ToOwned::to_owned)) .collect::>(); // Reverse sort. The longer comes first. mount_list.sort_by(|a, b| b.cmp(a)); @@ -492,12 +490,12 @@ impl Stater { Ok(Stater { follow: matches.opt_present("dereference"), - showfs: showfs, + showfs, from_user: !fmtstr.is_empty(), files: matches.free, - default_tokens: default_tokens, - default_dev_tokens: default_dev_tokens, - mount_list: mount_list, + default_tokens, + default_dev_tokens, + mount_list, }) } @@ -507,7 +505,7 @@ impl Stater { Err(_) => return None, }; if let Some(ref mount_list) = self.mount_list { - for root in mount_list.into_iter() { + for root in mount_list.iter() { if path.starts_with(root) { return Some(root.clone()); } @@ -541,10 +539,10 @@ impl Stater { &self.default_dev_tokens }; - for t in tokens.into_iter() { - match t { - &Token::Char(c) => print!("{}", c), - &Token::Directive { + for t in tokens.iter() { + match *t { + Token::Char(c) => print!("{}", c), + Token::Directive { flag, width, precision, @@ -608,7 +606,7 @@ impl Stater { // group name of owner 'G' => { arg = entries::gid2grp(meta.gid()) - .unwrap_or("UNKNOWN".to_owned()); + .unwrap_or_else(|_| "UNKNOWN".to_owned()); otype = OutputType::Str; } // number of hard links @@ -683,7 +681,7 @@ impl Stater { // user name of owner 'U' => { arg = entries::uid2usr(meta.uid()) - .unwrap_or("UNKNOWN".to_owned()); + .unwrap_or_else(|_| "UNKNOWN".to_owned()); otype = OutputType::Str; } @@ -750,10 +748,10 @@ impl Stater { Ok(meta) => { let tokens = &self.default_tokens; - for t in tokens.into_iter() { - match t { - &Token::Char(c) => print!("{}", c), - &Token::Directive { + for t in tokens.iter() { + match *t { + Token::Char(c) => print!("{}", c), + Token::Directive { flag, width, precision, diff --git a/src/stdbuf/stdbuf.rs b/src/stdbuf/stdbuf.rs index 1b58ad5a245..9c27a1a138d 100644 --- a/src/stdbuf/stdbuf.rs +++ b/src/stdbuf/stdbuf.rs @@ -86,15 +86,15 @@ fn print_usage(opts: &Options) { Also some filters (like 'dd' and 'cat' etc.) don't use streams for I/O, \ and are thus unaffected by 'stdbuf' settings.\n"; println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage: stdbuf OPTION... COMMAND"); - println!(""); + println!(); println!("{}\n{}", opts.usage(brief), explanation); } fn parse_size(size: &str) -> Option { let ext = size.trim_start_matches(|c: char| c.is_digit(10)); - let num = size.trim_end_matches(|c: char| c.is_alphabetic()); + let num = size.trim_end_matches(char::is_alphabetic); let mut recovered = num.to_owned(); recovered.push_str(ext); if recovered != size { @@ -238,7 +238,7 @@ pub fn uumain(args: Vec) -> i32 { stderr: BufferType::Default, }; let mut command_idx: i32 = -1; - for i in 1..args.len() + 1 { + for i in 1..=args.len() { match parse_options(&args[1..i], &mut options, &opts) { Ok(OkMsg::Buffering) => { command_idx = (i as i32) - 1; @@ -279,9 +279,9 @@ pub fn uumain(args: Vec) -> i32 { }; match process.wait() { Ok(status) => match status.code() { - Some(i) => return i, + Some(i) => i, None => crash!(1, "process killed by signal {}", status.signal().unwrap()), }, Err(e) => crash!(1, "{}", e), - }; + } } diff --git a/src/sum/sum.rs b/src/sum/sum.rs index 1fd7a6202f7..797cbae046b 100644 --- a/src/sum/sum.rs +++ b/src/sum/sum.rs @@ -31,7 +31,7 @@ fn bsd_sum(mut reader: Box) -> (usize, u16) { blocks_read += 1; for &byte in buf[..n].iter() { checksum = (checksum >> 1) + ((checksum & 1) << 15); - checksum = checksum.wrapping_add(byte as u16); + checksum = checksum.wrapping_add(u16::from(byte)); } } _ => break, @@ -51,7 +51,7 @@ fn sysv_sum(mut reader: Box) -> (usize, u16) { Ok(n) if n != 0 => { blocks_read += 1; for &byte in buf[..n].iter() { - ret = ret.wrapping_add(byte as u32); + ret = ret.wrapping_add(u32::from(byte)); } } _ => break, diff --git a/src/sync/sync.rs b/src/sync/sync.rs index c9608e519b4..a6d7faabafd 100644 --- a/src/sync/sync.rs +++ b/src/sync/sync.rs @@ -72,6 +72,7 @@ mod platform { } unsafe fn find_first_volume() -> (String, winnt::HANDLE) { + #[allow(deprecated)] let mut name: [winnt::WCHAR; minwindef::MAX_PATH] = mem::uninitialized(); let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as minwindef::DWORD); if handle == handleapi::INVALID_HANDLE_VALUE { @@ -87,6 +88,7 @@ mod platform { let (first_volume, next_volume_handle) = find_first_volume(); let mut volumes = vec![first_volume]; loop { + #[allow(deprecated)] let mut name: [winnt::WCHAR; minwindef::MAX_PATH] = mem::uninitialized(); if kernel32::FindNextVolumeW( next_volume_handle, @@ -147,7 +149,7 @@ pub fn uumain(args: Vec) -> i32 { fn version() { println!("{} (uutils) {}", NAME, VERSION); println!("The MIT License"); - println!(""); + println!(); println!("Author -- Alexander Fomin."); } diff --git a/src/tac/tac.rs b/src/tac/tac.rs index eb6786359e2..61bff94a79b 100644 --- a/src/tac/tac.rs +++ b/src/tac/tac.rs @@ -103,12 +103,9 @@ fn tac(filenames: Vec, before: bool, _: bool, separator: &str) { }); let mut data = Vec::new(); - match file.read_to_end(&mut data) { - Err(e) => { - show_warning!("failed to read '{}': {}", filename, e); - continue; - } - Ok(_) => (), + if let Err(e) = file.read_to_end(&mut data) { + show_warning!("failed to read '{}': {}", filename, e); + continue; }; // find offsets in string of all separators @@ -126,7 +123,6 @@ fn tac(filenames: Vec, before: bool, _: bool, separator: &str) { i += 1; } } - drop(i); // if there isn't a separator at the end of the file, fake it if offsets.is_empty() || *offsets.last().unwrap() < data.len() - slen { diff --git a/src/tail/tail.rs b/src/tail/tail.rs index c6bbbfdf22c..8aa7abb3eee 100755 --- a/src/tail/tail.rs +++ b/src/tail/tail.rs @@ -48,7 +48,7 @@ struct Settings { impl Default for Settings { fn default() -> Settings { Settings { - mode: FilterMode::Lines(10, '\n' as u8), + mode: FilterMode::Lines(10, b'\n'), sleep_msec: 1000, beginning: false, follow: false, @@ -57,13 +57,14 @@ impl Default for Settings { } } +#[allow(clippy::cognitive_complexity)] pub fn uumain(args: Vec) -> i32 { let mut settings: Settings = Default::default(); // handle obsolete -number syntax let options = match obsolete(&args[1..]) { (args, Some(n)) => { - settings.mode = FilterMode::Lines(n, '\n' as u8); + settings.mode = FilterMode::Lines(n, b'\n'); args } (args, None) => args, @@ -114,16 +115,12 @@ pub fn uumain(args: Vec) -> i32 { settings.follow = given_options.opt_present("f"); if settings.follow { - match given_options.opt_str("s") { - Some(n) => { - let parsed: Option = n.parse().ok(); - match parsed { - Some(m) => settings.sleep_msec = m * 1000, - None => {} - } + if let Some(n) = given_options.opt_str("s") { + let parsed: Option = n.parse().ok(); + if let Some(m) = parsed { + settings.sleep_msec = m * 1000 } - None => {} - }; + } } if let Some(pid_str) = given_options.opt_str("pid") { @@ -150,29 +147,26 @@ pub fn uumain(args: Vec) -> i32 { slice = &slice[1..]; } match parse_size(slice) { - Ok(m) => settings.mode = FilterMode::Lines(m, '\n' as u8), + Ok(m) => settings.mode = FilterMode::Lines(m, b'\n'), Err(e) => { show_error!("{}", e.description()); return 1; } } } - None => match given_options.opt_str("c") { - Some(n) => { - let mut slice: &str = n.as_ref(); - if slice.chars().next().unwrap_or('_') == '+' { - settings.beginning = true; - slice = &slice[1..]; - } - match parse_size(slice) { - Ok(m) => settings.mode = FilterMode::Bytes(m), - Err(e) => { - show_error!("{}", e.description()); - return 1; - } + None => if let Some(n) = given_options.opt_str("c") { + let mut slice: &str = n.as_ref(); + if slice.chars().next().unwrap_or('_') == '+' { + settings.beginning = true; + slice = &slice[1..]; + } + match parse_size(slice) { + Ok(m) => settings.mode = FilterMode::Bytes(m), + Err(e) => { + show_error!("{}", e.description()); + return 1; } } - None => {} }, }; @@ -276,7 +270,7 @@ pub fn parse_size(mut size_slice: &str) -> Result { 1024u64 }; - let exponent = if size_slice.len() > 0 { + let exponent = if !size_slice.is_empty() { let mut has_suffix = true; let exp = match size_slice.chars().last().unwrap_or('_') { 'K' | 'k' => 1u64, @@ -316,7 +310,7 @@ pub fn parse_size(mut size_slice: &str) -> Result { let value: Option = size_slice.parse().ok(); value .map(|v| Ok(multiplier * v)) - .unwrap_or(Err(ParseSizeErr::parse_failure(size_slice))) + .unwrap_or_else(|| Err(ParseSizeErr::parse_failure(size_slice))) } } @@ -333,7 +327,7 @@ fn obsolete(options: &[String]) -> (Vec, Option) { let current = options[a].clone(); let current = current.as_bytes(); - if current.len() > 1 && current[0] == '-' as u8 { + if current.len() > 1 && current[0] == b'-' { let len = current.len(); for pos in 1..len { // Ensure that the argument is only made out of digits @@ -456,7 +450,7 @@ fn bounded_tail(mut file: &File, settings: &Settings) { // Find the position in the file to start printing from. match settings.mode { FilterMode::Lines(mut count, delimiter) => { - backwards_thru_file(&mut file, size, &mut buf, delimiter, &mut |byte| { + backwards_thru_file(&file, size, &mut buf, delimiter, &mut |byte| { if byte == delimiter { count -= 1; count == 0 @@ -476,7 +470,7 @@ fn bounded_tail(mut file: &File, settings: &Settings) { let mut stdout = stdout(); for b in &buf[0..bytes_read] { - print_byte(&mut stdout, b); + print_byte(&mut stdout, *b); } if bytes_read == 0 { @@ -549,7 +543,7 @@ fn unbounded_tail(reader: &mut BufReader, settings: &Settings) { } let mut stdout = stdout(); for datum in &ringbuf { - print_byte(&mut stdout, datum); + print_byte(&mut stdout, *datum); } } } @@ -560,8 +554,8 @@ fn is_seekable(file: &mut T) -> bool { } #[inline] -fn print_byte(stdout: &mut T, ch: &u8) { - if let Err(err) = stdout.write(&[*ch]) { +fn print_byte(stdout: &mut T, ch: u8) { + if let Err(err) = stdout.write(&[ch]) { crash!(1, "{}", err); } } diff --git a/src/tee/tee.rs b/src/tee/tee.rs index de77d855575..abc77e347a5 100644 --- a/src/tee/tee.rs +++ b/src/tee/tee.rs @@ -80,7 +80,7 @@ fn options(args: &[String]) -> Result { fn exec(options: Options) -> Result<()> { match options.print_and_exit { - Some(text) => Ok(println!("{}", text)), + Some(text) => { println!("{}", text); Ok(()) }, None => tee(options), } } @@ -119,8 +119,8 @@ fn open(name: String, append: bool) -> Box { } }; Box::new(NamedWriter { - inner: inner, - path: path, + inner, + path, }) as Box } diff --git a/src/test/test.rs b/src/test/test.rs index 907b4488810..a89ce730004 100644 --- a/src/test/test.rs +++ b/src/test/test.rs @@ -53,7 +53,7 @@ pub fn uumain(_: Vec) -> i32 { } fn one(args: &[&[u8]]) -> bool { - args[0].len() > 0 + !args[0].is_empty() } fn two(args: &[&[u8]], error: &mut bool) -> bool { @@ -212,13 +212,13 @@ enum Precedence { } fn parse_expr(mut args: &[&[u8]], error: &mut bool) -> bool { - if args.len() == 0 { + if args.is_empty() { false } else { let hashmap = setup_hashmap(); let lhs = dispatch(&mut args, error); - if args.len() > 0 { + if !args.is_empty() { parse_expr_helper(&hashmap, &mut args, lhs, Precedence::Unknown, error) } else { lhs @@ -237,11 +237,11 @@ fn parse_expr_helper<'a>( *error = true; &min_prec }); - while !*error && args.len() > 0 && prec as usize >= min_prec as usize { + while !*error && !args.is_empty() && prec as usize >= min_prec as usize { let op = args[0]; *args = &(*args)[1..]; let mut rhs = dispatch(args, error); - while args.len() > 0 { + while !args.is_empty() { let subprec = *hashmap.get(&args[0]).unwrap_or_else(|| { *error = true; &min_prec @@ -269,7 +269,7 @@ fn parse_expr_helper<'a>( Precedence::Paren => unimplemented!(), // TODO: implement parentheses _ => unreachable!(), }; - if args.len() > 0 { + if !args.is_empty() { prec = *hashmap.get(&args[0]).unwrap_or_else(|| { *error = true; &min_prec @@ -370,7 +370,7 @@ fn path(path: &[u8], cond: PathCondition) -> bool { } else if gid == metadata.gid() { metadata.mode() & ((p as u32) << 3) != 0 } else { - metadata.mode() & ((p as u32)) != 0 + metadata.mode() & (p as u32) != 0 } }; diff --git a/src/touch/touch.rs b/src/touch/touch.rs index ed75a767651..503ee062e76 100644 --- a/src/touch/touch.rs +++ b/src/touch/touch.rs @@ -95,9 +95,9 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") || matches.free.is_empty() { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage: {} [OPTION]... FILE...", NAME); - println!(""); + println!(); println!( "{}", opts.usage( @@ -182,10 +182,8 @@ pub fn uumain(args: Vec) -> i32 { if let Err(e) = set_symlink_file_times(path, atime, mtime) { show_warning!("cannot touch '{}': {}", path, e); } - } else { - if let Err(e) = filetime::set_file_times(path, atime, mtime) { + } else if let Err(e) = filetime::set_file_times(path, atime, mtime) { show_warning!("cannot touch '{}': {}", path, e); - } } } diff --git a/src/tr/expand.rs b/src/tr/expand.rs index d9d38688ab5..510e3392597 100644 --- a/src/tr/expand.rs +++ b/src/tr/expand.rs @@ -43,7 +43,7 @@ impl<'a> Iterator for Unescape<'a> { #[inline] fn next(&mut self) -> Option { - if self.string.len() == 0 { + if self.string.is_empty() { return None; } @@ -95,7 +95,10 @@ impl<'a> Iterator for ExpandSet<'a> { self.unesc.next(); // this is the '-' let last = self.unesc.next().unwrap(); // this is the end of the range + #[allow(clippy::range_plus_one)] + { self.range = first as u32 + 1..last as u32 + 1; + } } return Some(first); // in any case, return the next char diff --git a/src/tr/tr.rs b/src/tr/tr.rs index c8e28c774b5..069d0fbc45e 100644 --- a/src/tr/tr.rs +++ b/src/tr/tr.rs @@ -33,7 +33,7 @@ static VERSION: &str = env!("CARGO_PKG_VERSION"); const BUFFER_LEN: usize = 1024; trait SymbolTranslator { - fn translate(&self, c: &char, prev_c: &char) -> Option; + fn translate(&self, c: char, prev_c: char) -> Option; } struct DeleteOperation { @@ -45,16 +45,16 @@ impl DeleteOperation { fn new(set: ExpandSet, complement: bool) -> DeleteOperation { DeleteOperation { bset: set.map(|c| c as usize).collect(), - complement: complement, + complement, } } } impl SymbolTranslator for DeleteOperation { - fn translate(&self, c: &char, _prev_c: &char) -> Option { - let uc = *c as usize; + fn translate(&self, c: char, _prev_c: char) -> Option { + let uc = c as usize; if self.complement == self.bset.contains(uc) { - Some(*c) + Some(c) } else { None } @@ -70,17 +70,17 @@ impl SqueezeOperation { fn new(squeeze_set: ExpandSet, complement: bool) -> SqueezeOperation { SqueezeOperation { squeeze_set: squeeze_set.map(|c| c as usize).collect(), - complement: complement, + complement, } } } impl SymbolTranslator for SqueezeOperation { - fn translate(&self, c: &char, prev_c: &char) -> Option { - if *prev_c == *c && self.complement != self.squeeze_set.contains(*c as usize) { + fn translate(&self, c: char, prev_c: char) -> Option { + if prev_c == c && self.complement != self.squeeze_set.contains(c as usize) { None } else { - Some(*c) + Some(c) } } } @@ -100,19 +100,19 @@ impl DeleteAndSqueezeOperation { DeleteAndSqueezeOperation { delete_set: delete_set.map(|c| c as usize).collect(), squeeze_set: squeeze_set.map(|c| c as usize).collect(), - complement: complement, + complement, } } } impl SymbolTranslator for DeleteAndSqueezeOperation { - fn translate(&self, c: &char, prev_c: &char) -> Option { - if self.complement != self.delete_set.contains(*c as usize) - || *prev_c == *c && self.squeeze_set.contains(*c as usize) + fn translate(&self, c: char, prev_c: char) -> Option { + if self.complement != self.delete_set.contains(c as usize) + || prev_c == c && self.squeeze_set.contains(c as usize) { None } else { - Some(*c) + Some(c) } } } @@ -140,8 +140,8 @@ impl TranslateOperation { } impl SymbolTranslator for TranslateOperation { - fn translate(&self, c: &char, _prev_c: &char) -> Option { - Some(*self.translate_map.get(&(*c as usize)).unwrap_or(c)) + fn translate(&self, c: char, _prev_c: char) -> Option { + Some(*self.translate_map.get(&(c as usize)).unwrap_or(&c)) } } @@ -161,7 +161,7 @@ fn translate_input( { // isolation to make borrow checker happy let filtered = buf.chars().filter_map(|c| { - let res = translator.translate(&c, &prev_c); + let res = translator.translate(c, prev_c); if res.is_some() { prev_c = c; } @@ -178,10 +178,10 @@ fn translate_input( fn usage(opts: &Options) { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [OPTIONS] SET1 [SET2]", NAME); - println!(""); + println!(); println!("{}", opts.usage("Translate or delete characters.")); } diff --git a/src/truncate/truncate.rs b/src/truncate/truncate.rs index 47070d9a7bf..f6ee266e0f9 100644 --- a/src/truncate/truncate.rs +++ b/src/truncate/truncate.rs @@ -58,15 +58,15 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [OPTION]... FILE...", NAME); - println!(""); + println!(); print!( "{}", opts.usage("Shrink or extend the size of each file to the specified size.") ); - print!( + println!( " SIZE is an integer with an optional prefix and optional unit. The available units (K, M, G, T, P, E, Z, and Y) use the following format: @@ -83,8 +83,7 @@ file based on its current size: '<' => at most '>' => at least '/' => round down to multiple of - '%' => round up to multiple of -" + '%' => round up to multiple of" ); } else if matches.opt_present("version") { println!("{} {}", NAME, VERSION); @@ -191,7 +190,7 @@ fn parse_size(size: &str) -> (u64, TruncateMode) { }; if slice.chars().last().unwrap().is_alphabetic() { slice = &slice[..slice.len() - 1]; - if slice.len() > 0 && slice.chars().last().unwrap().is_alphabetic() { + if !slice.is_empty() && slice.chars().last().unwrap().is_alphabetic() { slice = &slice[..slice.len() - 1]; } } diff --git a/src/tsort/tsort.rs b/src/tsort/tsort.rs index 72a96229da8..b24ce500746 100644 --- a/src/tsort/tsort.rs +++ b/src/tsort/tsort.rs @@ -36,10 +36,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("h") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [OPTIONS] FILE", NAME); - println!(""); + println!(); println!("{}", opts.usage("Topological sort the strings in FILE. Strings are defined as any sequence of tokens separated by whitespace (tab, space, or newline). If FILE is not passed in, stdin is used instead.")); return 0; } @@ -135,12 +135,12 @@ impl Graph { self.in_edges.get(to).unwrap().contains(from) } - fn init_node(&mut self, n: &String) { - self.in_edges.insert(n.clone(), HashSet::new()); - self.out_edges.insert(n.clone(), vec![]); + fn init_node(&mut self, n: &str) { + self.in_edges.insert(n.to_string(), HashSet::new()); + self.out_edges.insert(n.to_string(), vec![]); } - fn add_edge(&mut self, from: &String, to: &String) { + fn add_edge(&mut self, from: &str, to: &str) { if !self.has_node(to) { self.init_node(to); } @@ -150,8 +150,8 @@ impl Graph { } if from != to && !self.has_edge(from, to) { - self.in_edges.get_mut(to).unwrap().insert(from.clone()); - self.out_edges.get_mut(from).unwrap().push(to.clone()); + self.in_edges.get_mut(to).unwrap().insert(from.to_string()); + self.out_edges.get_mut(from).unwrap().push(to.to_string()); } } @@ -185,7 +185,7 @@ impl Graph { } fn is_acyclic(&self) -> bool { - for (_, edges) in &self.out_edges { + for edges in self.out_edges.values() { if !edges.is_empty() { return false; } diff --git a/src/tty/tty.rs b/src/tty/tty.rs index eaff78c964b..033f4fbcce3 100644 --- a/src/tty/tty.rs +++ b/src/tty/tty.rs @@ -41,10 +41,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [OPTION]...", NAME); - println!(""); + println!(); print!( "{}", opts.usage("Print the file name of the terminal connected to standard input.") diff --git a/src/unexpand/unexpand.rs b/src/unexpand/unexpand.rs index 076a68fee7f..2006424a513 100644 --- a/src/unexpand/unexpand.rs +++ b/src/unexpand/unexpand.rs @@ -76,10 +76,10 @@ impl Options { }; Options { - files: files, - tabstops: tabstops, - aflag: aflag, - uflag: uflag, + files, + tabstops, + aflag, + uflag, } } } @@ -189,13 +189,13 @@ fn write_tabs( break; } - safe_unwrap!(output.write_all("\t".as_bytes())); + safe_unwrap!(output.write_all(b"\t")); scol += nts; } } while col > scol { - safe_unwrap!(output.write_all(" ".as_bytes())); + safe_unwrap!(output.write_all(b" ")); scol += 1; } } @@ -219,7 +219,7 @@ fn unexpand(options: Options) { for file in options.files.into_iter() { let mut fh = open(file); - while match fh.read_until('\n' as u8, &mut buf) { + while match fh.read_until(b'\n', &mut buf) { Ok(s) => s > 0, Err(_) => !buf.is_empty(), } { diff --git a/src/uniq/uniq.rs b/src/uniq/uniq.rs index 62db7b104d7..0b64bc08470 100644 --- a/src/uniq/uniq.rs +++ b/src/uniq/uniq.rs @@ -79,12 +79,12 @@ impl Uniq { let mut i = 0; while field < skip_fields && i < line.len() { while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() { - i = i + 1; + i += 1; } while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() { - i = i + 1; + i += 1; } - field = field + 1; + field += 1; } &line[i..] } else { @@ -99,7 +99,7 @@ impl Uniq { if self.zero_terminated { 0 } else { - '\n' as u8 + b'\n' } } @@ -126,7 +126,7 @@ impl Uniq { // fast path: avoid skipping if self.ignore_case && slice_start == 0 && slice_stop == len { return closure(&mut fields_to_check.chars().map(|c| match c { - 'a'...'z' => ((c as u8) - 32) as char, + 'a'..='z' => ((c as u8) - 32) as char, _ => c, })); } @@ -142,7 +142,7 @@ impl Uniq { .skip(slice_start) .take(slice_stop) .map(|c| match c { - 'a'...'z' => ((c as u8) - 32) as char, + 'a'..='z' => ((c as u8) - 32) as char, _ => c, }), ) @@ -252,10 +252,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); + println!(); print!( "{}", opts.usage( @@ -263,7 +263,7 @@ pub fn uumain(args: Vec) -> i32 { writing to OUTPUT (or standard output)." ) ); - println!(""); + println!(); println!( "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\ You may want to sort the input first, or use 'sort -u' without '{0}'.\n", diff --git a/src/unlink/unlink.rs b/src/unlink/unlink.rs index 9bca5e585bf..8c472824b6a 100644 --- a/src/unlink/unlink.rs +++ b/src/unlink/unlink.rs @@ -21,7 +21,6 @@ use getopts::Options; use libc::{S_IFLNK, S_IFMT, S_IFREG}; use libc::{lstat, stat, unlink}; use std::io::{Error, ErrorKind}; -use std::mem::uninitialized; use std::ffi::CString; static NAME: &str = "unlink"; @@ -40,10 +39,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [FILE]... [OPTION]...", NAME); - println!(""); + println!(); println!("{}", opts.usage("Unlink the file at [FILE].")); return 0; } @@ -71,7 +70,8 @@ pub fn uumain(args: Vec) -> i32 { let c_string = CString::new(matches.free[0].clone()).unwrap(); // unwrap() cannot fail, the string comes from argv so it cannot contain a \0. let st_mode = { - let mut buf: stat = unsafe { uninitialized() }; + #[allow(deprecated)] + let mut buf: stat = unsafe { std::mem::uninitialized() }; let result = unsafe { lstat( c_string.as_ptr(), diff --git a/src/uptime/uptime.rs b/src/uptime/uptime.rs index b2d97ee650f..73fca4716cb 100644 --- a/src/uptime/uptime.rs +++ b/src/uptime/uptime.rs @@ -50,10 +50,10 @@ pub fn uumain(args: Vec) -> i32 { } if matches.opt_present("help") || !matches.free.is_empty() { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {0} [OPTION]", NAME); - println!(""); + println!(); println!( "{}", opts.usage( @@ -85,13 +85,12 @@ pub fn uumain(args: Vec) -> i32 { #[cfg(unix)] fn print_loadavg() { use libc::c_double; - use std::mem::transmute; let mut avg: [c_double; 3] = [0.0; 3]; - let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) }; + let loads: i32 = unsafe { getloadavg(avg.as_mut_ptr(), 3) }; if loads == -1 { - print!("\n"); + println!(); } else { print!("load average: "); for n in 0..loads { @@ -138,11 +137,11 @@ fn process_utmpx() -> (Option, usize) { } fn print_nusers(nusers: usize) { - if nusers == 1 { - print!("1 user, "); - } else if nusers > 1 { - print!("{} users, ", nusers); - } + match nusers.cmp(&1) { + std::cmp::Ordering::Equal => print!("1 user, "), + std::cmp::Ordering::Greater => print!("{} users, ", nusers), + _ => {} + }; } fn print_time() { @@ -189,11 +188,9 @@ fn print_uptime(upsecs: i64) { let updays = upsecs / 86400; let uphours = (upsecs - (updays * 86400)) / 3600; let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60; - if updays == 1 { - print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins); - } else if updays > 1 { - print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins); - } else { - print!("up {:2}:{:02}, ", uphours, upmins); - } + match updays.cmp(&1) { + std::cmp::Ordering::Equal => print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins), + std::cmp::Ordering::Greater => print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins), + _ => print!("up {:2}:{:02}, ", uphours, upmins), + }; } diff --git a/src/users/users.rs b/src/users/users.rs index 10fb5eca5ca..11330346e8c 100644 --- a/src/users/users.rs +++ b/src/users/users.rs @@ -37,10 +37,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [OPTION]... [FILE]", NAME); - println!(""); + println!(); println!( "{}", opts.usage("Output who is currently logged in according to FILE.") @@ -67,7 +67,7 @@ pub fn uumain(args: Vec) -> i32 { fn exec(filename: &str) { let mut users = Utmpx::iter_all_records() .read_from(filename) - .filter(|ut| ut.is_user_process()) + .filter(uucore::utmpx::Utmpx::is_user_process) .map(|ut| ut.user()) .collect::>(); diff --git a/src/uutils/uutils.rs b/src/uutils/uutils.rs index a2481bcf73e..e7bd5434544 100644 --- a/src/uutils/uutils.rs +++ b/src/uutils/uutils.rs @@ -24,10 +24,11 @@ include!(concat!(env!("OUT_DIR"), "/uutils_map.rs")); fn usage(cmap: &UtilityMap) { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {} [util [arguments...]]\n", NAME); println!("Currently defined functions:"); + #[allow(clippy::map_clone)] let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect(); utils.sort(); for util in utils { @@ -70,7 +71,7 @@ fn main() { } // try first arg as util name. - if args.len() >= 1 { + if !args.is_empty() { let util = &args[0][..]; match umap.get(util) { diff --git a/src/wc/wc.rs b/src/wc/wc.rs index 67c120e9313..78285941275 100644 --- a/src/wc/wc.rs +++ b/src/wc/wc.rs @@ -90,10 +90,10 @@ pub fn uumain(args: Vec) -> i32 { if matches.opt_present("help") { println!("{} {}", NAME, VERSION); - println!(""); + println!(); println!("Usage:"); println!(" {0} [OPTION]... [FILE]...", NAME); - println!(""); + println!(); println!( "{}", opts.usage("Print newline, word and byte counts for each FILE") @@ -121,10 +121,10 @@ pub fn uumain(args: Vec) -> i32 { 0 } -const CR: u8 = '\r' as u8; -const LF: u8 = '\n' as u8; -const SPACE: u8 = ' ' as u8; -const TAB: u8 = '\t' as u8; +const CR: u8 = b'\r'; +const LF: u8 = b'\n'; +const SPACE: u8 = b' '; +const TAB: u8 = b'\t'; const SYN: u8 = 0x16 as u8; const FF: u8 = 0x0C as u8; @@ -254,7 +254,7 @@ fn print_stats(settings: &Settings, result: &Result, max_width: usize) { if result.title != "-" { println!(" {}", result.title); } else { - println!(""); + println!(); } } diff --git a/src/who/who.rs b/src/who/who.rs index 99f0cb9a016..f3b8a3b80fe 100644 --- a/src/who/who.rs +++ b/src/who/who.rs @@ -128,6 +128,8 @@ pub fn uumain(args: Vec) -> i32 { let mut assumptions = true; + #[allow(clippy::useless_let_if_seq)] + { if matches.opt_present("a") { need_boottime = true; need_deadprocs = true; @@ -202,23 +204,24 @@ pub fn uumain(args: Vec) -> i32 { disp_err!("{}", msg_wrong_number_of_arguments!()); exit!(1); } + } let mut who = Who { - do_lookup: do_lookup, - short_list: short_list, - short_output: short_output, - include_idle: include_idle, - include_heading: include_heading, - include_mesg: include_mesg, - include_exit: include_exit, - need_boottime: need_boottime, - need_deadprocs: need_deadprocs, - need_login: need_login, - need_initspawn: need_initspawn, - need_clockchange: need_clockchange, - need_runlevel: need_runlevel, - need_users: need_users, - my_line_only: my_line_only, + do_lookup, + short_list, + short_output, + include_idle, + include_heading, + include_mesg, + include_exit, + need_boottime, + need_deadprocs, + need_login, + need_initspawn, + need_clockchange, + need_runlevel, + need_users, + my_line_only, has_records: false, args: matches.free, }; @@ -311,7 +314,7 @@ impl Who { if self.short_list { let users = Utmpx::iter_all_records() .read_from(f) - .filter(|ut| ut.is_user_process()) + .filter(uucore::utmpx::Utmpx::is_user_process) .map(|ut| ut.user()) .collect::>(); println!("{}", users.join(" ")); @@ -463,7 +466,7 @@ impl Who { let mut res = ut_host.splitn(2, ':'); if let Some(h) = res.next() { if self.do_lookup { - buf.push(ut.canon_host().unwrap_or(h.to_owned())); + buf.push(ut.canon_host().unwrap_or_else(|_| h.to_owned())); } else { buf.push(h.to_owned()); } @@ -486,6 +489,7 @@ impl Who { ); } + #[allow(clippy::too_many_arguments)] fn print_line( &self, user: &str, @@ -506,10 +510,7 @@ impl Who { } buf.push_str(&format!(" {:<12}", line)); // "%Y-%m-%d %H:%M" - let mut time_size = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2; - if !self.has_records { - time_size -= 4; - } + let time_size = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2; buf.push_str(&format!(" {:<1$}", time, time_size)); if !self.short_output { diff --git a/src/whoami/platform/windows.rs b/src/whoami/platform/windows.rs index b321b93befa..d08937a6528 100644 --- a/src/whoami/platform/windows.rs +++ b/src/whoami/platform/windows.rs @@ -19,6 +19,7 @@ use self::winapi::shared::lmcons; use self::winapi::shared::minwindef; pub unsafe fn getusername() -> Result { + #[allow(deprecated)] let mut buffer: [winnt::WCHAR; lmcons::UNLEN as usize + 1] = mem::uninitialized(); let mut len = buffer.len() as minwindef::DWORD; if advapi32::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 { diff --git a/tests/common/util.rs b/tests/common/util.rs index 43e83f1e64e..abae40826a4 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -31,6 +31,22 @@ static ALREADY_RUN: &'static str = testing();"; static MULTIPLE_STDIN_MEANINGLESS: &'static str = "Ucommand is designed around a typical use case of: provide args and input stream -> spawn process -> block until completion -> return output streams. For verifying that a particular section of the input stream is what causes a particular behavior, use the Command type directly."; +/// Test if the program is running under WSL +// ref: @@ +// ToDO: test on WSL2 which likely doesn't need special handling; plan change to `is_wsl_1()` if WSL2 is less needy +pub fn is_wsl() -> bool { + #[cfg(target_os = "linux")] + { + if let Ok(b) = std::fs::read("/proc/sys/kernel/osrelease") { + if let Ok(s) = std::str::from_utf8(&b) { + let a = s.to_ascii_lowercase(); + return a.contains("microsoft") || a.contains("wsl"); + } + } + } + false +} + fn read_scenario_fixture>(tmpd: &Option>, file_rel_path: S) -> String { let tmpdir_path = tmpd.as_ref().unwrap().as_ref().path(); AtPath::new(tmpdir_path).read(file_rel_path.as_ref().to_str().unwrap()) @@ -73,7 +89,7 @@ impl CmdResult { /// 1. you can not know exactly what stdout will be /// or 2. you know that stdout will also be empty pub fn no_stderr(&self) -> Box<&CmdResult> { - assert_eq!("", self.stderr); + assert_eq!(self.stderr, ""); Box::new(self) } @@ -84,7 +100,7 @@ impl CmdResult { /// 1. you can not know exactly what stderr will be /// or 2. you know that stderr will also be empty pub fn no_stdout(&self) -> Box<&CmdResult> { - assert_eq!("", self.stdout); + assert_eq!(self.stdout, ""); Box::new(self) } @@ -93,8 +109,8 @@ impl CmdResult { /// stdout_only is a better choice unless stderr may or will be non-empty pub fn stdout_is>(&self, msg: T) -> Box<&CmdResult> { assert_eq!( - String::from(msg.as_ref()), - self.stdout + self.stdout, + String::from(msg.as_ref()) ); Box::new(self) } @@ -110,8 +126,8 @@ impl CmdResult { /// stderr_only is a better choice unless stdout may or will be non-empty pub fn stderr_is>(&self, msg: T) -> Box<&CmdResult> { assert_eq!( - String::from(msg.as_ref()).trim_end(), - self.stderr.trim_end() + self.stderr.trim_end(), + String::from(msg.as_ref()).trim_end() ); Box::new(self) } @@ -152,7 +168,7 @@ impl CmdResult { pub fn fails_silently(&self) -> Box<&CmdResult> { assert!(!self.success); - assert_eq!("", self.stderr); + assert_eq!(self.stderr, ""); Box::new(self) } } @@ -163,7 +179,7 @@ pub fn log_info, U: AsRef>(msg: T, par: U) { pub fn recursive_copy(src: &Path, dest: &Path) -> Result<()> { if fs::metadata(src)?.is_dir() { - for entry in try!(fs::read_dir(src)) { + for entry in fs::read_dir(src)? { let entry = entry?; let mut new_dest = PathBuf::from(dest); new_dest.push(entry.file_name()); diff --git a/tests/test_chgrp.rs b/tests/test_chgrp.rs index e5a974910ba..a2a2b107bfc 100644 --- a/tests/test_chgrp.rs +++ b/tests/test_chgrp.rs @@ -98,7 +98,10 @@ fn test_preserve_root_symlink() { #[test] #[cfg(target_os = "linux")] fn test_reference() { - if get_effective_gid() != 0 { + // skip for root or MS-WSL + // * MS-WSL is bugged (as of 2019-12-25), allowing non-root accounts su-level privileges for `chgrp` + // * for MS-WSL, succeeds and stdout == 'group of /etc retained as root' + if !(get_effective_gid() == 0 || is_wsl()) { new_ucmd!() .arg("-v") .arg("--reference=/etc/passwd") diff --git a/tests/test_du.rs b/tests/test_du.rs index 7ade82dd77d..d63c70cc1cc 100644 --- a/tests/test_du.rs +++ b/tests/test_du.rs @@ -47,7 +47,12 @@ fn _du_basics_subdir(s: String) { } #[cfg(not(target_os = "macos"))] fn _du_basics_subdir(s: String) { - assert_eq!(s, "8\tsubdir/deeper\n"); + // MS-WSL linux has altered expected output + if !is_wsl() { + assert_eq!(s, "8\tsubdir/deeper\n"); + } else { + assert_eq!(s, "0\tsubdir/deeper\n"); + } } #[test] @@ -81,7 +86,12 @@ fn _du_soft_link(s: String) { } #[cfg(not(target_os = "macos"))] fn _du_soft_link(s: String) { - assert_eq!(s, "16\tsubdir/links\n"); + // MS-WSL linux has altered expected output + if !is_wsl() { + assert_eq!(s, "16\tsubdir/links\n"); + } else { + assert_eq!(s, "8\tsubdir/links\n"); + } } #[test] @@ -104,7 +114,12 @@ fn _du_hard_link(s: String) { } #[cfg(not(target_os = "macos"))] fn _du_hard_link(s: String) { - assert_eq!(s, "16\tsubdir/links\n"); + // MS-WSL linux has altered expected output + if !is_wsl() { + assert_eq!(s, "16\tsubdir/links\n"); + } else { + assert_eq!(s, "8\tsubdir/links\n"); + } } #[test] @@ -123,5 +138,10 @@ fn _du_d_flag(s: String) { } #[cfg(not(target_os = "macos"))] fn _du_d_flag(s: String) { - assert_eq!(s, "28\t./subdir\n36\t./\n"); + // MS-WSL linux has altered expected output + if !is_wsl() { + assert_eq!(s, "28\t./subdir\n36\t./\n"); + } else { + assert_eq!(s, "8\t./subdir\n8\t./\n"); + } } diff --git a/tests/test_stat.rs b/tests/test_stat.rs index cac75654857..1cf33162f12 100644 --- a/tests/test_stat.rs +++ b/tests/test_stat.rs @@ -1,3 +1,5 @@ +extern crate regex; + use common::util::*; extern crate uu_stat; @@ -144,11 +146,11 @@ fn test_invalid_option() { } #[cfg(target_os = "linux")] -const NORMAL_FMTSTR: &'static str = "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %w %W %x %X %y %Y %z %Z"; +const NORMAL_FMTSTR: &'static str = "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations #[cfg(target_os = "linux")] const DEV_FMTSTR: &'static str = "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z"; #[cfg(target_os = "linux")] -const FS_FMTSTR: &'static str = "%a %b %c %d %f %i %l %n %s %S %t %T"; +const FS_FMTSTR: &'static str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions #[test] #[cfg(target_os = "linux")] @@ -171,10 +173,49 @@ fn test_fs_format() { #[test] #[cfg(target_os = "linux")] fn test_terse_normal_format() { + // note: contains birth/creation date which increases test fragility + // * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations let args = ["-t", "/"]; - new_ucmd!().args(&args) - .run() - .stdout_is(expected_result(&args)); + let actual = new_ucmd!().args(&args).run().stdout; + let expect = expected_result(&args); + println!("actual: {:?}", actual); + println!("expect: {:?}", expect); + let v_actual: Vec<&str> = actual.split(' ').collect(); + let v_expect: Vec<&str> = expect.split(' ').collect(); + // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value) + assert!(v_actual.iter().zip(v_expect.iter()).all(|(a,e)| a == e || *e == "0")); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_format_created_time() { + let args = ["-c", "%w", "/boot"]; + let actual = new_ucmd!().args(&args).run().stdout; + let expect = expected_result(&args); + println!("actual: {:?}", actual); + println!("expect: {:?}", expect); + // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences + let re = regex::Regex::new(r"\s").unwrap(); + let v_actual: Vec<&str> = re.split(&actual).collect(); + let v_expect: Vec<&str> = re.split(&expect).collect(); + // * allow for inequality if `stat` (aka, expect) returns "-" (unknown value) + assert!(v_actual.iter().zip(v_expect.iter()).all(|(a,e)| a == e || *e == "-")); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_format_created_seconds() { + let args = ["-c", "%W", "/boot"]; + let actual = new_ucmd!().args(&args).run().stdout; + let expect = expected_result(&args); + println!("actual: {:?}", actual); + println!("expect: {:?}", expect); + // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences + let re = regex::Regex::new(r"\s").unwrap(); + let v_actual: Vec<&str> = re.split(&actual).collect(); + let v_expect: Vec<&str> = re.split(&expect).collect(); + // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value) + assert!(v_actual.iter().zip(v_expect.iter()).all(|(a,e)| a == e || *e == "0")); } #[test] @@ -233,8 +274,5 @@ fn test_printf() { #[cfg(target_os = "linux")] fn expected_result(args: &[&str]) -> String { - use std::process::Command; - - let output = Command::new(util_name!()).env("LANGUAGE", "C").args(args).output().unwrap(); - String::from_utf8_lossy(&output.stdout).into_owned() + TestScenario::new(util_name!()).cmd_keepenv(util_name!()).env("LANGUAGE", "C").args(args).run().stdout } diff --git a/tests/test_who.rs b/tests/test_who.rs index 039f2e86cc3..539b3fe9cbb 100644 --- a/tests/test_who.rs +++ b/tests/test_who.rs @@ -1,7 +1,7 @@ +#[cfg(target_os = "linux")] use common::util::*; - #[cfg(target_os = "linux")] #[test] fn test_count() {