#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn to_snake_case(name: &str) -> String {
let chars: Vec<char> = name.chars().collect();
let mut result = String::with_capacity(name.len() + 4);
let mut prev_lower = false;
let mut prev_upper = false;
for (i, &ch) in chars.iter().enumerate() {
if ch.is_uppercase() {
let needs_separator = prev_lower || needs_acronym_break(prev_upper, &chars, i);
if needs_separator {
result.push('_');
}
result.push(ch.to_lowercase().next().unwrap_or(ch));
prev_lower = false;
prev_upper = true;
} else {
result.push(ch);
prev_lower = ch.is_alphabetic();
prev_upper = false;
}
}
result
}
fn needs_acronym_break(prev_upper: bool, chars: &[char], i: usize) -> bool {
prev_upper && chars.get(i + 1).is_some_and(|next| next.is_lowercase())
}
fn replace_filename(path: &str, new_filename: &str) -> String {
if let Some(dir_end) = path.rfind('/') {
format!("{}/{new_filename}", &path[..dir_end])
} else {
new_filename.to_string()
}
}
fn strip_part_segments(stem: &str) -> String {
let mut result = String::new();
let mut rest = stem;
while !rest.is_empty() {
if let Some(idx) = rest.find("_part_") {
result.push_str(&rest[..idx]);
let after = &rest[idx + 6..];
let digit_end = after
.find(|c: char| !c.is_ascii_digit())
.unwrap_or(after.len());
rest = &after[digit_end..];
} else {
result.push_str(rest);
break;
}
}
result
}
fn detect_parent_file(file_path: &str, index: &AgentContextIndex) -> Option<String> {
let dir = file_path.rfind('/').map(|i| &file_path[..i])?;
let mod_rs = format!("{dir}/mod.rs");
if index.file_index.contains_key(&mod_rs) {
return Some(mod_rs);
}
let stem = Path::new(file_path)
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("");
let base = strip_part_segments(stem);
if !base.is_empty() && base != stem {
let parent = format!("{dir}/{base}.rs");
if index.file_index.contains_key(&parent) {
return Some(parent);
}
}
None
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn check_collision(suggested_path: &str, index: &AgentContextIndex) -> bool {
index.file_index.contains_key(suggested_path)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn find_context_word(entries: &[&FunctionEntry]) -> Option<String> {
let mut word_counts: HashMap<String, usize> = HashMap::new();
for entry in entries {
if entry.definition_type != DefinitionType::Function {
continue;
}
for part in entry.function_name.split('_') {
let part = part.to_lowercase();
if part.len() >= 4 && !is_stopword(&part) {
*word_counts.entry(part).or_insert(0) += 1;
}
}
}
word_counts
.into_iter()
.max_by_key(|(_, count)| *count)
.map(|(word, _)| word)
}
fn longest_common_prefix(strings: &[&str]) -> String {
if strings.is_empty() {
return String::new();
}
let first: Vec<char> = strings[0].chars().collect();
let mut prefix_len = first.len();
for s in &strings[1..] {
let chars: Vec<char> = s.chars().collect();
prefix_len = prefix_len.min(chars.len());
for i in 0..prefix_len {
if first[i] != chars[i] {
prefix_len = i;
break;
}
}
}
first[..prefix_len].iter().collect()
}
fn is_stopword(word: &str) -> bool {
matches!(
word,
"this"
| "that"
| "with"
| "from"
| "have"
| "will"
| "been"
| "were"
| "they"
| "them"
| "their"
| "what"
| "when"
| "where"
| "which"
| "while"
| "into"
| "over"
| "then"
| "than"
| "also"
| "each"
| "more"
| "most"
| "only"
| "some"
| "such"
| "other"
| "self"
| "none"
| "true"
| "false"
| "returns"
| "return"
| "function"
| "should"
| "given"
| "expect"
| "verify"
| "check"
| "assert"
| "arguments"
| "correctly"
| "properly"
)
}
fn is_valid_module_name(name: &str) -> bool {
if name.is_empty() {
return false;
}
let first = name.as_bytes()[0];
let starts_valid = first.is_ascii_alphabetic() || first == b'_';
starts_valid && name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_')
}