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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub use std::collections::HashMap;
pub use super::{
types::{Enum, NewType, Struct, TypeRef, Union},
TypeId,
};
#[derive(Default)]
pub struct TypeRegistry {
pub(super) types: HashMap<TypeId, Type>,
pub(super) structs: Vec<TypeId>,
pub(super) enums: Vec<TypeId>,
pub(super) unions: Vec<TypeId>,
pub(super) newtypes: Vec<TypeId>,
}
impl TypeRegistry {
pub fn new() -> Self {
TypeRegistry::default()
}
pub fn register_struct(&mut self, id: TypeId, details: Struct) -> TypeRef {
if !self.types.contains_key(&id) {
self.structs.push(id.clone());
}
self.register_type(id, Type::Struct(details))
}
pub fn register_newtype(&mut self, id: TypeId, details: NewType) -> TypeRef {
if !self.types.contains_key(&id) {
self.newtypes.push(id.clone());
}
self.register_type(id, Type::NewType(details))
}
pub fn register_enum(&mut self, id: TypeId, details: Enum) -> TypeRef {
if !self.types.contains_key(&id) {
self.enums.push(id.clone());
}
self.register_type(id, Type::Enum(details))
}
pub fn register_union(&mut self, id: TypeId, details: Union) -> TypeRef {
if !self.types.contains_key(&id) {
self.unions.push(id.clone());
}
self.register_type(id, Type::Union(details))
}
fn register_type(&mut self, id: TypeId, ty: Type) -> TypeRef {
if self.types.contains_key(&id) {
match self.types.get(&id) {
Some(existing) if ty.same_kind(&existing) => return existing.type_ref(),
other => panic!("Type register mismatch: {:?} vs {:?}", ty, other),
}
}
let type_ref = ty.type_ref();
self.types.insert(id, ty);
type_ref
}
}
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
pub(super) enum Type {
Struct(Struct),
Enum(Enum),
Union(Union),
NewType(NewType),
}
impl Type {
fn type_ref(&self) -> TypeRef {
match self {
Type::Struct(st) => TypeRef {
name: st.name.clone(),
},
Type::Enum(en) => TypeRef {
name: en.name.clone(),
},
Type::Union(un) => TypeRef {
name: un.name.clone(),
},
Type::NewType(nt) => TypeRef {
name: nt.name.clone(),
},
}
}
#[allow(clippy::match_like_matches_macro)]
fn same_kind(&self, other: &Type) -> bool {
match (self, other) {
(Type::Struct(_), Type::Struct(_)) => true,
(Type::Enum(_), Type::Enum(_)) => true,
(Type::Union(_), Type::Union(_)) => true,
(Type::NewType(_), Type::NewType(_)) => true,
_ => false,
}
}
}