Skip to main content

luaur_bytecode/records/
string_ref.rs

1use core::hash::{Hash, Hasher};
2
3#[derive(Debug, Clone, Copy, Default)]
4pub struct StringRef {
5    pub(crate) data: *const i8,
6    pub(crate) length: usize,
7}
8
9impl StringRef {
10    pub fn new(data: *const i8, length: usize) -> Self {
11        Self { data, length }
12    }
13
14    #[inline]
15    fn as_bytes(&self) -> &[u8] {
16        if self.data.is_null() {
17            &[]
18        } else {
19            unsafe { core::slice::from_raw_parts(self.data as *const u8, self.length) }
20        }
21    }
22}
23
24// C++ `BytecodeBuilder::StringRef::operator==`:
25//   (data && other.data) ? (length == other.length && memcmp(...) == 0) : (data == other.data)
26// i.e. content comparison when both pointers are non-null, otherwise raw-pointer
27// equality (so the DenseHashMap's {null, 0} empty-key sentinel still matches itself).
28// The derived impl compared the raw pointer, so the same string reached via two
29// different buffers (e.g. an AstName key vs a string-literal key, both "f") failed to
30// dedup and produced duplicate string-table / constant entries.
31impl PartialEq for StringRef {
32    fn eq(&self, other: &Self) -> bool {
33        if !self.data.is_null() && !other.data.is_null() {
34            self.length == other.length && self.as_bytes() == other.as_bytes()
35        } else {
36            self.data == other.data
37        }
38    }
39}
40
41impl Eq for StringRef {}
42
43// C++ `StringRefHash` hashes the content range (`hashRange(data, length)`); equal
44// content must hash equally for the dedup map.
45impl Hash for StringRef {
46    fn hash<H: Hasher>(&self, state: &mut H) {
47        self.as_bytes().hash(state);
48    }
49}