1
1
use once_cell:: sync:: Lazy ;
2
- use rustc_hash:: FxHashMap ;
2
+ use rustc_hash:: { FxHashMap , FxHashSet } ;
3
3
4
4
use crate :: {
5
5
TraitType , ValueType ,
6
- id:: { TraitTypeId , ValueTypeId } ,
6
+ id:: { FunctionId , TraitTypeId , ValueTypeId } ,
7
7
macro_helpers:: CollectableFunction ,
8
8
native_function:: NativeFunction ,
9
9
value_type:: { CollectableTrait , CollectableValueType } ,
10
10
} ;
11
11
12
- pub fn get_function_by_global_name ( global_name : & str ) -> & ' static NativeFunction {
13
- static NAME_TO_FUNCTION : Lazy < FxHashMap < & ' static str , & ' static NativeFunction > > =
14
- Lazy :: new ( || {
15
- let mut map = FxHashMap :: default ( ) ;
16
- for collected in inventory:: iter :: < CollectableFunction > {
17
- let native_function = & * * collected. 0 ;
18
- let global_name = native_function. global_name ;
19
- let prev = map. insert ( global_name, native_function) ;
20
- debug_assert ! (
21
- prev. is_none( ) ,
22
- "multiple functions registered with the name {global_name}!"
23
- ) ;
24
- }
25
- map. shrink_to_fit ( ) ;
26
- map
27
- } ) ;
28
-
29
- match NAME_TO_FUNCTION . get ( global_name) {
30
- Some ( f) => f,
31
- None => panic ! ( "unable to find function: {global_name}" ) ,
12
+ struct Functions {
13
+ id_to_value : Box < [ & ' static NativeFunction ] > ,
14
+ value_to_id : FxHashMap < & ' static NativeFunction , FunctionId > ,
15
+ }
16
+ static FUNCTIONS : Lazy < Functions > = Lazy :: new ( || {
17
+ let mut functions = inventory:: iter :: < CollectableFunction >
18
+ . into_iter ( )
19
+ . map ( |c| & * * c. 0 )
20
+ . collect :: < Vec < _ > > ( ) ;
21
+ functions. sort_by_key ( |f| f. global_name ) ;
22
+ let mut value_to_id = FxHashMap :: default ( ) ;
23
+ let mut names = FxHashSet :: default ( ) ;
24
+ names. reserve ( functions. len ( ) ) ;
25
+ for ( index, & native_function) in functions. iter ( ) . enumerate ( ) {
26
+ // SAFETY: as a usize, usize+1 is definitely non-zero.
27
+ let id = unsafe { FunctionId :: new_unchecked ( ( index + 1 ) . try_into ( ) . unwrap ( ) ) } ;
28
+ value_to_id. insert ( native_function, id) ;
29
+ let global_name = native_function. global_name ;
30
+ let new = names. insert ( global_name) ;
31
+ debug_assert ! (
32
+ !new,
33
+ "multiple functions registered with name: {global_name}!"
34
+ ) ;
35
+ }
36
+ value_to_id. shrink_to_fit ( ) ;
37
+ Functions {
38
+ id_to_value : functions. into_boxed_slice ( ) ,
39
+ value_to_id,
32
40
}
41
+ } ) ;
42
+
43
+ pub fn get_native_function ( id : FunctionId ) -> & ' static NativeFunction {
44
+ FUNCTIONS . id_to_value [ * id as usize - 1 ]
45
+ }
46
+
47
+ pub fn get_function_id ( func : & ' static NativeFunction ) -> FunctionId {
48
+ * FUNCTIONS
49
+ . value_to_id
50
+ . get ( & func)
51
+ . expect ( "function isn't registered" )
33
52
}
34
53
35
54
struct Values {
@@ -50,17 +69,18 @@ static VALUES: Lazy<Values> = Lazy::new(|| {
50
69
51
70
let mut value_to_id = FxHashMap :: default ( ) ;
52
71
value_to_id. reserve ( all_values. len ( ) ) ;
53
- let mut global_name_to_value = FxHashMap :: default ( ) ;
54
- global_name_to_value. reserve ( all_values. len ( ) ) ;
72
+ // Our sort above is non-sensical if names are not unique
73
+ let mut names = FxHashSet :: default ( ) ;
74
+ names. reserve ( all_values. len ( ) ) ;
55
75
56
76
for ( index, & value_type) in all_values. iter ( ) . enumerate ( ) {
57
77
// SAFETY: as a usize, usize+1 is definitely non-zero.
58
78
let id = unsafe { ValueTypeId :: new_unchecked ( ( index + 1 ) . try_into ( ) . unwrap ( ) ) } ;
59
79
value_to_id. insert ( value_type, id) ;
60
- let prev = global_name_to_value . insert ( value_type. global_name , ( id , value_type ) ) ;
80
+ let new = names . insert ( value_type. global_name ) ;
61
81
debug_assert ! (
62
- prev . is_none ( ) ,
63
- "two traits registered with the same name: {}" ,
82
+ new ,
83
+ "two values registered with the same name: {}" ,
64
84
value_type. global_name
65
85
) ;
66
86
}
0 commit comments