use serde::{Deserialize, Serialize};
#[derive(Debug, thiserror::Error)]
pub enum AstError {
#[error("AST error: {0}")]
Message(String),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SymbolAnchor {
pub symbol_hash: u64,
pub crate_name: String,
pub module_path: String,
pub symbol_name: String,
pub file_path: String,
pub start_line: u32,
pub end_line: u32,
pub doc_comment: Option<String>,
}
pub fn compute_symbol_hash(crate_name: &str, module_path: &str, symbol_name: &str) -> u64 {
let mut hasher = blake3::Hasher::new();
hasher.update(crate_name.as_bytes());
hasher.update(b"::");
hasher.update(module_path.as_bytes());
hasher.update(b"::");
hasher.update(symbol_name.as_bytes());
let result = hasher.finalize();
let bytes = &result.as_bytes()[0..8];
u64::from_le_bytes(bytes.try_into().unwrap())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stable_symbol_hash() {
let hash1 = compute_symbol_hash("rustbrain", "storage::engine", "CsrMatrix");
let hash2 = compute_symbol_hash("rustbrain", "storage::engine", "CsrMatrix");
assert_eq!(hash1, hash2);
assert_ne!(hash1, 0);
}
#[test]
fn hash_independent_of_path_param() {
let a = compute_symbol_hash("c", "foo::bar", "Baz");
let b = compute_symbol_hash("c", "foo::bar", "Baz");
assert_eq!(a, b);
let c = compute_symbol_hash("c", "foo::other", "Baz");
assert_ne!(a, c);
}
}