pub use std::collections::HashMap;
pub use super::{
types::{Alias, 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>,
pub(super) aliases: Vec<TypeId>,
}
impl TypeRegistry {
pub fn new() -> Self {
TypeRegistry::default()
}
pub fn register_alias(&mut self, id: TypeId, details: Alias) -> TypeRef {
if !self.types.contains_key(&id) {
self.aliases.push(id.clone());
}
self.register_type(id, Type::Alias(details))
}
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 enum Type {
Struct(Struct),
Enum(Enum),
Union(Union),
NewType(NewType),
Alias(Alias),
}
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(),
},
Type::Alias(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,
}
}
}