use xxhash_rust::xxh32::xxh32;
pub(crate) const HASHLINE_FILE_HASH_LENGTH: usize = 4;
pub(crate) fn compute_file_hash(text: &str) -> String {
let normalized = normalize_file_hash_text(text);
let low16 = xxh32(normalized.as_bytes(), 0) & 0xffff;
format!("{low16:0HASHLINE_FILE_HASH_LENGTH$X}")
}
pub(crate) fn format_hashline_header(path: &str, tag: &str) -> String {
format!("[{path}#{tag}]")
}
pub(crate) fn format_numbered_lines(lines: &[(usize, String)]) -> Vec<String> {
lines
.iter()
.map(|(line_number, line)| format!("{line_number}:{line}"))
.collect()
}
fn normalize_file_hash_text(text: &str) -> String {
let mut output = String::with_capacity(text.len());
let bytes = text.as_bytes();
let mut start = 0usize;
for (index, byte) in bytes.iter().enumerate() {
if *byte == b'\n' {
let mut end = index;
while end > start && matches!(bytes[end - 1], b' ' | b'\t' | b'\r') {
end -= 1;
}
output.push_str(&text[start..end]);
output.push('\n');
start = index + 1;
}
}
let mut end = text.len();
while end > start && matches!(bytes[end - 1], b' ' | b'\t' | b'\r') {
end -= 1;
}
output.push_str(&text[start..end]);
output
}