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