1 // Copyright 2015 Brendan Zabarauskas and the gl-rs developers
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::collections::{BTreeMap, BTreeSet};
16 
17 use super::{Registry, Type};
18 use utils::{multimap_append, multimap_insert};
19 
20 #[derive(Debug, Clone)]
21 pub enum NamedType {
22     Mixin(Mixin),
23     Interface(Interface),
24     Dictionary(Dictionary),
25     Enum(Enum),
26     Typedef(Type),
27     Callback(Callback),
28 }
29 
30 #[derive(Debug, Clone)]
31 pub struct Mixin {
32     pub members: BTreeMap<String, Vec<Member>>,
33 }
34 
35 #[derive(Debug, Clone)]
36 pub struct Interface {
37     pub inherits: Option<String>,
38     pub mixins: BTreeSet<String>,
39     pub members: BTreeMap<String, Vec<Member>>,
40     pub is_hidden: bool,
41     pub has_class: bool,
42     pub rendering_context: Option<&'static str>,
43     pub doc_comment: String,
44 }
45 
46 #[derive(Debug, Clone)]
47 pub struct Dictionary {
48     pub inherits: Option<String>,
49     pub fields: BTreeMap<String, Field>,
50     pub is_hidden: bool,
51 }
52 
53 #[derive(Debug, Clone)]
54 pub struct Enum {
55     pub variants: BTreeSet<String>,
56 }
57 
58 #[derive(Debug, PartialEq, Eq, Clone)]
59 pub struct Callback {
60     pub args: Vec<Argument>,
61     pub return_type: Option<Type>,
62 }
63 
64 #[derive(Debug, PartialEq, Eq, Clone)]
65 pub struct Const {
66     pub type_: Type,
67     pub value: String,
68 }
69 
70 #[derive(Debug, Eq, Clone)]
71 pub struct Argument {
72     pub name: String,
73     pub optional: bool,
74     pub type_: Type,
75     pub variadic: bool,
76 }
77 
78 #[derive(Debug, PartialEq, Eq, Clone)]
79 pub struct Operation {
80     pub args: Vec<Argument>,
81     pub return_type: Option<Type>,
82     pub doc_comment: String,
83 }
84 
85 #[derive(Debug, PartialEq, Eq, Clone)]
86 pub struct Attribute {
87     pub type_: Type,
88     pub setter: bool,
89     pub getter: bool,
90 }
91 
92 #[derive(Debug, PartialEq, Eq, Clone)]
93 pub enum Member {
94     Const(Const),
95     Operation(Operation),
96     Attribute(Attribute),
97 }
98 
99 #[derive(Debug, Clone)]
100 pub struct Field {
101     pub type_: Type,
102 }
103 
104 #[derive(Debug)]
105 pub struct VisitOptions {
106     pub visit_mixins: bool,
107 }
108 
109 impl NamedType {
as_mixin(&self) -> Option<&Mixin>110     pub fn as_mixin(&self) -> Option<&Mixin> {
111         if let &NamedType::Mixin(ref m) = self {
112             Some(m)
113         } else {
114             None
115         }
116     }
as_interface(&self) -> Option<&Interface>117     pub fn as_interface(&self) -> Option<&Interface> {
118         if let &NamedType::Interface(ref i) = self {
119             Some(i)
120         } else {
121             None
122         }
123     }
as_dictionary(&self) -> Option<&Dictionary>124     pub fn as_dictionary(&self) -> Option<&Dictionary> {
125         if let &NamedType::Dictionary(ref d) = self {
126             Some(d)
127         } else {
128             None
129         }
130     }
as_enum(&self) -> Option<&Enum>131     pub fn as_enum(&self) -> Option<&Enum> {
132         if let &NamedType::Enum(ref e) = self {
133             Some(e)
134         } else {
135             None
136         }
137     }
as_typedef(&self) -> Option<&Type>138     pub fn as_typedef(&self) -> Option<&Type> {
139         if let &NamedType::Typedef(ref t) = self {
140             Some(t)
141         } else {
142             None
143         }
144     }
as_mixin_mut(&mut self) -> Option<&mut Mixin>145     pub fn as_mixin_mut(&mut self) -> Option<&mut Mixin> {
146         if let &mut NamedType::Mixin(ref mut m) = self {
147             Some(m)
148         } else {
149             None
150         }
151     }
as_interface_mut(&mut self) -> Option<&mut Interface>152     pub fn as_interface_mut(&mut self) -> Option<&mut Interface> {
153         if let &mut NamedType::Interface(ref mut i) = self {
154             Some(i)
155         } else {
156             None
157         }
158     }
as_dictionary_mut(&mut self) -> Option<&mut Dictionary>159     pub fn as_dictionary_mut(&mut self) -> Option<&mut Dictionary> {
160         if let &mut NamedType::Dictionary(ref mut d) = self {
161             Some(d)
162         } else {
163             None
164         }
165     }
as_enum_mut(&mut self) -> Option<&mut Enum>166     pub fn as_enum_mut(&mut self) -> Option<&mut Enum> {
167         if let &mut NamedType::Enum(ref mut e) = self {
168             Some(e)
169         } else {
170             None
171         }
172     }
as_typedef_mut(&mut self) -> Option<&mut Type>173     pub fn as_typedef_mut(&mut self) -> Option<&mut Type> {
174         if let &mut NamedType::Typedef(ref mut t) = self {
175             Some(t)
176         } else {
177             None
178         }
179     }
180 }
181 
182 impl PartialEq for Argument {
eq(&self, other: &Self) -> bool183     fn eq(&self, other: &Self) -> bool {
184         self.type_ == other.type_
185     }
186 }
187 
188 impl Default for VisitOptions {
default() -> Self189     fn default() -> Self {
190         VisitOptions { visit_mixins: true }
191     }
192 }
193 
194 impl Dictionary {
collect_fields<'a>(&'a self, registry: &'a Registry) -> BTreeMap<&'a str, &'a Field>195     pub fn collect_fields<'a>(&'a self, registry: &'a Registry) -> BTreeMap<&'a str, &'a Field> {
196         let mut fields = BTreeMap::new();
197 
198         // Inherits
199         if let Some(inherit_name) = self.inherits.as_ref() {
200             let inherit = registry
201                 .types
202                 .get(inherit_name)
203                 .and_then(NamedType::as_dictionary)
204                 .expect(inherit_name);
205             fields.append(&mut inherit.collect_fields(registry));
206         }
207 
208         // Fields
209         for (name, field) in &self.fields {
210             fields.insert(name, field);
211         }
212 
213         fields
214     }
215 }
216 
217 impl Interface {
collect_members<'a>( &'a self, registry: &'a Registry, options: &VisitOptions, ) -> BTreeMap<&'a str, Vec<&'a Member>>218     pub fn collect_members<'a>(
219         &'a self,
220         registry: &'a Registry,
221         options: &VisitOptions,
222     ) -> BTreeMap<&'a str, Vec<&'a Member>> {
223         let mut members = BTreeMap::new();
224 
225         // Mixins
226         for mixin_name in &self.mixins {
227             let mixin = registry
228                 .types
229                 .get(mixin_name)
230                 .and_then(NamedType::as_mixin)
231                 .expect(mixin_name);
232             if options.visit_mixins {
233                 multimap_append(&mut members, mixin.collect_members(registry, options));
234             }
235         }
236 
237         // Members
238         for (name, ms) in &self.members {
239             for member in ms {
240                 multimap_insert(&mut members, &**name, member);
241             }
242         }
243 
244         members
245     }
246 }
247 
248 impl Mixin {
collect_members<'a>( &'a self, _registry: &'a Registry, _options: &VisitOptions, ) -> BTreeMap<&'a str, Vec<&'a Member>>249     pub fn collect_members<'a>(
250         &'a self,
251         _registry: &'a Registry,
252         _options: &VisitOptions,
253     ) -> BTreeMap<&'a str, Vec<&'a Member>> {
254         let mut members = BTreeMap::new();
255 
256         // Members
257         for (name, ms) in &self.members {
258             for member in ms {
259                 multimap_insert(&mut members, &**name, member);
260             }
261         }
262 
263         members
264     }
265 }
266