1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(const_if_match, const_loop, track_caller, proc_macro_hygiene)]
#![feature(asm)]
#![feature(unwind_attributes)]
#![feature(associated_type_bounds)]
#![feature(simd_ffi)] // lol sorry jam

pub mod crc32;

pub mod params;

#[cfg(feature = "std")]
pub mod resource;

#[doc(hidden)]
pub mod cpp;

#[doc(hidden)]
pub mod common;

#[doc(inline)]
pub use common::root::*;

#[doc(inline)]
pub use cpp::root::*;

// Find the hash40 of a given string
pub const fn hash40(string: &str) -> u64 {
    let bytes = string.as_bytes();

    ((bytes.len() as u64) << 32) + crc32::crc32(bytes) as u64
}

impl phx::Hash40 {
    pub fn new(string: &str) -> Self {
        Self {
            hash: hash40(string),
        }
    }

    pub fn new_raw(raw: u64) -> Self {
        Self { hash: raw }
    }
}

mod lua_const;

#[repr(C)]
pub struct CppHash40MapEntry<T> {
    pub next: *mut Self,
    pub key: phx::Hash40,
    pub also_key: phx::Hash40,
    pub value: T
}

#[repr(C)]
#[derive(Debug, Copy, Clone)] // really bad, don't do this :P
pub struct CppHash40Map<T: Sized> {
    pub buckets: *const *mut CppHash40MapEntry<T>,
    pub bucket_count: u64
}

impl<T: Sized> CppHash40Map<T> {
    pub fn get<'a>(&'a self, key: &phx::Hash40) -> Option<&'a T> {
        let bucket_idx = key.hash % self.bucket_count;
        if !self.buckets.is_null() {
            unsafe {
                let mut current = *self.buckets.add(bucket_idx as usize);
                if !current.is_null() {
                    current = (*current).next;
                    while !current.is_null() {
                        let current_key = (*current).key;
                        if current_key != *key && (current_key.hash % self.bucket_count) != bucket_idx {
                            break;
                        }
                        if current_key == *key && (*current).also_key == *key {
                            return Some(&(*current).value);
                        }
                        current = (*current).next;
                    }
                }
                None
            }
        } else {
            None
        }
    }

    pub fn get_mut(&mut self, key: &phx::Hash40) -> Option<&mut T> {
        let bucket_idx = key.hash % self.bucket_count;
        if !self.buckets.is_null() {
            unsafe {
                let mut current = *self.buckets.add(bucket_idx as usize);
                if !current.is_null() {
                    current = (*current).next;
                    while !current.is_null() {
                        let current_key = (*current).key;
                        if current_key != *key && (current_key.hash % self.bucket_count) != bucket_idx {
                            break;
                        }
                        if current_key == *key && (*current).also_key == *key {
                            return Some(&mut (*current).value);
                        }
                        current = (*current).next;
                    }
                }
                None
            }
        } else {
            None
        }
    }
}