aboutsummaryrefslogtreecommitdiff
path: root/core/reflect/map.odin
blob: c56173074c142a1f673a6d44ee8f97d88179c240 (plain)
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
package reflect

import "core:runtime"
import "core:mem"
_ :: runtime
_ :: mem

Map_Entry_Info :: struct($Key, $Value: typeid) {
	hash:  uintptr,
	key:   Key,
	value: Value,
}

map_entry_info_slice :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V)) #no_bounds_check {
	m := m
	rm := (^mem.Raw_Map)(&m)

	info := type_info_base(type_info_of(M)).variant.(Type_Info_Map)
	gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct)
	ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array)
	entry_type := ed.elem.variant.(Type_Info_Struct)
	key_offset :=  entry_type.offsets[2]
	value_offset :=  entry_type.offsets[3]
	entry_size := uintptr(ed.elem_size)

	entries = make(type_of(entries), rm.entries.len)

	data := uintptr(rm.entries.data)
	for i in 0..<rm.entries.len {
		header := (^runtime.Map_Entry_Header)(data)

		hash  := header.hash
		key   := (^K)(data + key_offset)^
		value := (^V)(data + value_offset)^

		entries[i] = {hash, key, value}

		data += entry_size
	}

	return entries
}