diff --git a/src/lib.rs b/src/lib.rs index c51eaf3..11ea85f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use std::borrow::ToOwned; use std::io::{self, BufReader, Write}; use std::path::Path; use std::process::{Command, Stdio}; @@ -74,7 +75,7 @@ impl Context { /// Get a context structure from a provided target flag, used when cargo /// was not used to build the binary. - fn from_flag(metadata: Metadata, target_flag: Option<&str>) -> Result { + fn from_flag(metadata: &Metadata, target_flag: Option<&str>) -> Result { let host_target_name = rustc_version::version_meta()?.host; // Get the "default" target override in .cargo/config. @@ -100,7 +101,7 @@ impl Context { fn from_target_name(target_name: &str) -> Result { let cfg = Cfg::of(target_name)?; - Ok(Context { + Ok(Self { cfg, target: target_name.to_string(), }) @@ -279,13 +280,13 @@ To see all the flags the proxied tool accepts run `cargo-{} -- --help`.{}", } } -fn get_metadata(tool: &Tool, matches: &ArgMatches) -> Result { +fn get_metadata(tool: Tool, matches: &ArgMatches) -> Result { let mut metadata_command = MetadataCommand::new(); metadata_command.no_deps(); if tool.needs_build() { if let Some(features) = matches.get_many::("features") { metadata_command.features(CargoOpt::SomeFeatures( - features.map(|s| s.to_owned()).collect(), + features.map(ToOwned::to_owned).collect(), )); } if matches.get_flag("no-default-features") { @@ -306,17 +307,17 @@ fn get_metadata(tool: &Tool, matches: &ArgMatches) -> Result { Ok(metadata) } -pub fn run(tool: Tool, matches: ArgMatches) -> Result { +pub fn run(tool: Tool, matches: &ArgMatches) -> Result { let mut tool_args = vec![]; if let Some(args) = matches.get_many::("args") { - tool_args.extend(args.map(|s| s.as_str())); + tool_args.extend(args.map(String::as_str)); } let tool_help = tool_args.first() == Some(&"--help"); let target_artifact = if tool.needs_build() && !tool_help { - let metadata = get_metadata(&tool, &matches)?; - cargo_build(&matches, &metadata)?.map(|a| (a, metadata)) + let metadata = get_metadata(tool, matches)?; + cargo_build(matches, &metadata)?.map(|a| (a, metadata)) } else { None }; @@ -328,8 +329,8 @@ pub fn run(tool: Tool, matches: ArgMatches) -> Result { Context::from_artifact(metadata, artifact)? } else { Context::from_flag( - get_metadata(&tool, &matches)?, - matches.get_one::("target").map(|s| s.as_str()), + &get_metadata(tool, matches)?, + matches.get_one::("target").map(String::as_str), )? }; @@ -345,7 +346,7 @@ pub fn run(tool: Tool, matches: ArgMatches) -> Result { } // Extra flags - if let Tool::Readobj = tool { + if tool == Tool::Readobj { // The default output style of `readobj` is JSON-like, which is not user friendly, so we // change it to the human readable GNU style lltool.arg("--elf-output-style=GNU"); @@ -354,23 +355,23 @@ pub fn run(tool: Tool, matches: ArgMatches) -> Result { if tool.needs_build() { // Artifact if let Some((artifact, _)) = &target_artifact { - let file = match &artifact.executable { - // Example and bins have an executable - Some(val) => val, - // Libs have an rlib and an rmeta. We want the rlib, which always - // comes first in the filenames array after some quick testing. - // - // We could instead look for files ending in .rlib, but that would - // fail for cdylib and other fancy crate kinds. - None => &artifact.filenames[0], - }; + // Example and bins have an executable while libs have an rlib and an rmeta. We + // want the rlib, which always comes first in the filenames array after some quick + // testing. + // + // We could instead look for files ending in .rlib, but that would + // fail for cdylib and other fancy crate kinds. + let file = artifact + .executable + .as_ref() + .map_or_else(|| &artifact.filenames[0], |val| val); match tool { // Tools that don't need a build Tool::Ar | Tool::As | Tool::Cov | Tool::Lld | Tool::Profdata => {} // for some tools we change the CWD (current working directory) and // make the artifact path relative. This makes the path that the - // tool will print easier to read. e.g. `libfoo.rlib` instead of + // tool will print easier to read. eg. `libfoo.rlib` instead of // `/home/user/rust/project/target/$T/debug/libfoo.rlib`. Tool::Objdump | Tool::Nm | Tool::Readobj | Tool::Size => { lltool @@ -551,7 +552,7 @@ fn cargo_build_args<'a>(matches: &'a ArgMatches, cargo: &mut Command) -> (BuildT cargo.args(["--target", target]); } - let verbose = matches.get_count("verbose") as u64; + let verbose = u64::from(matches.get_count("verbose")); if verbose > 1 { cargo.arg(format!("-{}", "v".repeat((verbose - 1) as usize))); } diff --git a/src/postprocess.rs b/src/postprocess.rs index 89096d4..aa83afb 100644 --- a/src/postprocess.rs +++ b/src/postprocess.rs @@ -10,49 +10,49 @@ use regex::{Captures, Regex}; pub fn demangle(bytes: &[u8]) -> Cow<'_, [u8]> { let re = Regex::new(r"_Z.+?E\b").expect("BUG: Malformed Regex"); - if let Ok(text) = str::from_utf8(bytes) { - match re.replace_all(text, |cs: &Captures<'_>| { + str::from_utf8(bytes).map_or_else( + |_| bytes.into(), + |text| match re.replace_all(text, |cs: &Captures<'_>| { format!("{}", rustc_demangle::demangle(cs.get(0).unwrap().as_str())) }) { Cow::Borrowed(s) => s.as_bytes().into(), Cow::Owned(s) => s.into_bytes().into(), - } - } else { - bytes.into() - } + }, + ) } // This pass turns the addresses in the output of `size -A` into hexadecimal format pub fn size(bytes: &[u8]) -> Cow<'_, [u8]> { - if let Ok(text) = str::from_utf8(bytes) { - let mut s = text - .lines() - .map(|line| -> Cow<'_, str> { - match line - .split_whitespace() - .nth(2) - .and_then(|part| part.parse::().ok().map(|addr| (part, addr))) - { - // the lines to postprocess have the form ".section_name 100 1024" where - // the second number is the address - Some((needle, addr)) if line.starts_with('.') => { - let pos = line.rfind(needle).unwrap(); - let hex_addr = format!("{addr:#x}"); - let start = pos + needle.len() - hex_addr.len(); - - format!("{}{}", &line[..start], hex_addr).into() + str::from_utf8(bytes).map_or_else( + |_| bytes.into(), + |text| { + let mut s = text + .lines() + .map(|line| -> Cow<'_, str> { + match line + .split_whitespace() + .nth(2) + .and_then(|part| part.parse::().ok().map(|addr| (part, addr))) + { + // the lines to postprocess have the form ".section_name 100 1024" where + // the second number is the address + Some((needle, addr)) if line.starts_with('.') => { + let pos = line.rfind(needle).unwrap(); + let hex_addr = format!("{addr:#x}"); + let start = pos + needle.len() - hex_addr.len(); + + format!("{}{}", &line[..start], hex_addr).into() + } + _ => line.into(), } - _ => line.into(), - } - }) - .collect::>() - .join("\n"); - - // `text.lines()` loses the trailing newline so we restore it here - s.push('\n'); - - s.into_bytes().into() - } else { - bytes.into() - } + }) + .collect::>() + .join("\n"); + + // `text.lines()` loses the trailing newline so we restore it here + s.push('\n'); + + s.into_bytes().into() + }, + ) } diff --git a/src/tool.rs b/src/tool.rs index 4948888..276c223 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -23,25 +23,27 @@ pub enum Tool { } impl Tool { - pub fn name(self) -> &'static str { + #[must_use] + pub const fn name(self) -> &'static str { match self { - Tool::Ar => "ar", - Tool::As => "as", - Tool::Cov => "cov", - Tool::Lld => "lld", - Tool::Nm => "nm", - Tool::Objcopy => "objcopy", - Tool::Objdump => "objdump", - Tool::Profdata => "profdata", - Tool::Readobj => "readobj", - Tool::Size => "size", - Tool::Strip => "strip", + Self::Ar => "ar", + Self::As => "as", + Self::Cov => "cov", + Self::Lld => "lld", + Self::Nm => "nm", + Self::Objcopy => "objcopy", + Self::Objdump => "objdump", + Self::Profdata => "profdata", + Self::Readobj => "readobj", + Self::Size => "size", + Self::Strip => "strip", } } + #[must_use] pub fn exe(self) -> String { match self { - Tool::Lld => format!("rust-lld{EXE_SUFFIX}"), + Self::Lld => format!("rust-lld{EXE_SUFFIX}"), _ => format!("llvm-{}{}", self.name(), EXE_SUFFIX), } } @@ -71,7 +73,7 @@ impl Tool { path.to_string_lossy() ); process::exit(102) - }; + } // Note: The first argument is the name of the binary (e.g. `rust-nm`) let args = env::args().skip(1); @@ -96,7 +98,7 @@ impl Tool { pub fn cargo_exec(self, examples: Option<&str>) -> ! { let matches = crate::args(self, examples); - match crate::run(self, matches) { + match crate::run(self, &matches) { Err(e) => { eprintln!("error: {e}"); process::exit(101) @@ -106,10 +108,11 @@ impl Tool { } // Whether this tool requires the project to be previously built - pub fn needs_build(self) -> bool { + #[must_use] + pub const fn needs_build(self) -> bool { match self { - Tool::Ar | Tool::As | Tool::Cov | Tool::Lld | Tool::Profdata => false, - Tool::Nm | Tool::Objcopy | Tool::Objdump | Tool::Readobj | Tool::Size | Tool::Strip => { + Self::Ar | Self::As | Self::Cov | Self::Lld | Self::Profdata => false, + Self::Nm | Self::Objcopy | Self::Objdump | Self::Readobj | Self::Size | Self::Strip => { true } }