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
6include!(concat!(env!("OUT_DIR"), "/id_map_meta.rs"));
7
8use std::num::NonZeroU32;
9
10#[repr(align(4))]
11struct Data([u8; DATA_LEN]);
12
13impl Data {
14    #[inline]
15    fn game_ids(&self) -> &[u32] {
16        let ptr = self.0.as_ptr().cast::<u32>();
17        unsafe { std::slice::from_raw_parts(ptr, COUNT) }
18    }
19
20    #[inline]
21    fn ghids(&self) -> &[u32] {
22        let ptr = self.0.as_ptr().cast::<u32>();
23        unsafe { std::slice::from_raw_parts(ptr.add(COUNT), COUNT) }
24    }
25
26    #[inline]
27    fn title_offsets(&self) -> &[u32] {
28        let ptr = self.0.as_ptr().cast::<u32>();
29        unsafe { std::slice::from_raw_parts(ptr.add(COUNT * 2), COUNT + 1) }
30    }
31
32    #[inline]
33    fn titles(&self) -> &str {
34        let slice = unsafe { self.0.get_unchecked(COUNT * 12 + 4..DATA_LEN) };
35        unsafe { std::str::from_utf8_unchecked(slice) }
36    }
37}
38
39static DATA: Data = Data(*include_bytes!(concat!(env!("OUT_DIR"), "/id_map.bin")));
40
41#[derive(Debug, Clone, Copy)]
42#[repr(transparent)]
43pub struct GameEntry(usize);
44
45impl GameEntry {
46    #[inline]
47    pub fn lookup(id: impl AsRef<str>) -> Option<Self> {
48        let base36 = u32::from_str_radix(id.as_ref(), 36).ok()?;
49        DATA.game_ids().binary_search(&base36).ok().map(Self)
50    }
51
52    #[inline]
53    pub fn ghid(&self) -> Option<NonZeroU32> {
54        let ghid = unsafe { *DATA.ghids().get_unchecked(self.0) };
55        NonZeroU32::new(ghid)
56    }
57
58    #[inline]
59    pub fn title(&self) -> &'static str {
60        let start = unsafe { *DATA.title_offsets().get_unchecked(self.0) } as usize;
61        let end = unsafe { *DATA.title_offsets().get_unchecked(self.0 + 1) } as usize;
62        unsafe { DATA.titles().get_unchecked(start..end) }
63    }
64}