Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stat.rs: Refactor to remove #[allow(clippy::cognitive_complexity)] #5881 #5924

Merged
merged 5 commits into from
Feb 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 118 additions & 103 deletions src/uu/stat/src/stat.rs
Original file line number Diff line number Diff line change
@@ -404,122 +404,137 @@
}

impl Stater {
#[allow(clippy::cognitive_complexity)]
fn generate_tokens(format_str: &str, use_printf: bool) -> UResult<Vec<Token>> {
let mut tokens = Vec::new();
let bound = format_str.len();
let chars = format_str.chars().collect::<Vec<char>>();
let mut i = 0;
while i < bound {
match chars[i] {
'%' => {
let old = i;
fn handle_percent_case(
chars: &[char],
i: &mut usize,
bound: usize,
format_str: &str,
) -> UResult<Token> {
let old = *i;

*i += 1;
if *i >= bound {
return Ok(Token::Char('%'));

Check warning on line 417 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L417

Added line #L417 was not covered by tests
}
if chars[*i] == '%' {
*i += 1;
return Ok(Token::Char('%'));

Check warning on line 421 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L420-L421

Added lines #L420 - L421 were not covered by tests
}

i += 1;
if i >= bound {
tokens.push(Token::Char('%'));
continue;
}
if chars[i] == '%' {
tokens.push(Token::Char('%'));
i += 1;
continue;
}
let mut flag = Flags::default();

while *i < bound {
match chars[*i] {
'#' => flag.alter = true,
'0' => flag.zero = true,
'-' => flag.left = true,
' ' => flag.space = true,
'+' => flag.sign = true,
'\'' => flag.group = true,
'I' => unimplemented!(),

Check warning on line 434 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L433-L434

Added lines #L433 - L434 were not covered by tests
_ => break,
}
*i += 1;
}
check_bound(format_str, bound, old, *i)?;

let mut flag = Flags::default();

while i < bound {
match chars[i] {
'#' => flag.alter = true,
'0' => flag.zero = true,
'-' => flag.left = true,
' ' => flag.space = true,
'+' => flag.sign = true,
'\'' => flag.group = true,
'I' => unimplemented!(),
_ => break,
}
i += 1;
}
check_bound(format_str, bound, old, i)?;
let mut width = 0;
let mut precision = None;
let mut j = *i;

let mut width = 0;
let mut precision = None;
let mut j = i;
if let Some((field_width, offset)) = format_str[j..].scan_num::<usize>() {
width = field_width;
j += offset;
}
check_bound(format_str, bound, old, j)?;

if let Some((field_width, offset)) = format_str[j..].scan_num::<usize>() {
width = field_width;
j += offset;
}
check_bound(format_str, bound, old, j)?;

if chars[j] == '.' {
j += 1;
check_bound(format_str, bound, old, j)?;

match format_str[j..].scan_num::<i32>() {
Some((value, offset)) => {
if value >= 0 {
precision = Some(value as usize);
}
j += offset;
}
None => precision = Some(0),
}
check_bound(format_str, bound, old, j)?;
if chars[j] == '.' {
j += 1;
check_bound(format_str, bound, old, j)?;

match format_str[j..].scan_num::<i32>() {
Some((value, offset)) => {
if value >= 0 {
precision = Some(value as usize);
}
j += offset;
}
None => precision = Some(0),

Check warning on line 462 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L462

Added line #L462 was not covered by tests
}
check_bound(format_str, bound, old, j)?;
}

i = j;
tokens.push(Token::Directive {
width,
flag,
precision,
format: chars[i],
});
*i = j;
Ok(Token::Directive {
width,
flag,
precision,
format: chars[*i],
})
}

fn handle_escape_sequences(
chars: &[char],
i: &mut usize,
bound: usize,
format_str: &str,
) -> Token {
*i += 1;
if *i >= bound {
show_warning!("backslash at end of format");
return Token::Char('\\');

Check warning on line 485 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L484-L485

Added lines #L484 - L485 were not covered by tests
}
match chars[*i] {
'x' if *i + 1 < bound => {
if let Some((c, offset)) = format_str[*i + 1..].scan_char(16) {
*i += offset;
Token::Char(c)
} else {
show_warning!("unrecognized escape '\\x'");
Token::Char('x')

Check warning on line 494 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L493-L494

Added lines #L493 - L494 were not covered by tests
}
}
'0'..='7' => {
let (c, offset) = format_str[*i..].scan_char(8).unwrap();
*i += offset - 1;
Token::Char(c)
}
'"' => Token::Char('"'),
'\\' => Token::Char('\\'),
'a' => Token::Char('\x07'),
'b' => Token::Char('\x08'),
'e' => Token::Char('\x1B'),
'f' => Token::Char('\x0C'),
'n' => Token::Char('\n'),
'r' => Token::Char('\r'),
't' => Token::Char('\t'),

Check warning on line 510 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L510

Added line #L510 was not covered by tests
'v' => Token::Char('\x0B'),
c => {
show_warning!("unrecognized escape '\\{}'", c);
Token::Char(c)
}

Check warning on line 515 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L512-L515

Added lines #L512 - L515 were not covered by tests
}
}

fn generate_tokens(format_str: &str, use_printf: bool) -> UResult<Vec<Token>> {
let mut tokens = Vec::new();
let bound = format_str.len();
let chars = format_str.chars().collect::<Vec<char>>();
let mut i = 0;
while i < bound {
match chars[i] {
'%' => tokens.push(Self::handle_percent_case(
&chars, &mut i, bound, format_str,
)?),

Check warning on line 528 in src/uu/stat/src/stat.rs

Codecov / codecov/patch

src/uu/stat/src/stat.rs#L528

Added line #L528 was not covered by tests
'\\' => {
if use_printf {
i += 1;
if i >= bound {
show_warning!("backslash at end of format");
tokens.push(Token::Char('\\'));
continue;
}
match chars[i] {
'x' if i + 1 < bound => {
if let Some((c, offset)) = format_str[i + 1..].scan_char(16) {
tokens.push(Token::Char(c));
i += offset;
} else {
show_warning!("unrecognized escape '\\x'");
tokens.push(Token::Char('x'));
}
}
'0'..='7' => {
let (c, offset) = format_str[i..].scan_char(8).unwrap();
tokens.push(Token::Char(c));
i += offset - 1;
}
'"' => tokens.push(Token::Char('"')),
'\\' => tokens.push(Token::Char('\\')),
'a' => tokens.push(Token::Char('\x07')),
'b' => tokens.push(Token::Char('\x08')),
'e' => tokens.push(Token::Char('\x1B')),
'f' => tokens.push(Token::Char('\x0C')),
'n' => tokens.push(Token::Char('\n')),
'r' => tokens.push(Token::Char('\r')),
't' => tokens.push(Token::Char('\t')),
'v' => tokens.push(Token::Char('\x0B')),
c => {
show_warning!("unrecognized escape '\\{}'", c);
tokens.push(Token::Char(c));
}
}
tokens.push(Self::handle_escape_sequences(
&chars, &mut i, bound, format_str,
));
} else {
tokens.push(Token::Char('\\'));
}
}

c => tokens.push(Token::Char(c)),
}
i += 1;
Loading