Skip to main content

wowlab_engine_domain/rotation/context/
slots.rs

1//! Generic slot-offset machinery shared by the schema builder.
2
3use std::{
4    collections::HashMap,
5    hash::{BuildHasher, Hash},
6};
7
8use wowlab_buffer_contract::SLOT_ALIGNMENT;
9
10pub(super) const fn align_up(offset: usize, align: usize) -> usize {
11    if offset % align == 0 {
12        offset
13    } else {
14        offset + (align - offset % align)
15    }
16}
17
18pub(super) trait SlotKey<M> {
19    fn get_offset<'m>(map: &'m M, key: &Self) -> Option<&'m usize>;
20    fn insert_offset(map: &mut M, key: Self, value: usize);
21}
22
23impl<K, S> SlotKey<HashMap<K, usize, S>> for K
24where
25    K: Copy + Eq + Hash,
26    S: BuildHasher,
27{
28    fn get_offset<'m>(map: &'m HashMap<K, usize, S>, key: &Self) -> Option<&'m usize> {
29        map.get(key)
30    }
31
32    fn insert_offset(map: &mut HashMap<K, usize, S>, key: Self, value: usize) {
33        map.insert(key, value);
34    }
35}
36
37impl<S> SlotKey<HashMap<String, usize, S>> for &str
38where
39    S: BuildHasher,
40{
41    fn get_offset<'m>(map: &'m HashMap<String, usize, S>, key: &Self) -> Option<&'m usize> {
42        map.get(*key)
43    }
44
45    fn insert_offset(map: &mut HashMap<String, usize, S>, key: Self, value: usize) {
46        map.insert(key.to_string(), value);
47    }
48}
49
50pub(super) fn ensure_slot<K, M>(
51    map: &mut M,
52    current_offset: &mut usize,
53    size: usize,
54    key: K,
55) -> usize
56where
57    K: SlotKey<M>,
58{
59    if let Some(&base) = K::get_offset(map, &key) {
60        return base;
61    }
62
63    *current_offset = align_up(*current_offset, SLOT_ALIGNMENT);
64    let base = *current_offset;
65
66    *current_offset += size;
67    K::insert_offset(map, key, base);
68
69    base
70}