Skip to main content

twbm_idmap/
lib.rs

1// SPDX-FileCopyrightText: 2026 Manuel Quarneti <mq1@ik.me>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4#![warn(clippy::all, rust_2018_idioms)]
5
6use std::num::NonZero;
7
8include!(concat!(env!("OUT_DIR"), "/id_map_meta.rs"));
9
10#[repr(C)]
11struct Data {
12    pub game_ids: [u32; COUNT],
13    pub ghids: [Option<NonZero<u32>>; COUNT],
14    pub title_offsets: [u32; COUNT + 1],
15    pub titles: [u8; TITLES_LEN],
16}
17
18#[cfg(not(feature = "compress"))]
19static DATA: Data = {
20    let bytes = *include_bytes!(concat!(env!("OUT_DIR"), "/id_map.bin"));
21    unsafe { std::mem::transmute(bytes) }
22};
23
24#[cfg(feature = "compress")]
25static DATA: std::sync::LazyLock<Box<Data>> = std::sync::LazyLock::new(|| {
26    let compressed = include_bytes!(concat!(env!("OUT_DIR"), "/id_map.bin"));
27
28    let mut buf = Box::<Data>::new_uninit();
29
30    // inflate
31    let ptr = buf.as_mut_ptr().cast::<u8>();
32    let slice = unsafe { std::slice::from_raw_parts_mut(ptr, std::mem::size_of::<Data>()) };
33    let it = std::iter::once(compressed.as_slice());
34    miniz_oxide::inflate::decompress_slice_iter_to_slice(slice, it, false, true).unwrap();
35
36    unsafe { buf.assume_init() }
37});
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40#[repr(transparent)]
41pub struct GameEntry(usize);
42
43impl GameEntry {
44    #[inline]
45    pub fn lookup(id: impl AsRef<str>) -> Option<Self> {
46        let id = u32::from_str_radix(id.as_ref(), 36).ok()?;
47        DATA.game_ids.binary_search(&id).ok().map(Self)
48    }
49
50    #[inline]
51    pub fn ghid(&self) -> Option<NonZero<u32>> {
52        unsafe { *DATA.ghids.get_unchecked(self.0) }
53    }
54
55    #[inline]
56    pub fn title(&self) -> &'static str {
57        let start = unsafe { *DATA.title_offsets.get_unchecked(self.0) } as usize;
58        let end = unsafe { *DATA.title_offsets.get_unchecked(self.0 + 1) } as usize;
59        let slice = unsafe { DATA.titles.get_unchecked(start..end) };
60
61        unsafe { std::str::from_utf8_unchecked(slice) }
62    }
63}