1use crate::Database;
2
3#[derive(Clone, Debug, Eq, PartialEq, Hash)]
4pub struct Schema {
5 pub imports: Vec<Import>,
6 pub interfaces: Vec<Interface>,
7 pub type_defs: Vec<mproto_codegen::ast::TypeDef>,
8}
9
10#[derive(Clone, Debug, Eq, PartialEq, Hash)]
11pub struct Import {
12 pub name: String,
13 pub path: String,
14}
15
16#[derive(Clone, Debug, Eq, PartialEq, Hash)]
17pub struct Interface {
18 pub name: String,
19 pub type_params: Vec<String>,
20 pub roles: Vec<String>,
21
22 pub events: Vec<InterfaceEventsList>,
23 pub objects: Vec<InterfaceObject>,
24 pub config: Vec<InterfaceConfigList>,
25 pub required_impls: Vec<InterfaceRequiredImplsList>,
26 pub methods: Vec<ObjectMethodsList>,
27 pub state: Vec<InterfaceState>,
28}
29
30#[derive(Clone, Debug, Eq, PartialEq, Hash)]
31pub struct InterfaceEventsList {
32 pub from_roles: Vec<String>,
33 pub to_roles: Vec<String>,
34 pub events: Vec<InterfaceEvent>,
35}
36
37#[derive(Clone, Debug, Eq, PartialEq, Hash)]
38pub struct InterfaceEvent {
39 pub name: String,
40 pub ty: mproto_codegen::ast::Type,
41 pub is_private: bool,
42}
43
44#[derive(Clone, Debug, Eq, PartialEq, Hash)]
45pub struct InterfaceState {
46 pub name: String,
47 pub ty: mproto_codegen::ast::Type,
48}
49
50#[derive(Clone, Debug, Eq, PartialEq, Hash)]
51pub struct InterfaceObject {
52 pub name: String,
53 pub construct: QualifiedIdentifier,
54 pub type_args: Vec<mproto_codegen::ast::Type>,
55 pub role_args: Vec<String>,
56}
57
58#[derive(Clone, Debug, Eq, PartialEq, Hash)]
59pub struct InterfaceConfigList {
60 pub roles: Vec<String>,
61 pub items: Vec<InterfaceConfigItem>,
62}
63
64#[derive(Clone, Debug, Eq, PartialEq, Hash)]
65pub struct InterfaceConfigItem {
66 pub name: String,
67 pub ty: mproto_codegen::ast::Type,
68}
69
70#[derive(Clone, Debug, Eq, PartialEq, Hash)]
71pub struct InterfaceRequiredImplsList {
72 pub roles: Vec<String>,
73 pub required_impls: Vec<InterfaceRequiredImpl>,
74}
75
76#[derive(Clone, Debug, Eq, PartialEq, Hash)]
77pub struct InterfaceRequiredImpl {
78 pub name: String,
79 pub is_async: bool,
80 pub input_ty: mproto_codegen::ast::Type,
81 pub output_ty: mproto_codegen::ast::Type,
82}
83
84#[derive(Clone, Debug, Eq, PartialEq, Hash)]
85pub struct ObjectMethodsList {
86 pub roles: Vec<String>,
87 pub methods: Vec<ObjectMethod>,
88}
89
90#[derive(Clone, Debug, Eq, PartialEq, Hash)]
91pub struct ObjectMethod {
92 pub name: String,
93 pub is_async: bool,
94 pub input_ty: mproto_codegen::ast::Type,
95 pub output_ty: mproto_codegen::ast::Type,
96}
97
98#[derive(Clone, Debug, Eq, PartialEq, Hash)]
99pub struct QualifiedIdentifier {
100 pub name: String,
101 pub module: Option<String>,
102}
103
104impl QualifiedIdentifier {
105 pub fn local(name: impl Into<String>) -> Self {
106 Self {
107 name: name.into(),
108 module: None,
109 }
110 }
111}
112
113impl Interface {
114 pub fn requires_impls_for_role(&self, role_name: &str) -> bool {
115 if self.has_public_event_impls_for_role(role_name) {
116 return true;
117 }
118
119 for required_impls in &self.required_impls {
120 if required_impls
121 .roles
122 .iter()
123 .find(|x| x == &role_name)
124 .is_some()
125 {
126 return true;
127 }
128 }
129
130 false
131 }
132
133 pub fn has_public_event_impls_for_role(&self, role_name: &str) -> bool {
134 for events_list in &self.events {
135 if events_list.events.len() > 0 {
136 if events_list
137 .to_roles
138 .iter()
139 .find(|x| x == &role_name)
140 .is_some()
141 {
142 for event in &events_list.events {
143 if !event.is_private {
144 return true;
145 }
146 }
147 }
148 }
149 }
150
151 false
152 }
153
154 pub fn has_private_event_impls_for_role(&self, role_name: &str) -> bool {
155 for events_list in &self.events {
156 if events_list.events.len() > 0 {
157 if events_list
158 .to_roles
159 .iter()
160 .find(|x| x == &role_name)
161 .is_some()
162 {
163 for event in &events_list.events {
164 if event.is_private {
165 return true;
166 }
167 }
168 }
169 }
170 }
171
172 false
173 }
174
175 pub fn has_methods_for_role(&self, role_name: &str) -> bool {
176 for methods_list in &self.methods {
177 if methods_list.methods.len() > 0 {
178 if methods_list
179 .roles
180 .iter()
181 .find(|x| x == &role_name)
182 .is_some()
183 {
184 return true;
185 }
186 }
187 }
188
189 false
190 }
191
192 pub fn has_impls_for_role(&self, role_name: &str) -> bool {
193 for required_impls in &self.required_impls {
194 if required_impls
195 .roles
196 .iter()
197 .find(|x| x == &role_name)
198 .is_some()
199 {
200 return true;
201 }
202 }
203
204 false
205 }
206
207 pub fn has_config_for_role(&self, role_name: &str) -> bool {
208 for config_list in &self.config {
209 if config_list.roles.iter().find(|x| x == &role_name).is_some() {
210 return true;
211 }
212 }
213
214 false
215 }
216
217 pub fn has_state(&self, db: &Database) -> bool {
218 if self.state.len() > 0 {
219 return true;
220 }
221
222 let mut has_state = false;
223
224 for object in &self.objects {
225 if let Some(object_interface) = db.lookup_interface(&object.construct) {
226 has_state |= object_interface.has_state(db);
227 } else {
228 panic!(
229 "Interface::has_state failed to lookup interface {:?}",
230 object.construct
231 );
232 }
233 }
234
235 has_state
236 }
237}
238
239impl InterfaceObject {
240 pub fn get_role_for_parent_role<'a>(
243 &self,
244 object_interface: &'a Interface,
245 parent_role_name: &str,
246 ) -> Option<&'a String> {
247 let role_arg_index = self
248 .role_args
249 .iter()
250 .enumerate()
251 .find(|(_, role_arg_name)| &parent_role_name == role_arg_name)
252 .map(|(i, _)| i)?;
253
254 Some(&object_interface.roles[role_arg_index])
255 }
256
257 pub fn get_roles_for_parent_role<'a>(
260 &self,
261 object_interface: &'a Interface,
262 parent_role_name: &str,
263 ) -> Vec<&'a String> {
264 self.role_args
265 .iter()
266 .enumerate()
267 .filter(move |(_, role_arg_name)| &parent_role_name == role_arg_name)
268 .map(|(role_arg_index, _)| &object_interface.roles[role_arg_index])
269 .collect()
270 }
271}