wowlab_engine_domain/rotation/context/
slots.rs1use 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}