#![cfg_attr(coverage_nightly, coverage(off))]
pub(super) fn estimate_nesting_depth(source: &str) -> u32 {
let mut max_depth: u32 = 0;
let mut current_depth: u32 = 0;
for ch in source.chars() {
match ch {
'{' => {
current_depth += 1;
max_depth = max_depth.max(current_depth);
}
'}' => {
current_depth = current_depth.saturating_sub(1);
}
_ => {}
}
}
max_depth
}
#[allow(clippy::cast_possible_truncation)]
pub(super) fn count_parameters(source: &str) -> u32 {
if let Some(start) = source.find('(') {
if let Some(end) = source.get(start..).unwrap_or_default().find(')') {
let params = source.get(start..start + end).unwrap_or_default();
if params.trim() == "()" {
return 0;
}
return (params.matches(',').count() + 1) as u32;
}
}
0
}
#[allow(clippy::cast_possible_truncation)]
pub(super) fn count_unique_variables(source: &str) -> u32 {
use std::collections::HashSet;
let mut variables = HashSet::new();
for token in source.split_whitespace() {
let cleaned = token.trim_matches(|c: char| !c.is_alphanumeric() && c != '_');
if !cleaned.is_empty() {
let first_char = cleaned.chars().next().expect("checked is_empty");
if first_char.is_lowercase() || first_char == '_' {
if !is_rust_keyword(cleaned) {
variables.insert(cleaned.to_string());
}
}
}
}
variables.len() as u32
}
pub(super) fn is_rust_keyword(word: &str) -> bool {
matches!(
word,
"fn" | "let"
| "mut"
| "const"
| "static"
| "if"
| "else"
| "for"
| "while"
| "loop"
| "match"
| "return"
| "break"
| "continue"
| "pub"
| "use"
| "mod"
| "struct"
| "enum"
| "impl"
| "trait"
| "type"
| "where"
| "unsafe"
| "async"
| "await"
| "move"
| "ref"
| "in"
| "as"
| "crate"
| "super"
| "self"
| "Self"
| "true"
| "false"
)
}