1use crate::constants::NULL_NAME;
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Default)]
12pub struct NameEntry {
13 pub hash: u32,
14 pub length: i32,
15 pub name: String,
16}
17
18#[derive(Debug, Clone, Default)]
25pub struct NameCache {
26 pub entries: Vec<NameEntry>,
27 pub map: HashMap<u32, i32>,
29}
30
31impl NameCache {
32 pub fn new() -> NameCache {
34 NameCache {
35 entries: Vec::new(),
36 map: HashMap::new(),
37 }
38 }
39
40 pub const NULL: u32 = NULL_NAME;
42
43 pub fn hash32(data: &[u8]) -> u32 {
45 const FNV32_OFFSET_BASIS: u32 = 0x811c_9dc5;
46 const FNV32_PRIME: u32 = 0x0100_0193;
47
48 let mut h = FNV32_OFFSET_BASIS;
49 for &b in data {
50 h ^= b as u32;
51 h = h.wrapping_mul(FNV32_PRIME);
52 }
53
54 h ^= h >> 16;
55 h = h.wrapping_mul(0x85eb_ca6b);
56 h ^= h >> 13;
57 h = h.wrapping_mul(0xc2b2_ae35);
58 h ^= h >> 16;
59 h
60 }
61
62 pub fn add_name(&mut self, name: &str) -> u32 {
65 if name.is_empty() {
66 return NULL_NAME;
67 }
68
69 let mut id = Self::hash32(name.as_bytes());
70 if id == 0 {
71 id = 1;
72 }
73
74 if let Some(&index) = self.map.get(&id) {
75 if self.entries[index as usize].name != name {
76 }
78 return id;
79 }
80
81 let index = self.entries.len() as i32;
82 self.entries.push(NameEntry {
83 hash: id,
84 length: name.len() as i32,
85 name: name.to_string(),
86 });
87 self.map.insert(id, index);
88 id
89 }
90
91 pub fn find_name(&self, id: u32) -> Option<&str> {
93 let index = *self.map.get(&id)?;
94 Some(&self.entries[index as usize].name)
95 }
96}