Skip to content

Commit

Permalink
chore: Add indexing_slicing lint (#637)
Browse files Browse the repository at this point in the history
* chore: Add indexing_slicing lint

* Allow index slicing in tests
  • Loading branch information
sdankel authored Jun 19, 2024
1 parent d2137f9 commit 100935d
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 49 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ members = ["component", "ci/build-channel", "ci/compare-versions"]
[dev-dependencies]
chrono = "0.4.33"
strip-ansi-escapes = "0.2.0"

[lints.clippy]
indexing_slicing = "warn"
7 changes: 5 additions & 2 deletions src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ pub fn get_latest_version(name: &str) -> Result<Version> {
let response: LatestReleaseApiResponse =
serde_json::from_str(&String::from_utf8_lossy(&data))?;

let version_str = &response.tag_name["v".len()..];
let version_str = response.tag_name.trim_start_matches('v');
let version = Version::parse(version_str)?;
Ok(version)
} else {
Expand Down Expand Up @@ -333,7 +333,10 @@ fn write_response_with_progress_bar<W: Write>(
if bytes_read == 0 {
break;
}
if let Err(e) = writer.write_all(&buffer[..bytes_read]) {
let buf = buffer
.get(..bytes_read)
.ok_or_else(|| anyhow!("Failed to read buffer"))?;
if let Err(e) = writer.write_all(buf) {
log_progress_bar(&progress_bar);
if target.is_empty() {
bail!("Something went wrong writing data: {}", e)
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(test, allow(clippy::indexing_slicing))]

pub mod channel;
pub mod commands;
pub mod config;
Expand Down
7 changes: 5 additions & 2 deletions src/ops/fuelup_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
toolchain::{DistToolchainDescription, Toolchain},
};
use ansiterm::Color;
use anyhow::Result;
use anyhow::{anyhow, Result};
use component::{self, Components};
use semver::Version;
use std::collections::HashMap;
Expand Down Expand Up @@ -114,7 +114,10 @@ fn check_toolchain(toolchain: &str, verbose: bool) -> Result<()> {

if !plugin.is_main_executable() {
print!("{:>2}", "");
plugin_name = &plugin.executables[index];
plugin_name = plugin
.executables
.get(index)
.ok_or_else(|| anyhow!("Plugin name not found"))?;
}

let maybe_latest_version = plugin.publish.map_or_else(
Expand Down
6 changes: 3 additions & 3 deletions src/proxy_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ pub fn proxy_run(arg0: &str) -> Result<ExitCode> {
let cmd_args: Vec<_> = env::args_os().skip(1).collect();
let toolchain = Toolchain::from_settings()?;

if !cmd_args.is_empty() {
let plugin = format!("{}-{}", arg0, &cmd_args[0].to_string_lossy());
if let Some(first_arg) = cmd_args.first() {
let plugin = format!("{}-{}", arg0, first_arg.to_string_lossy());
if Components::collect_plugin_executables()?.contains(&plugin) {
direct_proxy(&plugin, &cmd_args[1..], &toolchain)?;
direct_proxy(&plugin, cmd_args.get(1..).unwrap_or_default(), &toolchain)?;
}
}

Expand Down
164 changes: 122 additions & 42 deletions src/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,23 @@ fn consume_back<T>(parts: &mut VecDeque<T>, number: usize) {
}
}

/// Attempts to parse a date from the front of the parts list, returning the date and consuming the
/// date parts if they are available
/// Attempts to parse a date from the end of the parts list, returning the date and consuming the
/// date parts if they are available.
fn extract_date(parts: &mut VecDeque<&str>) -> Option<Date> {
let len = parts.len();
if len < 3 {
return None;
}

let date_str = format!("{}-{}-{}", parts[len - 3], parts[len - 2], parts[len - 1]);
let date_str = parts
.iter()
.rev()
.take(3)
.cloned()
.rev()
.collect::<Vec<&str>>()
.join("-");

match Date::parse(&date_str, DATE_FORMAT) {
Ok(d) => {
consume_back(parts, 3);
Expand All @@ -122,41 +130,33 @@ fn extract_date(parts: &mut VecDeque<&str>) -> Option<Date> {
}
}

/// Attemps to parse the target from a vector of parts, returning the target and consuming the
/// target parts if they are available
/// Attempts to parse the target from the end of the parts list, returning the target and consuming the
/// target parts if they are available.
fn extract_target(parts: &mut VecDeque<&str>) -> Option<TargetTriple> {
if parts.len() < 3 {
return None;
}

let len = parts.len();
let target_str = format!("{}-{}-{}", parts[len - 3], parts[len - 2], parts[len - 1]);
match TargetTriple::new(&target_str) {
Ok(t) => {
consume_back(parts, 3);
Some(t)
fn try_extract(parts: &mut VecDeque<&str>, count: usize) -> Option<TargetTriple> {
if parts.len() < count {
return None;
}
Err(_) => {
if parts.len() < 4 {
return None;
}

let target_str = format!(
"{}-{}-{}-{}",
parts[len - 4],
parts[len - 3],
parts[len - 2],
parts[len - 1]
);
match TargetTriple::new(&target_str) {
Ok(t) => {
consume_back(parts, 4);
Some(t)
}
Err(_) => None,
let target_str: String = parts
.iter()
.rev()
.take(count)
.cloned()
.rev()
.collect::<Vec<&str>>()
.join("-");

match TargetTriple::new(&target_str) {
Ok(t) => {
consume_back(parts, count);
Some(t)
}
Err(_) => None,
}
}

try_extract(parts, 3).or_else(|| try_extract(parts, 4))
}

/// Parses a distributable toolchain description from a string.
Expand All @@ -177,12 +177,16 @@ impl FromStr for DistToolchainDescription {
}

let mut parts = s.split('-').collect::<VecDeque<_>>();

match parts.len() {
1 => Ok(Self {
name: DistToolchainName::from_str(parts[0])?,
target: TargetTriple::from_host().ok(),
date: None,
}),
1 => {
let first_part = *parts.front().unwrap_or(&"");
Ok(Self {
name: DistToolchainName::from_str(first_part)?,
target: TargetTriple::from_host().ok(),
date: None,
})
}
_ => {
let date = extract_date(&mut parts);
let target = extract_target(&mut parts);
Expand Down Expand Up @@ -420,11 +424,13 @@ impl Toolchain {

Ok(())
}
fn remove_executables(&self, component: &str) -> Result<()> {
let executables = &Components::collect().unwrap().component[component].executables;
for executable in executables {
remove_file(self.bin_path.join(executable))
.with_context(|| format!("failed to remove executable '{executable}'"))?;
fn remove_executables(&self, component_name: &str) -> Result<()> {
let components = Components::collect()?;
if let Some(component) = components.component.get(component_name) {
for executable in &component.executables {
remove_file(self.bin_path.join(executable))
.with_context(|| format!("failed to remove executable '{executable}'"))?;
}
}
Ok(())
}
Expand Down Expand Up @@ -673,4 +679,78 @@ mod tests {
DistToolchainDescription::from_str(channel).expect_err("invalid channel");
}
}

#[test]
fn test_extract_target_with_three_parts() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["aarch64", "apple", "darwin"]);
let target = extract_target(&mut parts).expect("target triple");
assert_eq!(target.to_string(), "aarch64-apple-darwin");
assert!(parts.is_empty()); // Ensure parts are consumed
}

#[test]
fn test_extract_target_with_four_parts() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["x86_64", "unknown", "linux", "gnu"]);
let target = extract_target(&mut parts).expect("target triple");
assert_eq!(target.to_string(), "x86_64-unknown-linux-gnu");
assert!(parts.is_empty()); // Ensure parts are consumed
}

#[test]
fn test_extract_target_with_five_parts() {
let mut parts: VecDeque<&str> =
VecDeque::from(vec!["my", "custom", "aarch64", "apple", "darwin"]);
let target = extract_target(&mut parts).expect("target triple");
assert_eq!(target.to_string(), "aarch64-apple-darwin");
assert_eq!(parts.len(), 2); // Ensure 3 parts were consumed
}

#[test]
fn test_extract_target_with_insufficient_parts() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["apple", "darwin"]);
assert!(extract_target(&mut parts).is_none());
assert_eq!(parts.len(), 2); // Ensure parts are not consumed
}

#[test]
fn test_extract_target_with_invalid_target() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["invalid", "target", "string"]);
assert!(extract_target(&mut parts).is_none());
assert_eq!(parts.len(), 3); // Ensure parts are not consumed

let mut parts: VecDeque<&str> =
VecDeque::from(vec!["still", "invalid", "target", "string"]);
assert!(extract_target(&mut parts).is_none());
assert_eq!(parts.len(), 4); // Ensure parts are not consumed
}

#[test]
fn test_extract_date_with_valid_date() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["2022", "12", "25"]);
let date = extract_date(&mut parts).expect("date");
assert_eq!(date.to_string(), "2022-12-25");
assert!(parts.is_empty()); // Ensure all parts are consumed
}

#[test]
fn test_extract_date_with_insufficient_parts() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["2022", "12"]);
assert!(extract_date(&mut parts).is_none());
assert_eq!(parts.len(), 2); // Ensure parts are not consumed
}

#[test]
fn test_extract_date_with_invalid_date() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["12", "25", "2022"]);
assert!(extract_date(&mut parts).is_none());
assert_eq!(parts.len(), 3); // Ensure parts are not consumed
}

#[test]
fn test_extract_date_with_extra_parts() {
let mut parts: VecDeque<&str> = VecDeque::from(vec!["extra", "2022", "12", "25"]);
let date = extract_date(&mut parts).expect("date");
assert_eq!(date.to_string(), "2022-12-25");
assert_eq!(parts.len(), 1); // Ensure only the date parts are consumed
}
}
1 change: 1 addition & 0 deletions src/toolchain_override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl ToolchainOverride {
Ok(Self { cfg, path })
}

#[allow(clippy::indexing_slicing)]
pub fn to_toml(&self) -> Document {
let mut document = toml_edit::Document::new();

Expand Down

0 comments on commit 100935d

Please sign in to comment.