refactor: adopted idiomatic combinators and updated the rust toolchain
- Updated the nightly rust toolchain channel in rust-toolchain.toml to nightly-2026-07-28. - Adopted slice chunking and multiple-of helper methods across native and vendor crates. - Replaced option map adapters and conditional patterns with idiomatic combinators.
This commit is contained in:
@@ -200,7 +200,7 @@ fn quote_bare_metavars(pattern: &str) -> String {
|
||||
}
|
||||
|
||||
/// Byte index of the end of the UTF-8 character starting at `index`.
|
||||
fn next_char_boundary(bytes: &[u8], index: usize) -> usize {
|
||||
const fn next_char_boundary(bytes: &[u8], index: usize) -> usize {
|
||||
let mut end = index + 1;
|
||||
while end < bytes.len() && (bytes[end] & 0b1100_0000) == 0b1000_0000 {
|
||||
end += 1;
|
||||
|
||||
@@ -814,7 +814,7 @@ pub(crate) struct GrepConfig {
|
||||
/// Check if `bytes[start]` (which must be `b'{'`) begins a valid repetition
|
||||
/// quantifier: `{N}`, `{N,}`, or `{N,M}` where N and M are decimal digits.
|
||||
/// Returns the byte index of the closing `}` if valid.
|
||||
fn find_valid_repetition(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
const fn find_valid_repetition(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
let len = bytes.len();
|
||||
let mut i = start + 1;
|
||||
// Must start with at least one digit.
|
||||
@@ -847,7 +847,7 @@ fn find_valid_repetition(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
fn find_braced_escape_end(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
const fn find_braced_escape_end(bytes: &[u8], start: usize) -> Option<usize> {
|
||||
let mut i = start + 1;
|
||||
while i < bytes.len() {
|
||||
if bytes[i] == b'}' {
|
||||
|
||||
@@ -323,9 +323,7 @@ pub fn matches_kitty_sequence(
|
||||
&& base == expected_codepoint
|
||||
{
|
||||
let cp = parsed.codepoint;
|
||||
let is_ascii_letter = u8::try_from(cp)
|
||||
.ok()
|
||||
.is_some_and(|b| b.is_ascii_alphabetic());
|
||||
let is_ascii_letter = u8::try_from(cp).is_ok_and(|b| b.is_ascii_alphabetic());
|
||||
let is_known_symbol = is_symbol_key(cp);
|
||||
if !is_ascii_letter && !is_known_symbol {
|
||||
return true;
|
||||
@@ -637,9 +635,7 @@ fn matches_key_inner(bytes: &[u8], key_id: &str, kitty_protocol_active: bool) ->
|
||||
if let Some(base) = parsed_base
|
||||
&& base == codepoint
|
||||
{
|
||||
let is_ascii_letter = u8::try_from(parsed_codepoint)
|
||||
.ok()
|
||||
.is_some_and(|b| b.is_ascii_alphabetic());
|
||||
let is_ascii_letter = u8::try_from(parsed_codepoint).is_ok_and(|b| b.is_ascii_alphabetic());
|
||||
let is_known_symbol = is_symbol_key(parsed_codepoint);
|
||||
if !is_ascii_letter && !is_known_symbol {
|
||||
return true;
|
||||
@@ -1389,9 +1385,7 @@ fn format_kitty_key(parsed: &ParsedKittySequence) -> Option<Cow<'static, str>> {
|
||||
text_codepoint
|
||||
} else {
|
||||
let cp = parsed.codepoint;
|
||||
let is_ascii_letter = u8::try_from(cp)
|
||||
.ok()
|
||||
.is_some_and(|b| b.is_ascii_alphabetic());
|
||||
let is_ascii_letter = u8::try_from(cp).is_ok_and(|b| b.is_ascii_alphabetic());
|
||||
let is_known_symbol = is_symbol_key(cp);
|
||||
if is_ascii_letter || is_known_symbol {
|
||||
cp
|
||||
|
||||
@@ -410,7 +410,7 @@ fn fill_repeat_bands_rgb(pixels: &mut [u8], width: usize, height: usize, grid: &
|
||||
for copy in 1..grid.repeat {
|
||||
let band_top = (row * grid.repeat + copy) * grid.cell_h;
|
||||
for y in band_top..(band_top + grid.cell_h).min(height) {
|
||||
for px in pixels[y * width * 3..(y + 1) * width * 3].chunks_exact_mut(3) {
|
||||
for px in pixels[y * width * 3..(y + 1) * width * 3].as_chunks_mut::<3>().0 {
|
||||
px.copy_from_slice(&band);
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1302,7 @@ fn render_snapcompact_png_sync(
|
||||
render_bitmap(&text, src_w, src_h, font, &native, black_ink)
|
||||
};
|
||||
let mut rgb = vec![0f32; src_w * src_h * 3];
|
||||
for (dst, &idx) in rgb.chunks_exact_mut(3).zip(&indexed) {
|
||||
for (dst, &idx) in rgb.as_chunks_mut::<3>().0.iter_mut().zip(&indexed) {
|
||||
let [r, g, b] = PALETTE[idx as usize];
|
||||
dst[0] = f32::from(r);
|
||||
dst[1] = f32::from(g);
|
||||
|
||||
@@ -405,7 +405,7 @@ fn ansi_seq_len_u16(data: &[u16], pos: usize) -> Option<usize> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_sgr_u16(seq: &[u16]) -> bool {
|
||||
const fn is_sgr_u16(seq: &[u16]) -> bool {
|
||||
seq.len() >= 3 && seq[1] == b'[' as u16 && *seq.last().unwrap() == b'm' as u16
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +745,7 @@ mod tests {
|
||||
// Two separate groups, not merged
|
||||
let unused_pos = out.find("unused_variables").unwrap();
|
||||
let clone_pos = out.find("clippy::redundant_clone").unwrap();
|
||||
assert!(unused_pos != clone_pos);
|
||||
assert_ne!(unused_pos, clone_pos);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -315,12 +315,12 @@ fn summarize_golangci_json(line: &str) -> Option<String> {
|
||||
.get("Pos")
|
||||
.and_then(|pos| pos.get("Line"))
|
||||
.and_then(serde_json::Value::as_u64)
|
||||
.map_or(0, |value| value);
|
||||
.unwrap_or(0);
|
||||
let col_no = issue
|
||||
.get("Pos")
|
||||
.and_then(|pos| pos.get("Column"))
|
||||
.and_then(serde_json::Value::as_u64)
|
||||
.map_or(0, |value| value);
|
||||
.unwrap_or(0);
|
||||
let linter = issue
|
||||
.get("FromLinter")
|
||||
.and_then(|v| v.as_str())
|
||||
|
||||
+1
-1
@@ -189,7 +189,7 @@ impl CommonCompleteCommandArgs {
|
||||
actions
|
||||
}
|
||||
|
||||
fn has_completion_spec(&self) -> bool {
|
||||
const fn has_completion_spec(&self) -> bool {
|
||||
!self.options.is_empty()
|
||||
|| !self.actions.is_empty()
|
||||
|| self.glob_pattern.is_some()
|
||||
|
||||
+6
-9
@@ -200,15 +200,12 @@ fn expand_history_args(
|
||||
let mut result = ExecutionResult::success();
|
||||
|
||||
for arg in args {
|
||||
match expand_history_arg(history, arg) {
|
||||
Ok(expanded) => {
|
||||
writeln!(stdout, "{expanded}")?;
|
||||
},
|
||||
Err(()) => {
|
||||
writeln!(stderr, "history: {arg}: history expansion failed")?;
|
||||
result = ExecutionResult::general_error();
|
||||
},
|
||||
}
|
||||
if let Ok(expanded) = expand_history_arg(history, arg) {
|
||||
writeln!(stdout, "{expanded}")?;
|
||||
} else {
|
||||
writeln!(stderr, "history: {arg}: history expansion failed")?;
|
||||
result = ExecutionResult::general_error();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ impl MapFileCommand {
|
||||
let array_index = self.origin.unwrap_or(0) + i64::try_from(entry_count)?;
|
||||
|
||||
if let Some(callback) = &self.callback
|
||||
&& (entry_count + 1) % callback_group_size == 0
|
||||
&& (entry_count + 1).is_multiple_of(callback_group_size)
|
||||
{
|
||||
let result = run_callback(callback, array_index, &line_str, context).await?;
|
||||
if !result.is_normal_flow() {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ impl TrapCommand {
|
||||
signal_type: TrapSignal,
|
||||
) -> Result<(), brush_core::Error> {
|
||||
if let Some(handler) = context.shell.traps().get_handler(signal_type) {
|
||||
writeln!(context.stdout(), "trap -- '{}' {signal_type}", &handler.command)?;
|
||||
writeln!(context.stdout(), "trap -- '{}' {signal_type}", handler.command)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
fn parse(mode: &str, current_umask: u32) -> u32 {
|
||||
parse_symbolic_umask(mode, current_umask).unwrap() as u32
|
||||
u32::from(parse_symbolic_umask(mode, current_umask).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+1
-1
@@ -1018,7 +1018,7 @@ pub enum ChildSessionAction {
|
||||
/// `child_stdin_is_terminal` arm before pipeline membership would ever matter.
|
||||
///
|
||||
/// Foregrounding remains gated on `new_pg && child_stdin_is_terminal`.
|
||||
pub fn child_session_action(
|
||||
pub const fn child_session_action(
|
||||
new_pg: bool,
|
||||
child_stdin_is_terminal: bool,
|
||||
_in_pipeline_group: bool,
|
||||
|
||||
+2
-3
@@ -1286,10 +1286,9 @@ fn try_get_variable_completions(
|
||||
return None;
|
||||
}
|
||||
(prefix, true)
|
||||
} else if let Some(prefix) = token.strip_prefix('$') {
|
||||
(prefix, false)
|
||||
} else {
|
||||
return None;
|
||||
let prefix = token.strip_prefix('$')?;
|
||||
(prefix, false)
|
||||
};
|
||||
|
||||
// If there's a path separator, this is a path like $HOME/foo, not a variable to
|
||||
|
||||
+2
-3
@@ -465,7 +465,8 @@ impl<'a> Iterator for Search<'a> {
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if let Some(index) = self.next_index {
|
||||
{
|
||||
let index = self.next_index?;
|
||||
// Make sure we haven't hit the end of the history.
|
||||
if index >= self.history.items.len() {
|
||||
return None;
|
||||
@@ -494,8 +495,6 @@ impl<'a> Iterator for Search<'a> {
|
||||
return Some(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -133,7 +133,7 @@ impl ExecutionParameters {
|
||||
}
|
||||
|
||||
/// Disables external-command output marking for this execution branch.
|
||||
pub fn disable_command_output_marking(&mut self) {
|
||||
pub const fn disable_command_output_marking(&mut self) {
|
||||
self.command_output_disabled = true;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1181,7 @@ impl Execute for ast::CaseClauseCommand {
|
||||
// switched on, but that's not it.
|
||||
if shell.options().print_commands_and_arguments {
|
||||
shell
|
||||
.trace_command(params, std::format!("case {} in", &self.value))
|
||||
.trace_command(params, std::format!("case {} in", self.value))
|
||||
.await;
|
||||
}
|
||||
|
||||
|
||||
+40
-40
@@ -5,8 +5,8 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
/// Normalizes shell-facing path aliases before std::fs sees them.
|
||||
pub fn normalize_shell_path(path: &Path) -> Cow<'_, Path> {
|
||||
/// Normalizes shell-facing path aliases before `std::fs` sees them.
|
||||
pub const fn normalize_shell_path(path: &Path) -> Cow<'_, Path> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
translate_unix_drive_path(path).map_or(Cow::Borrowed(path), Cow::Owned)
|
||||
@@ -18,7 +18,7 @@ pub fn normalize_shell_path(path: &Path) -> Cow<'_, Path> {
|
||||
}
|
||||
|
||||
/// Returns a Windows drive root for a shell pattern that starts with an MSYS/WSL drive alias.
|
||||
pub fn pattern_drive_alias_root(
|
||||
pub const fn pattern_drive_alias_root(
|
||||
starts_with_forward_slash: bool,
|
||||
first: &str,
|
||||
second: Option<&str>,
|
||||
@@ -72,7 +72,7 @@ fn drive_root_path(drive: u8) -> PathBuf {
|
||||
}
|
||||
|
||||
#[cfg(any(windows, test))]
|
||||
fn is_ascii_drive_component(value: &str) -> bool {
|
||||
const fn is_ascii_drive_component(value: &str) -> bool {
|
||||
value.len() == 1 && value.as_bytes()[0].is_ascii_alphabetic()
|
||||
}
|
||||
|
||||
@@ -122,6 +122,42 @@ const fn is_path_separator(byte: u8) -> bool {
|
||||
byte == b'/' || byte == b'\\'
|
||||
}
|
||||
|
||||
pub use super::platform::fs::*;
|
||||
|
||||
/// Extension trait for path-related filesystem operations.
|
||||
pub trait PathExt {
|
||||
/// Returns true if the path exists and is readable by the current user.
|
||||
fn readable(&self) -> bool;
|
||||
/// Returns true if the path exists and is writable by the current user.
|
||||
fn writable(&self) -> bool;
|
||||
/// Returns true if the path exists and is executable by the current user.
|
||||
///
|
||||
/// On Windows, this returns true if *either* the path itself is a file with
|
||||
/// a `PATHEXT` extension *or* appending some `PATHEXT` extension resolves
|
||||
/// to an existing file. To recover the actual on-disk path in the
|
||||
/// latter case, use [`resolve_executable`] which takes ownership
|
||||
/// and avoids copies on platforms where no resolution is needed.
|
||||
fn executable(&self) -> bool;
|
||||
|
||||
/// Returns true if the path exists and is a block device.
|
||||
fn exists_and_is_block_device(&self) -> bool;
|
||||
/// Returns true if the path exists and is a character device.
|
||||
fn exists_and_is_char_device(&self) -> bool;
|
||||
/// Returns true if the path exists and is a FIFO (named pipe).
|
||||
fn exists_and_is_fifo(&self) -> bool;
|
||||
/// Returns true if the path exists and is a socket.
|
||||
fn exists_and_is_socket(&self) -> bool;
|
||||
/// Returns true if the path exists and has the setgid bit set.
|
||||
fn exists_and_is_setgid(&self) -> bool;
|
||||
/// Returns true if the path exists and has the setuid bit set.
|
||||
fn exists_and_is_setuid(&self) -> bool;
|
||||
/// Returns true if the path exists and has the sticky bit set.
|
||||
fn exists_and_is_sticky_bit(&self) -> bool;
|
||||
|
||||
/// Returns the device ID and inode number for the path.
|
||||
fn get_device_and_inode(&self) -> Result<(u64, u64), crate::error::Error>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -183,39 +219,3 @@ mod tests {
|
||||
assert_eq!(translate_unix_drive_path(Path::new("\\mnt\\d\\logs")).as_deref(), None);
|
||||
}
|
||||
}
|
||||
|
||||
pub use super::platform::fs::*;
|
||||
|
||||
/// Extension trait for path-related filesystem operations.
|
||||
pub trait PathExt {
|
||||
/// Returns true if the path exists and is readable by the current user.
|
||||
fn readable(&self) -> bool;
|
||||
/// Returns true if the path exists and is writable by the current user.
|
||||
fn writable(&self) -> bool;
|
||||
/// Returns true if the path exists and is executable by the current user.
|
||||
///
|
||||
/// On Windows, this returns true if *either* the path itself is a file with
|
||||
/// a `PATHEXT` extension *or* appending some `PATHEXT` extension resolves
|
||||
/// to an existing file. To recover the actual on-disk path in the
|
||||
/// latter case, use [`resolve_executable`] which takes ownership
|
||||
/// and avoids copies on platforms where no resolution is needed.
|
||||
fn executable(&self) -> bool;
|
||||
|
||||
/// Returns true if the path exists and is a block device.
|
||||
fn exists_and_is_block_device(&self) -> bool;
|
||||
/// Returns true if the path exists and is a character device.
|
||||
fn exists_and_is_char_device(&self) -> bool;
|
||||
/// Returns true if the path exists and is a FIFO (named pipe).
|
||||
fn exists_and_is_fifo(&self) -> bool;
|
||||
/// Returns true if the path exists and is a socket.
|
||||
fn exists_and_is_socket(&self) -> bool;
|
||||
/// Returns true if the path exists and has the setgid bit set.
|
||||
fn exists_and_is_setgid(&self) -> bool;
|
||||
/// Returns true if the path exists and has the setuid bit set.
|
||||
fn exists_and_is_setuid(&self) -> bool;
|
||||
/// Returns true if the path exists and has the sticky bit set.
|
||||
fn exists_and_is_sticky_bit(&self) -> bool;
|
||||
|
||||
/// Returns the device ID and inode number for the path.
|
||||
fn get_device_and_inode(&self) -> Result<(u64, u64), crate::error::Error>;
|
||||
}
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ impl Matcher for MultiExecMatcher {
|
||||
writeln!(
|
||||
&mut stderr(),
|
||||
"Cannot fit a single argument {}: {}",
|
||||
&path_to_file.to_string_lossy(),
|
||||
path_to_file.to_string_lossy(),
|
||||
e
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2026-04-29"
|
||||
channel = "nightly-2026-07-28"
|
||||
components = ["rustfmt", "clippy", "rust-analyzer"]
|
||||
targets = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
|
||||
|
||||
Reference in New Issue
Block a user