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 { name: name.into(), module: None }
107 }
108}
109
110impl Interface {
111 pub fn requires_impls_for_role(&self, role_name: &str) -> bool {
112 if self.has_public_event_impls_for_role(role_name) {
113 return true;
114 }
115
116 for required_impls in &self.required_impls {
117 if required_impls.roles
118 .iter()
119 .find(|x| x == &role_name)
120 .is_some()
121 {
122 return true;
123 }
124 }
125
126 false
127 }
128
129 pub fn has_public_event_impls_for_role(&self, role_name: &str) -> bool {
130 for events_list in &self.events {
131 if events_list.events.len() > 0 {
132 if events_list.to_roles
133 .iter()
134 .find(|x| x == &role_name)
135 .is_some()
136 {
137 for event in &events_list.events {
138 if !event.is_private {
139 return true;
140 }
141 }
142 }
143 }
144 }
145
146 false
147 }
148
149 pub fn has_private_event_impls_for_role(&self, role_name: &str) -> bool {
150 for events_list in &self.events {
151 if events_list.events.len() > 0 {
152 if events_list.to_roles
153 .iter()
154 .find(|x| x == &role_name)
155 .is_some()
156 {
157 for event in &events_list.events {
158 if event.is_private {
159 return true;
160 }
161 }
162 }
163 }
164 }
165
166 false
167 }
168
169 pub fn has_methods_for_role(&self, role_name: &str) -> bool {
170 for methods_list in &self.methods {
171 if methods_list.methods.len() > 0 {
172 if methods_list.roles
173 .iter()
174 .find(|x| x == &role_name)
175 .is_some()
176 {
177 return true;
178 }
179 }
180 }
181
182 false
183 }
184
185 pub fn has_impls_for_role(&self, role_name: &str) -> bool {
186 for required_impls in &self.required_impls {
187 if required_impls.roles
188 .iter()
189 .find(|x| x == &role_name)
190 .is_some()
191 {
192 return true;
193 }
194 }
195
196 false
197 }
198
199 pub fn has_config_for_role(&self, role_name: &str) -> bool {
200 for config_list in &self.config {
201 if config_list.roles
202 .iter()
203 .find(|x| x == &role_name)
204 .is_some()
205 {
206 return true;
207 }
208 }
209
210 false
211 }
212
213 pub fn has_state(&self, db: &Database) -> bool {
214 if self.state.len() > 0 { return true; }
215
216 let mut has_state = false;
217
218 for object in &self.objects {
219 if let Some(object_interface) = db.lookup_interface(&object.construct) {
220 has_state |= object_interface.has_state(db);
221 } else {
222 panic!("Interface::has_state failed to lookup interface {:?}", object.construct);
223 }
224 }
225
226 has_state
227 }
228}
229
230impl InterfaceObject {
231 pub fn get_role_for_parent_role<'a>(
234 &self,
235 object_interface: &'a Interface,
236 parent_role_name: &str,
237 ) -> Option<&'a String> {
238 let role_arg_index = self.role_args.iter().enumerate()
239 .find(|(_, role_arg_name)| &parent_role_name == role_arg_name)
240 .map(|(i, _)| i)?;
241
242 Some(&object_interface.roles[role_arg_index])
243 }
244
245 pub fn get_roles_for_parent_role<'a>(
248 &self,
249 object_interface: &'a Interface,
250 parent_role_name: &str,
251 ) -> Vec<&'a String> {
252 self.role_args.iter().enumerate()
253 .filter(move |(_, role_arg_name)| &parent_role_name == role_arg_name)
254 .map(|(role_arg_index, _)| &object_interface.roles[role_arg_index])
255 .collect()
256 }
257}
258