gobby_code/index/
hasher.rs1use std::path::Path;
5
6pub fn file_content_hash(path: &Path) -> anyhow::Result<String> {
8 Ok(gobby_core::indexing::file_content_hash(path)?)
9}
10
11pub fn content_hash(source: &[u8]) -> String {
13 gobby_core::indexing::content_hash(source)
14}
15
16pub fn symbol_content_hash(source: &[u8], start: usize, end: usize) -> anyhow::Result<String> {
18 let slice = source.get(start..end).ok_or_else(|| {
19 anyhow::anyhow!(
20 "invalid byte range {}..{} for source len {}",
21 start,
22 end,
23 source.len()
24 )
25 })?;
26 Ok(gobby_core::indexing::content_hash(slice))
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn file_content_hash_delegates_to_gobby_core() {
35 let tmp = tempfile::NamedTempFile::new().expect("tempfile");
36 std::fs::write(tmp.path(), b"hash me\n").expect("write file");
37
38 let actual = file_content_hash(tmp.path()).expect("hash via wrapper");
39 let expected =
40 gobby_core::indexing::file_content_hash(tmp.path()).expect("hash via gobby-core");
41 assert_eq!(actual, expected);
42
43 let source = include_str!("hasher.rs");
44 let delegate = ["gobby_core", "::indexing::file_content_hash"].concat();
45 let local_buffer = format!("let mut buf = [0u8; {}]", 64 * 1024);
46 assert!(source.contains(&delegate));
47 assert!(!source.contains(&local_buffer));
48 }
49
50 #[test]
51 fn content_hash_delegates_to_gobby_core() {
52 let source = b"hash me from memory\n";
53
54 assert_eq!(
55 content_hash(source),
56 gobby_core::indexing::content_hash(source)
57 );
58 }
59}