rustbrain_core/ast/
symbol.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, thiserror::Error)]
7pub enum AstError {
8 #[error("AST error: {0}")]
10 Message(String),
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
15pub struct SymbolAnchor {
16 pub symbol_hash: u64,
18 pub crate_name: String,
20 pub module_path: String,
22 pub symbol_name: String,
24 pub file_path: String,
26 pub start_line: u32,
28 pub end_line: u32,
30 pub doc_comment: Option<String>,
32}
33
34pub fn compute_symbol_hash(crate_name: &str, module_path: &str, symbol_name: &str) -> u64 {
41 let mut hasher = blake3::Hasher::new();
42 hasher.update(crate_name.as_bytes());
43 hasher.update(b"::");
44 hasher.update(module_path.as_bytes());
45 hasher.update(b"::");
46 hasher.update(symbol_name.as_bytes());
47
48 let result = hasher.finalize();
49 let bytes = &result.as_bytes()[0..8];
50 u64::from_le_bytes(bytes.try_into().unwrap())
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn stable_symbol_hash() {
59 let hash1 = compute_symbol_hash("rustbrain", "storage::engine", "CsrMatrix");
60 let hash2 = compute_symbol_hash("rustbrain", "storage::engine", "CsrMatrix");
61 assert_eq!(hash1, hash2);
62 assert_ne!(hash1, 0);
63 }
64
65 #[test]
66 fn hash_independent_of_path_param() {
67 let a = compute_symbol_hash("c", "foo::bar", "Baz");
69 let b = compute_symbol_hash("c", "foo::bar", "Baz");
70 assert_eq!(a, b);
71 let c = compute_symbol_hash("c", "foo::other", "Baz");
72 assert_ne!(a, c);
73 }
74}