go_away/
registry.rs

1pub use std::collections::HashMap;
2
3pub use super::{
4    types::{Alias, Enum, NewType, Struct, TypeRef, Union},
5    TypeId,
6};
7
8/// A registry of type details.
9///
10/// Can be populated by passing in to `TypeMetadata::metadata` and then used
11/// to output types in other languages.
12#[derive(Default)]
13pub struct TypeRegistry {
14    /// The master list of types
15    pub(super) types: HashMap<TypeId, Type>,
16
17    /// An ordered list of struct IDs, used to output in order.
18    pub(super) structs: Vec<TypeId>,
19    /// An ordered list of enum IDs, used to output in order.
20    pub(super) enums: Vec<TypeId>,
21    /// An ordered list of union IDs, used to output in order.
22    pub(super) unions: Vec<TypeId>,
23    /// An ordered list of newtype IDs, used to output in order.
24    pub(super) newtypes: Vec<TypeId>,
25    /// An ordered list of alias IDs
26    pub(super) aliases: Vec<TypeId>,
27}
28
29impl TypeRegistry {
30    /// Construct a new TypeRegistry
31    pub fn new() -> Self {
32        TypeRegistry::default()
33    }
34
35    /// Registers an `Alias` in the `TypeRegistry`
36    ///
37    /// Users should use `crate::TypeAlias::register_alias` rather than calling this directly.
38    pub fn register_alias(&mut self, id: TypeId, details: Alias) -> TypeRef {
39        if !self.types.contains_key(&id) {
40            self.aliases.push(id.clone());
41        }
42        self.register_type(id, Type::Alias(details))
43    }
44
45    /// Register a `Struct`
46    ///
47    /// Users should use `crate::TypeMetadata::metadata` rather than calling this directly.
48    pub fn register_struct(&mut self, id: TypeId, details: Struct) -> TypeRef {
49        if !self.types.contains_key(&id) {
50            self.structs.push(id.clone());
51        }
52        self.register_type(id, Type::Struct(details))
53    }
54
55    /// Register a `NewType`
56    ///
57    /// Users should use `crate::TypeMetadata::metadata` rather than calling this directly.
58    pub fn register_newtype(&mut self, id: TypeId, details: NewType) -> TypeRef {
59        if !self.types.contains_key(&id) {
60            self.newtypes.push(id.clone());
61        }
62        self.register_type(id, Type::NewType(details))
63    }
64
65    /// Register an `Enum`
66    ///
67    /// Users should use `crate::TypeMetadata::metadata` rather than calling this directly.
68    pub fn register_enum(&mut self, id: TypeId, details: Enum) -> TypeRef {
69        if !self.types.contains_key(&id) {
70            self.enums.push(id.clone());
71        }
72        self.register_type(id, Type::Enum(details))
73    }
74
75    /// Register a `Uninon`
76    ///
77    /// Users should use `crate::TypeMetadata::metadata` rather than calling this directly.
78    pub fn register_union(&mut self, id: TypeId, details: Union) -> TypeRef {
79        if !self.types.contains_key(&id) {
80            self.unions.push(id.clone());
81        }
82        self.register_type(id, Type::Union(details))
83    }
84
85    fn register_type(&mut self, id: TypeId, ty: Type) -> TypeRef {
86        if self.types.contains_key(&id) {
87            match self.types.get(&id) {
88                Some(existing) if ty.same_kind(existing) => return existing.type_ref(),
89                other => panic!("Type register mismatch: {:?} vs {:?}", ty, other),
90            }
91        }
92
93        let type_ref = ty.type_ref();
94        self.types.insert(id, ty);
95
96        type_ref
97    }
98}
99
100#[derive(Debug)]
101#[allow(clippy::enum_variant_names)]
102pub enum Type {
103    Struct(Struct),
104    Enum(Enum),
105    Union(Union),
106    NewType(NewType),
107    Alias(Alias),
108}
109
110impl Type {
111    fn type_ref(&self) -> TypeRef {
112        match self {
113            Type::Struct(st) => TypeRef {
114                name: st.name.clone(),
115            },
116            Type::Enum(en) => TypeRef {
117                name: en.name.clone(),
118            },
119            Type::Union(un) => TypeRef {
120                name: un.name.clone(),
121            },
122            Type::NewType(nt) => TypeRef {
123                name: nt.name.clone(),
124            },
125            Type::Alias(nt) => TypeRef {
126                name: nt.name.clone(),
127            },
128        }
129    }
130
131    #[allow(clippy::match_like_matches_macro)]
132    fn same_kind(&self, other: &Type) -> bool {
133        match (self, other) {
134            (Type::Struct(_), Type::Struct(_)) => true,
135            (Type::Enum(_), Type::Enum(_)) => true,
136            (Type::Union(_), Type::Union(_)) => true,
137            (Type::NewType(_), Type::NewType(_)) => true,
138            _ => false,
139        }
140    }
141}