oo_bindgen/model/builder/
library.rs

1use std::collections::{HashMap, HashSet};
2use std::rc::Rc;
3
4use crate::model::*;
5
6pub(crate) struct LibraryFields {
7    // a record of statements preserved in order
8    pub(crate) statements: Vec<Statement<Unvalidated>>,
9
10    // native stuff
11    pub(crate) structs_declarations: HashSet<StructDeclarationHandle>,
12    pub(crate) structs: HashMap<StructDeclarationHandle, StructType<Unvalidated>>,
13    pub(crate) functions: HashSet<Handle<Function<Unvalidated>>>,
14    pub(crate) enums: HashSet<Handle<Enum<Unvalidated>>>,
15
16    // oo stuff
17    pub(crate) class_declarations: HashSet<ClassDeclarationHandle>,
18    pub(crate) classes: HashMap<ClassDeclarationHandle, Handle<Class<Unvalidated>>>,
19    pub(crate) static_classes: HashSet<Handle<StaticClass<Unvalidated>>>,
20    pub(crate) interfaces: HashSet<Handle<Interface<Unvalidated>>>,
21
22    // specialized types
23    pub(crate) iterators: HashSet<Handle<AbstractIterator<Unvalidated>>>,
24    pub(crate) collections: HashSet<Handle<Collection<Unvalidated>>>,
25}
26
27impl LibraryFields {
28    pub(crate) fn find_struct<T: AsRef<str>>(&self, name: T) -> Option<&StructType<Unvalidated>> {
29        self.structs.values().find(|x| x.name() == name.as_ref())
30    }
31
32    pub(crate) fn find_enum<T: AsRef<str>>(&self, name: T) -> Option<&Handle<Enum<Unvalidated>>> {
33        self.enums.iter().find(|x| x.name == name.as_ref())
34    }
35
36    pub(crate) fn find_class_declaration<T: AsRef<str>>(
37        &self,
38        name: T,
39    ) -> Option<&ClassDeclarationHandle> {
40        self.class_declarations
41            .iter()
42            .find(|x| x.name == name.as_ref())
43    }
44
45    pub(crate) fn find_class<T: AsRef<str>>(&self, name: T) -> Option<&Handle<Class<Unvalidated>>> {
46        self.classes.values().find(|x| x.name() == name.as_ref())
47    }
48
49    pub(crate) fn find_interface<T: AsRef<str>>(
50        &self,
51        name: T,
52    ) -> Option<&Handle<Interface<Unvalidated>>> {
53        self.interfaces.iter().find(|x| x.name == name.as_ref())
54    }
55
56    pub(crate) fn new() -> Self {
57        Self {
58            statements: Vec::new(),
59
60            structs_declarations: HashSet::new(),
61            structs: HashMap::new(),
62
63            enums: HashSet::new(),
64
65            class_declarations: HashSet::new(),
66            classes: HashMap::new(),
67            static_classes: HashSet::new(),
68
69            interfaces: HashSet::new(),
70
71            iterators: HashSet::new(),
72            collections: HashSet::new(),
73
74            functions: HashSet::new(),
75        }
76    }
77}
78
79pub struct LibraryBuilder {
80    version: Version,
81    info: Rc<LibraryInfo>,
82
83    settings: Rc<LibrarySettings>,
84
85    // names of symbols used in the library
86    symbol_names: HashSet<String>,
87    fields: LibraryFields,
88}
89
90impl LibraryBuilder {
91    pub fn new(version: Version, info: LibraryInfo, settings: Rc<LibrarySettings>) -> Self {
92        Self {
93            version,
94            info: Rc::new(info),
95            settings,
96            symbol_names: HashSet::new(),
97            fields: LibraryFields::new(),
98        }
99    }
100
101    pub(crate) fn settings(&self) -> &LibrarySettings {
102        &self.settings
103    }
104
105    pub(crate) fn clone_settings(&self) -> Rc<LibrarySettings> {
106        self.settings.clone()
107    }
108
109    pub(crate) fn add_statement(&mut self, statement: Statement<Unvalidated>) -> BindResult<()> {
110        // verify that all the pieces of the statement are from this library
111        self.check_statement(&statement)?;
112
113        if let Some(name) = statement.unique_name() {
114            self.check_unique_symbol(name)?;
115        }
116
117        self.fields.statements.push(statement.clone());
118
119        match statement {
120            Statement::Constants(_) => {}
121            Statement::StructDeclaration(x) => {
122                self.fields.structs_declarations.insert(x);
123            }
124            Statement::StructDefinition(x) => {
125                self.fields.structs.insert(x.declaration(), x);
126            }
127            Statement::EnumDefinition(x) => {
128                self.fields.enums.insert(x);
129            }
130            Statement::ErrorType(_) => {}
131            Statement::ClassDeclaration(x) => {
132                self.fields.class_declarations.insert(x);
133            }
134            Statement::ClassDefinition(x) => {
135                self.fields.classes.insert(x.declaration.clone(), x);
136            }
137            Statement::StaticClassDefinition(x) => {
138                self.fields.static_classes.insert(x);
139            }
140            Statement::InterfaceDefinition(x) => {
141                self.fields.interfaces.insert(x.untyped().clone());
142            }
143            Statement::IteratorDeclaration(x) => {
144                self.fields.iterators.insert(x);
145            }
146            Statement::CollectionDeclaration(x) => {
147                self.fields.collections.insert(x);
148            }
149            Statement::FunctionDefinition(x) => {
150                self.fields.functions.insert(x);
151            }
152        }
153
154        Ok(())
155    }
156
157    fn validate_statement(
158        &self,
159        statement: &Statement<Unvalidated>,
160    ) -> BindResult<Statement<Validated>> {
161        match statement {
162            Statement::Constants(x) => Ok(Statement::Constants(x.validate(&self.fields)?)),
163            Statement::StructDeclaration(x) => Ok(Statement::StructDeclaration(x.clone())),
164            Statement::StructDefinition(x) => {
165                Ok(Statement::StructDefinition(x.validate(&self.fields)?))
166            }
167            Statement::EnumDefinition(x) => {
168                Ok(Statement::EnumDefinition(x.validate(&self.fields)?))
169            }
170            Statement::ErrorType(x) => Ok(Statement::ErrorType(x.validate(&self.fields)?)),
171            Statement::ClassDeclaration(x) => Ok(Statement::ClassDeclaration(x.clone())),
172            Statement::ClassDefinition(x) => {
173                Ok(Statement::ClassDefinition(x.validate(&self.fields)?))
174            }
175            Statement::StaticClassDefinition(x) => {
176                Ok(Statement::StaticClassDefinition(x.validate(&self.fields)?))
177            }
178            Statement::InterfaceDefinition(x) => {
179                Ok(Statement::InterfaceDefinition(x.validate(&self.fields)?))
180            }
181            Statement::IteratorDeclaration(x) => {
182                Ok(Statement::IteratorDeclaration(x.validate(&self.fields)?))
183            }
184            Statement::CollectionDeclaration(x) => {
185                Ok(Statement::CollectionDeclaration(x.validate(&self.fields)?))
186            }
187            Statement::FunctionDefinition(x) => {
188                Ok(Statement::FunctionDefinition(x.validate(&self.fields)?))
189            }
190        }
191    }
192
193    pub fn build(mut self) -> BindResult<Library> {
194        // Add the version function
195        self.define_function("version")?
196            .returns(StringType, "Version number")?
197            .doc("Get the version of the library as a string")?
198            .build()?;
199
200        let statements: BindResult<Vec<Statement<Validated>>> = self
201            .fields
202            .statements
203            .iter()
204            .map(|s| self.validate_statement(s))
205            .collect();
206
207        Ok(Library::new(
208            self.version,
209            self.info,
210            self.settings,
211            statements?,
212        ))
213    }
214
215    pub fn define_error_type<T: IntoName>(
216        &mut self,
217        error_name: T,
218        exception_name: T,
219        exception_type: ExceptionType,
220    ) -> BindResult<ErrorTypeBuilder> {
221        let exception_name = exception_name.into_name()?;
222        let builder = self
223            .define_enum(error_name)?
224            .push("ok", "Success, i.e. no error occurred")?;
225
226        Ok(ErrorTypeBuilder::new(
227            exception_name,
228            exception_type,
229            builder,
230        ))
231    }
232
233    pub fn define_constants<T: IntoName>(&mut self, name: T) -> BindResult<ConstantSetBuilder> {
234        Ok(ConstantSetBuilder::new(self, name.into_name()?))
235    }
236
237    pub(crate) fn declare_struct<T: IntoName>(
238        &mut self,
239        name: T,
240    ) -> BindResult<StructDeclarationHandle> {
241        let name = name.into_name()?;
242        let handle = Handle::new(StructDeclaration::new(name, self.settings.clone()));
243        self.add_statement(Statement::StructDeclaration(handle.clone()))?;
244        Ok(handle)
245    }
246
247    pub fn declare_universal_struct<T: IntoName>(
248        &mut self,
249        name: T,
250    ) -> BindResult<UniversalStructDeclaration> {
251        Ok(UniversalStructDeclaration::new(
252            self.declare_struct(name.into_name()?)?,
253        ))
254    }
255
256    pub fn declare_function_argument_struct<T: IntoName>(
257        &mut self,
258        name: T,
259    ) -> BindResult<FunctionArgStructDeclaration> {
260        Ok(FunctionArgStructDeclaration::new(
261            self.declare_struct(name.into_name()?)?,
262        ))
263    }
264
265    pub fn declare_function_return_struct<T: IntoName>(
266        &mut self,
267        name: T,
268    ) -> BindResult<FunctionReturnStructDeclaration> {
269        Ok(FunctionReturnStructDeclaration::new(
270            self.declare_struct(name.into_name()?)?,
271        ))
272    }
273
274    pub fn declare_callback_argument_struct<T: IntoName>(
275        &mut self,
276        name: T,
277    ) -> BindResult<CallbackArgStructDeclaration> {
278        Ok(CallbackArgStructDeclaration::new(
279            self.declare_struct(name.into_name()?)?,
280        ))
281    }
282
283    /// Define a structure that can be used in any context.
284    ///
285    /// Backends will generate bi-directional conversion routines
286    /// for this type of struct.
287    pub fn define_universal_struct(
288        &mut self,
289        declaration: UniversalStructDeclaration,
290    ) -> BindResult<UniversalStructBuilder> {
291        if self.fields.structs.contains_key(&declaration.inner) {
292            Err(BindingErrorVariant::StructAlreadyDefined {
293                handle: declaration.inner,
294            }
295            .into())
296        } else {
297            Ok(UniversalStructBuilder::new(self, declaration))
298        }
299    }
300
301    /// Define an opaque structure which must be of universal type
302    pub fn define_opaque_struct(
303        &mut self,
304        declaration: UniversalStructDeclaration,
305    ) -> BindResult<UniversalStructBuilder> {
306        if self.fields.structs.contains_key(&declaration.inner) {
307            Err(BindingErrorVariant::StructAlreadyDefined {
308                handle: declaration.inner,
309            }
310            .into())
311        } else {
312            Ok(UniversalStructBuilder::opaque(self, declaration))
313        }
314    }
315
316    /// Define a structure that can be only be used in callback function arguments
317    pub fn define_callback_argument_struct<T>(
318        &mut self,
319        declaration: T,
320    ) -> BindResult<CallbackArgStructBuilder>
321    where
322        T: Into<CallbackArgStructDeclaration>,
323    {
324        let declaration = declaration.into();
325        if self.fields.structs.contains_key(&declaration.inner) {
326            Err(BindingErrorVariant::StructAlreadyDefined {
327                handle: declaration.inner,
328            }
329            .into())
330        } else {
331            Ok(CallbackArgStructBuilder::new(self, declaration))
332        }
333    }
334
335    /// Define a structure that can only be used as function return value
336    pub fn define_function_return_struct<T>(
337        &mut self,
338        declaration: T,
339    ) -> BindResult<FunctionReturnStructBuilder>
340    where
341        T: Into<FunctionReturnStructDeclaration>,
342    {
343        let declaration = declaration.into();
344        if self.fields.structs.contains_key(&declaration.inner) {
345            Err(BindingErrorVariant::StructAlreadyDefined {
346                handle: declaration.inner,
347            }
348            .into())
349        } else {
350            Ok(FunctionReturnStructBuilder::new(self, declaration))
351        }
352    }
353
354    /// Define a structure that can only be be used as a function argument
355    pub fn define_function_argument_struct<T>(
356        &mut self,
357        declaration: T,
358    ) -> BindResult<FunctionArgStructBuilder>
359    where
360        T: Into<FunctionArgStructDeclaration>,
361    {
362        let declaration = declaration.into();
363        if self.fields.structs.contains_key(&declaration.inner) {
364            Err(BindingErrorVariant::StructAlreadyDefined {
365                handle: declaration.inner,
366            }
367            .into())
368        } else {
369            Ok(FunctionArgStructBuilder::new(self, declaration))
370        }
371    }
372
373    /// Define an enumeration
374    pub fn define_enum<T: IntoName>(&mut self, name: T) -> BindResult<EnumBuilder> {
375        Ok(EnumBuilder::new(self, name.into_name()?))
376    }
377
378    pub fn define_function<T: IntoName>(&mut self, name: T) -> BindResult<FunctionBuilder> {
379        self.define_function_with_category(name, FunctionCategory::Native)
380    }
381
382    pub fn define_method<T: IntoName>(
383        &mut self,
384        name: T,
385        class: ClassDeclarationHandle,
386    ) -> BindResult<ClassMethodBuilder> {
387        ClassMethodBuilder::new(self, name.into_name()?, class)
388    }
389
390    pub fn define_future_method<T: IntoName>(
391        &mut self,
392        name: T,
393        class: ClassDeclarationHandle,
394        future: FutureInterface<Unvalidated>,
395    ) -> BindResult<FutureMethodBuilder> {
396        FutureMethodBuilder::new(self, name.into_name()?, class, future)
397    }
398
399    pub fn define_constructor(
400        &mut self,
401        class: ClassDeclarationHandle,
402    ) -> BindResult<ClassConstructorBuilder> {
403        ClassConstructorBuilder::new(self, class)
404    }
405
406    pub fn define_destructor<D: Into<Doc<Unvalidated>>>(
407        &mut self,
408        class: ClassDeclarationHandle,
409        doc: D,
410    ) -> BindResult<ClassDestructor<Unvalidated>> {
411        ClassDestructor::new(self, class, doc.into())
412    }
413
414    pub(crate) fn define_function_with_category<T: IntoName>(
415        &mut self,
416        name: T,
417        category: FunctionCategory,
418    ) -> BindResult<FunctionBuilder> {
419        Ok(FunctionBuilder::new(self, name.into_name()?, category))
420    }
421
422    pub fn declare_class<T: IntoName>(&mut self, name: T) -> BindResult<ClassDeclarationHandle> {
423        self.declare_any_class(name, ClassType::Normal)
424    }
425
426    fn declare_iterator<T: IntoName>(&mut self, name: T) -> BindResult<IteratorClassDeclaration> {
427        Ok(IteratorClassDeclaration::new(
428            self.declare_any_class(name, ClassType::Iterator)?,
429        ))
430    }
431
432    fn declare_collection<T: IntoName>(
433        &mut self,
434        name: T,
435    ) -> BindResult<CollectionClassDeclaration> {
436        Ok(CollectionClassDeclaration::new(self.declare_any_class(
437            name.into_name()?,
438            ClassType::Collection,
439        )?))
440    }
441
442    fn declare_any_class<T: IntoName>(
443        &mut self,
444        name: T,
445        class_type: ClassType,
446    ) -> BindResult<ClassDeclarationHandle> {
447        let name = name.into_name()?;
448        let handle = ClassDeclarationHandle::new(ClassDeclaration::new(
449            name,
450            class_type,
451            self.settings.clone(),
452        ));
453        self.add_statement(Statement::ClassDeclaration(handle.clone()))?;
454        Ok(handle)
455    }
456
457    pub fn define_class(
458        &mut self,
459        declaration: &ClassDeclarationHandle,
460    ) -> BindResult<ClassBuilder> {
461        self.check_class_declaration(declaration)?;
462        if self.fields.classes.contains_key(declaration) {
463            Err(BindingErrorVariant::ClassAlreadyDefined {
464                handle: declaration.clone(),
465            }
466            .into())
467        } else {
468            Ok(ClassBuilder::new(self, declaration.clone()))
469        }
470    }
471
472    pub fn define_static_class<T: IntoName>(&mut self, name: T) -> BindResult<StaticClassBuilder> {
473        Ok(StaticClassBuilder::new(self, name.into_name()?))
474    }
475
476    /// A future interface is a specialized asynchronous which consists of
477    /// a single callback method providing a single value. The callback
478    /// represents the completion of a "future" and is mapped appropriately
479    /// in backends.
480    pub fn define_future_interface<
481        T: IntoName,
482        D: Into<Doc<Unvalidated>>,
483        E: Into<DocString<Unvalidated>>,
484        V: Into<CallbackArgument>,
485    >(
486        &mut self,
487        name: T,
488        interface_docs: D,
489        value_type: V,
490        value_type_docs: E,
491        error_type: ErrorType<Unvalidated>,
492    ) -> BindResult<FutureInterface<Unvalidated>> {
493        let value_type = value_type.into();
494        let value_type_docs = value_type_docs.into();
495        let name = name.into_name()?;
496        let success_callback_name = self.settings.future.success_callback_method_name.clone();
497        let success_parameter_name = self.settings.future.success_single_parameter_name.clone();
498        let failure_callback_name = self.settings.future.failure_callback_method_name.clone();
499        let failure_parameter_name = self.settings.future.failure_single_parameter_name.clone();
500
501        let builder = self
502            .define_interface(name, interface_docs)?
503            .begin_callback(
504                success_callback_name,
505                "Invoked when the asynchronous operation completes successfully",
506            )?
507            .param(
508                success_parameter_name,
509                value_type.clone(),
510                value_type_docs.clone(),
511            )?
512            .enable_functional_transform()
513            .end_callback()?;
514
515        let builder = builder
516            .begin_callback(
517                failure_callback_name,
518                "Invoked when the asynchronous operation fails",
519            )?
520            .param(
521                failure_parameter_name,
522                CallbackArgument::Basic(BasicType::Enum(error_type.clone_enum())),
523                "Enumeration indicating which error occurred",
524            )?
525            .enable_functional_transform()
526            .end_callback()?;
527
528        let (interface, lib) = builder.build(InterfaceCategory::Future);
529        let ret = FutureInterface::new(value_type, error_type, interface, value_type_docs);
530        lib.add_statement(Statement::InterfaceDefinition(InterfaceType::Future(
531            ret.clone(),
532        )))?;
533
534        Ok(ret)
535    }
536
537    pub fn define_interface<T: IntoName, D: Into<Doc<Unvalidated>>>(
538        &mut self,
539        name: T,
540        doc: D,
541    ) -> BindResult<InterfaceBuilder> {
542        Ok(InterfaceBuilder::new(self, name.into_name()?, doc.into()))
543    }
544
545    pub fn define_iterator<N: IntoName, T: Into<IteratorItemType>>(
546        &mut self,
547        class_name: N,
548        item_type: T,
549    ) -> BindResult<AbstractIteratorHandle> {
550        self.define_iterator_impl(class_name, false, item_type)
551    }
552
553    pub fn define_iterator_with_lifetime<N: IntoName, T: Into<IteratorItemType>>(
554        &mut self,
555        class_name: N,
556        item_type: T,
557    ) -> BindResult<AbstractIteratorHandle> {
558        self.define_iterator_impl(class_name, true, item_type)
559    }
560
561    fn define_iterator_impl<N: IntoName, T: Into<IteratorItemType>>(
562        &mut self,
563        class_name: N,
564        has_lifetime: bool,
565        item_type: T,
566    ) -> BindResult<AbstractIteratorHandle> {
567        let class_name = class_name.into_name()?;
568        let item_type = item_type.into();
569
570        let class = self.declare_iterator(&class_name)?;
571        let next_function = self
572            .define_function_with_category(
573                class_name.append(&self.settings.iterator.next_function_suffix),
574                FunctionCategory::IteratorNext,
575            )?
576            .param(
577                "iter",
578                class.clone(),
579                "opaque iterator on which to retrieve the next value",
580            )?
581            .doc("returns a pointer to the next value or NULL")?
582            .returns(item_type.get_function_return_value(), "next value or NULL")?
583            .build()?;
584
585        let iter = AbstractIteratorHandle::new(AbstractIterator::new(
586            has_lifetime,
587            class.inner,
588            next_function,
589            item_type,
590            self.settings.clone(),
591        ));
592        self.add_statement(Statement::IteratorDeclaration(iter.clone()))?;
593        Ok(iter)
594    }
595
596    pub fn define_collection<N: IntoName, A: Into<FunctionArgument>>(
597        &mut self,
598        class_name: N,
599        value_type: A,
600        has_reserve: bool,
601    ) -> BindResult<CollectionHandle> {
602        let class_name = class_name.into_name()?;
603        let value_type = value_type.into();
604
605        let class_decl = self.declare_collection(&class_name)?;
606
607        let builder = self
608            .define_function_with_category(
609                class_name.append(&self.settings.collection.create_function_suffix),
610                FunctionCategory::CollectionCreate,
611            )?
612            .doc("Creates an instance of the collection")?;
613
614        let builder = if has_reserve {
615            builder.param(
616                "reserve_size",
617                Primitive::U32,
618                "preallocate a particular size",
619            )?
620        } else {
621            builder
622        };
623
624        let create_func = builder
625            .returns(class_decl.clone(), "Allocated opaque collection instance")?
626            .build()?;
627
628        let destroy_func = self
629            .define_function_with_category(
630                class_name.append(&self.settings.collection.destroy_function_suffix),
631                FunctionCategory::CollectionDestroy,
632            )?
633            .doc("Destroys an instance of the collection")?
634            .param("instance", class_decl.clone(), "instance to destroy")?
635            .build()?;
636
637        let add_func = self
638            .define_function_with_category(
639                class_name.append(&self.settings.collection.add_function_suffix),
640                FunctionCategory::CollectionAdd,
641            )?
642            .doc("Add a value to the collection")?
643            .param(
644                "instance",
645                class_decl.clone(),
646                "instance to which to add the value",
647            )?
648            .param("value", value_type.clone(), "value to add to the instance")?
649            .build()?;
650
651        let collection = Handle::new(Collection::new(
652            class_decl.inner,
653            value_type,
654            create_func,
655            destroy_func,
656            add_func,
657            has_reserve,
658        ));
659
660        self.add_statement(Statement::CollectionDeclaration(collection.clone()))?;
661        Ok(collection)
662    }
663
664    fn check_unique_symbol(&mut self, name: &Name) -> BindResult<()> {
665        if self.symbol_names.insert(name.to_string()) {
666            Ok(())
667        } else {
668            Err(BindingErrorVariant::SymbolAlreadyUsed { name: name.clone() }.into())
669        }
670    }
671
672    fn check_statement(&self, statement: &Statement<Unvalidated>) -> BindResult<()> {
673        match statement {
674            // no internals that can be from another library
675            Statement::Constants(_) => Ok(()),
676            Statement::StructDeclaration(_) => Ok(()),
677            Statement::EnumDefinition(_) => Ok(()),
678            Statement::ClassDeclaration(_) => Ok(()),
679            // these types have internals that must be checked
680            Statement::StructDefinition(x) => self.check_struct_declaration(&x.declaration()),
681            Statement::ErrorType(x) => self.check_enum(&x.inner),
682            Statement::ClassDefinition(x) => {
683                self.check_class_declaration(&x.declaration)?;
684                if let Some(x) = &x.constructor {
685                    self.check_function(&x.function)?;
686                }
687                if let Some(x) = &x.destructor {
688                    self.check_function(&x.function)?;
689                }
690                for x in x.static_methods.iter() {
691                    self.check_function(&x.native_function)?
692                }
693                for x in x.methods.iter() {
694                    self.check_function(&x.native_function)?
695                }
696                for x in x.future_methods.iter() {
697                    self.check_function(&x.native_function)?
698                }
699                Ok(())
700            }
701            Statement::StaticClassDefinition(x) => {
702                for x in x.static_methods.iter() {
703                    self.check_function(&x.native_function)?;
704                }
705                Ok(())
706            }
707            Statement::InterfaceDefinition(x) => {
708                for cb in x.untyped().callbacks.iter() {
709                    for arg in cb.arguments.iter() {
710                        self.check_callback_argument(&arg.arg_type)?;
711                    }
712                    if let Some(ret) = cb.return_type.get() {
713                        self.check_callback_return_value(&ret.value)?;
714                    }
715                }
716                Ok(())
717            }
718            Statement::IteratorDeclaration(x) => {
719                self.check_class_declaration(&x.iter_class)?;
720                self.check_function(&x.next_function)?;
721                match &x.item_type {
722                    IteratorItemType::Struct(x) => self.check_struct_declaration(&x.declaration()),
723                    IteratorItemType::Primitive(_) => Ok(()),
724                }
725            }
726            Statement::CollectionDeclaration(x) => {
727                self.check_class_declaration(&x.collection_class)?;
728                self.check_function(&x.create_func)?;
729                self.check_function(&x.add_func)?;
730                self.check_function(&x.delete_func)?;
731                self.check_function_argument(&x.item_type)?;
732                Ok(())
733            }
734            Statement::FunctionDefinition(x) => {
735                for p in x.arguments.iter() {
736                    self.check_function_argument(&p.arg_type)?;
737                }
738                if let Some(r) = x.return_type.get() {
739                    self.check_function_return_type(&r.value)?;
740                }
741                if let Some(err) = x.error_type.get() {
742                    self.check_enum(&err.inner)?;
743                }
744                Ok(())
745            }
746        }
747    }
748
749    fn check_struct_declaration(&self, native_struct: &StructDeclarationHandle) -> BindResult<()> {
750        if self.fields.structs_declarations.contains(native_struct) {
751            Ok(())
752        } else {
753            Err(BindingErrorVariant::NotPartOfThisLibrary {
754                name: native_struct.name.clone(),
755            }
756            .into())
757        }
758    }
759
760    fn check_function(&self, native_function: &FunctionHandle) -> BindResult<()> {
761        if self.fields.functions.contains(native_function) {
762            Ok(())
763        } else {
764            Err(BindingErrorVariant::NotPartOfThisLibrary {
765                name: native_function.name.clone(),
766            }
767            .into())
768        }
769    }
770
771    fn check_enum(&self, native_enum: &Handle<Enum<Unvalidated>>) -> BindResult<()> {
772        if self.fields.enums.contains(native_enum) {
773            Ok(())
774        } else {
775            Err(BindingErrorVariant::NotPartOfThisLibrary {
776                name: native_enum.name.clone(),
777            }
778            .into())
779        }
780    }
781
782    fn check_interface(&self, interface: &InterfaceHandle) -> BindResult<()> {
783        if self.fields.interfaces.contains(interface) {
784            Ok(())
785        } else {
786            Err(BindingErrorVariant::NotPartOfThisLibrary {
787                name: interface.name.clone(),
788            }
789            .into())
790        }
791    }
792
793    fn check_class_declaration(
794        &self,
795        class_declaration: &ClassDeclarationHandle,
796    ) -> BindResult<()> {
797        if self.fields.class_declarations.contains(class_declaration) {
798            Ok(())
799        } else {
800            Err(BindingErrorVariant::NotPartOfThisLibrary {
801                name: class_declaration.name.clone(),
802            }
803            .into())
804        }
805    }
806
807    fn check_function_argument(&self, arg: &FunctionArgument) -> BindResult<()> {
808        match arg {
809            FunctionArgument::Basic(x) => self.check_basic_type(x),
810            FunctionArgument::String(_) => Ok(()),
811            FunctionArgument::Collection(x) => self.check_collection(x),
812            FunctionArgument::Struct(x) => self.check_struct_declaration(&x.declaration()),
813            FunctionArgument::StructRef(x) => self.check_struct_declaration(&x.inner),
814            FunctionArgument::ClassRef(x) => self.check_class_declaration(x),
815            FunctionArgument::Interface(x) => self.check_interface(x),
816        }
817    }
818
819    fn check_callback_argument(&self, arg: &CallbackArgument) -> BindResult<()> {
820        match arg {
821            CallbackArgument::Basic(x) => self.check_basic_type(x),
822            CallbackArgument::String(_) => Ok(()),
823            CallbackArgument::Iterator(x) => self.check_iterator(x),
824            CallbackArgument::Class(x) => self.check_class_declaration(x),
825            CallbackArgument::Struct(x) => self.check_struct_declaration(&x.declaration()),
826        }
827    }
828
829    fn check_callback_return_value(&self, arg: &CallbackReturnValue) -> BindResult<()> {
830        match arg {
831            CallbackReturnValue::Basic(x) => self.check_basic_type(x),
832            CallbackReturnValue::Struct(x) => self.check_struct_declaration(&x.declaration()),
833        }
834    }
835
836    fn check_basic_type(&self, arg: &BasicType) -> BindResult<()> {
837        match arg {
838            BasicType::Primitive(_) => Ok(()),
839            BasicType::Duration(_) => Ok(()),
840            BasicType::Enum(x) => self.check_enum(x),
841        }
842    }
843
844    fn check_function_return_type(&self, value: &FunctionReturnValue) -> BindResult<()> {
845        match value {
846            FunctionReturnValue::Basic(x) => self.check_basic_type(x),
847            FunctionReturnValue::PrimitiveRef(_) => Ok(()),
848            FunctionReturnValue::String(_) => Ok(()),
849            FunctionReturnValue::ClassRef(x) => self.check_class_declaration(x),
850            FunctionReturnValue::Struct(x) => self.check_struct_declaration(&x.declaration()),
851            FunctionReturnValue::StructRef(x) => self.check_struct_declaration(x.untyped()),
852        }
853    }
854
855    fn check_iterator(&self, iter: &AbstractIteratorHandle) -> BindResult<()> {
856        if self.fields.iterators.contains(iter) {
857            Ok(())
858        } else {
859            Err(BindingErrorVariant::NotPartOfThisLibrary {
860                name: iter.iter_class.name.clone(),
861            }
862            .into())
863        }
864    }
865
866    fn check_collection(&self, collection: &CollectionHandle) -> BindResult<()> {
867        if self.fields.collections.contains(collection) {
868            Ok(())
869        } else {
870            Err(BindingErrorVariant::NotPartOfThisLibrary {
871                name: collection.collection_class.name.clone(),
872            }
873            .into())
874        }
875    }
876}