oo_bindgen/model/
library.rs

1use std::path::PathBuf;
2use std::rc::Rc;
3
4use crate::model::*;
5
6#[derive(Clone, Debug)]
7pub(crate) enum Statement<D>
8where
9    D: DocReference,
10{
11    Constants(Handle<ConstantSet<D>>),
12    StructDeclaration(StructDeclarationHandle),
13    StructDefinition(StructType<D>),
14    EnumDefinition(Handle<Enum<D>>),
15    ErrorType(ErrorType<D>),
16    ClassDeclaration(ClassDeclarationHandle),
17    ClassDefinition(Handle<Class<D>>),
18    StaticClassDefinition(Handle<StaticClass<D>>),
19    InterfaceDefinition(InterfaceType<D>),
20    IteratorDeclaration(Handle<AbstractIterator<D>>),
21    CollectionDeclaration(Handle<Collection<D>>),
22    FunctionDefinition(Handle<Function<D>>),
23}
24
25impl Statement<Unvalidated> {
26    pub(crate) fn unique_name(&self) -> Option<&Name> {
27        match self {
28            Statement::Constants(x) => Some(&x.name),
29            Statement::StructDeclaration(x) => Some(&x.name),
30            Statement::StructDefinition(_) => {
31                // the name is shared with the declaration
32                None
33            }
34            Statement::EnumDefinition(x) => Some(&x.name),
35            Statement::ErrorType(x) => Some(&x.exception_name),
36            Statement::ClassDeclaration(x) => Some(&x.name),
37            Statement::ClassDefinition(_) => {
38                // the name is shared with the declaration
39                None
40            }
41            Statement::StaticClassDefinition(x) => Some(&x.name),
42            Statement::InterfaceDefinition(x) => Some(&x.untyped().name),
43            Statement::IteratorDeclaration(_) => {
44                // the name is derived in a language specific way
45                None
46            }
47            Statement::CollectionDeclaration(_) => {
48                // the name is derived in a language specific way
49                None
50            }
51            Statement::FunctionDefinition(x) => Some(&x.name),
52        }
53    }
54}
55
56pub struct DeveloperInfo {
57    /// Full name of the developer
58    pub name: String,
59    /// Email of the developer
60    pub email: String,
61    /// Name of the organization the developer is working for
62    pub organization: String,
63    /// Organization website URL
64    pub organization_url: String,
65}
66
67/// metadata related to the library
68pub struct LibraryInfo {
69    /// Description of the library
70    pub description: String,
71    /// URL of the project
72    pub project_url: String,
73    /// GitHub organisation and repo name (e.g. stepfunc/oo_bindgen)
74    pub repository: String,
75    /// License name
76    pub license_name: String,
77    /// Short description of the license (to put on every generated file)
78    pub license_description: Vec<String>,
79    /// Path to the license file from the root directory
80    pub license_path: PathBuf,
81    /// List of developers
82    pub developers: Vec<DeveloperInfo>,
83    /// Logo of the company (in PNG)
84    ///
85    /// Use `include_bytes` to import the data
86    pub logo_png: &'static [u8],
87}
88
89/// Settings that affect iterator function naming
90#[derive(Debug)]
91pub struct IteratorSettings {
92    /// name of the C function which retrieve's the iterator's next value
93    /// is automatically generated as `<c_ffi_prefix>_<iterator_class_name>_<next_function_suffix>`
94    pub next_function_suffix: Name,
95}
96
97impl IteratorSettings {
98    pub fn new(next_function_suffix: Name) -> IteratorSettings {
99        Self {
100            next_function_suffix,
101        }
102    }
103}
104
105impl Default for IteratorSettings {
106    fn default() -> Self {
107        Self {
108            next_function_suffix: Name::create("next").unwrap(),
109        }
110    }
111}
112
113/// Settings that affect C interface member naming
114#[derive(Debug)]
115pub struct InterfaceSettings {
116    /// Name of the C void* context variable, defaults to "ctx"
117    pub context_variable_name: Name,
118    /// Name of the function that destroys an interface when it is dropped, defaults to "on_destroy"
119    pub destroy_func_name: Name,
120}
121
122impl InterfaceSettings {
123    pub fn new(context_variable_name: Name, destroy_func_name: Name) -> Self {
124        Self {
125            context_variable_name,
126            destroy_func_name,
127        }
128    }
129}
130
131impl Default for InterfaceSettings {
132    fn default() -> Self {
133        Self {
134            context_variable_name: Name::create("ctx").unwrap(),
135            destroy_func_name: Name::create("on_destroy").unwrap(),
136        }
137    }
138}
139
140/// Settings that affect class method naming
141#[derive(Debug)]
142pub struct ClassSettings {
143    /// Methods in C always take an instance of the class at the first parameter.
144    /// This setting controls the name automatically assigned to this parameter.
145    ///
146    /// This value defaults to "instance"
147    pub method_instance_argument_name: Name,
148    /// suffix for C destructors.
149    /// The full C function name is automatically generated as `<c_ffi_prefix>_<class_name>_<class_destructor_suffix>`
150    ///
151    /// This value defaults to 'destroy'
152    pub class_destructor_suffix: Name,
153    /// suffix for C constructors.
154    /// The full C function name is automatically generated as `<c_ffi_prefix>_<class_name>_<class_constructor_suffix>`
155    ///
156    /// This value defaults to 'new'
157    pub class_constructor_suffix: Name,
158}
159
160impl ClassSettings {
161    pub fn new(
162        method_instance_argument_name: Name,
163        class_destructor_suffix: Name,
164        class_constructor_suffix: Name,
165    ) -> Self {
166        Self {
167            method_instance_argument_name,
168            class_destructor_suffix,
169            class_constructor_suffix,
170        }
171    }
172}
173
174impl Default for ClassSettings {
175    fn default() -> ClassSettings {
176        Self {
177            method_instance_argument_name: Name::create("instance").unwrap(),
178            class_destructor_suffix: Name::create("destroy").unwrap(),
179            class_constructor_suffix: Name::create("create").unwrap(),
180        }
181    }
182}
183
184/// Settings that affect how things are named in future-style callback interfaces
185#[derive(Debug)]
186pub struct FutureSettings {
187    /// The name given to the success completion method on interface
188    pub success_callback_method_name: Name,
189    /// The name given to the result parameter of the success completion method
190    pub success_single_parameter_name: Name,
191    /// The name given to the failure completion method on interface
192    pub failure_callback_method_name: Name,
193    /// The name given to the error parameter of the failure completion method
194    pub failure_single_parameter_name: Name,
195    /// The name given to the final callback parameter of the async methods
196    pub async_method_callback_parameter_name: Name,
197}
198
199impl FutureSettings {
200    pub fn new(
201        success_callback_method_name: Name,
202        success_single_parameter_name: Name,
203        failure_callback_method_name: Name,
204        failure_single_parameter_name: Name,
205        async_method_callback_parameter_name: Name,
206    ) -> Self {
207        Self {
208            success_callback_method_name,
209            success_single_parameter_name,
210            failure_callback_method_name,
211            failure_single_parameter_name,
212            async_method_callback_parameter_name,
213        }
214    }
215}
216
217impl Default for FutureSettings {
218    fn default() -> Self {
219        Self {
220            success_callback_method_name: Name::create("on_complete").unwrap(),
221            success_single_parameter_name: Name::create("result").unwrap(),
222            failure_callback_method_name: Name::create("on_failure").unwrap(),
223            failure_single_parameter_name: Name::create("error").unwrap(),
224            async_method_callback_parameter_name: Name::create("callback").unwrap(),
225        }
226    }
227}
228
229/// Settings that affect collection function naming
230#[derive(Debug)]
231pub struct CollectionSettings {
232    /// name of the C function which creates a collection
233    /// is automatically generated as `<c_ffi_prefix>_<collection_class_name>_<create_function_suffix>`
234    pub create_function_suffix: Name,
235    /// name of the C function which creates a collection
236    /// is automatically generated as `<c_ffi_prefix>_<collection_class_name>_<add_function_suffix>`
237    pub add_function_suffix: Name,
238    /// name of the C function which destroys a collection
239    /// is automatically generated as `<c_ffi_prefix>_<collection_class_name>_<destroy_function_suffix>`
240    pub destroy_function_suffix: Name,
241}
242
243impl CollectionSettings {
244    pub fn new(
245        create_function_suffix: Name,
246        add_function_suffix: Name,
247        destroy_function_suffix: Name,
248    ) -> Self {
249        Self {
250            create_function_suffix,
251            add_function_suffix,
252            destroy_function_suffix,
253        }
254    }
255}
256
257impl Default for CollectionSettings {
258    fn default() -> CollectionSettings {
259        Self {
260            create_function_suffix: Name::create("create").unwrap(),
261            add_function_suffix: Name::create("add").unwrap(),
262            destroy_function_suffix: Name::create("destroy").unwrap(),
263        }
264    }
265}
266
267/// Settings that affect the names of things
268#[derive(Debug)]
269pub struct LibrarySettings {
270    /// name of the library
271    pub name: Name,
272    /// prefix given to all API types, e.g. structs, enums, functions, etc
273    pub c_ffi_prefix: Name,
274    /// settings that control class generation
275    pub class: ClassSettings,
276    /// settings that control iterator generation
277    pub iterator: IteratorSettings,
278    /// settings that control collection generation
279    pub collection: CollectionSettings,
280    /// settings that control future-style interface generation
281    pub future: FutureSettings,
282    /// settings that control C interface member naming
283    pub interface: InterfaceSettings,
284}
285
286impl LibrarySettings {
287    /// create an RC to the settings that is cheaply cloned
288    pub fn create<S: IntoName, R: IntoName>(
289        name: S,
290        c_ffi_prefix: R,
291        class: ClassSettings,
292        iterator: IteratorSettings,
293        collection: CollectionSettings,
294        future: FutureSettings,
295        interface: InterfaceSettings,
296    ) -> BindResult<Rc<Self>> {
297        Ok(Rc::new(Self {
298            name: name.into_name()?,
299            c_ffi_prefix: c_ffi_prefix.into_name()?,
300            class,
301            iterator,
302            collection,
303            future,
304            interface,
305        }))
306    }
307}
308
309pub struct Library {
310    pub(crate) version: Version,
311    pub(crate) info: Rc<LibraryInfo>,
312    pub(crate) settings: Rc<LibrarySettings>,
313    /// history of statements from which we can find other types
314    statements: Vec<Statement<Validated>>,
315}
316
317impl Library {
318    pub(crate) fn new(
319        version: Version,
320        info: Rc<LibraryInfo>,
321        settings: Rc<LibrarySettings>,
322        statements: Vec<Statement<Validated>>,
323    ) -> Self {
324        Self {
325            version,
326            info,
327            settings,
328            statements,
329        }
330    }
331
332    pub(crate) fn statements(&self) -> impl Iterator<Item = &Statement<Validated>> {
333        self.statements.iter()
334    }
335
336    pub(crate) fn functions(&self) -> impl Iterator<Item = &Handle<Function<Validated>>> {
337        self.statements().filter_map(|statement| match statement {
338            Statement::FunctionDefinition(handle) => Some(handle),
339            _ => None,
340        })
341    }
342
343    pub(crate) fn structs(&self) -> impl Iterator<Item = &StructType<Validated>> {
344        self.statements
345            .iter()
346            .filter_map(|statement| match statement {
347                Statement::StructDefinition(x) => Some(x),
348                _ => None,
349            })
350    }
351
352    pub(crate) fn constants(&self) -> impl Iterator<Item = &Handle<ConstantSet<Validated>>> {
353        self.statements().filter_map(|statement| match statement {
354            Statement::Constants(handle) => Some(handle),
355            _ => None,
356        })
357    }
358
359    pub(crate) fn enums(&self) -> impl Iterator<Item = &Handle<Enum<Validated>>> {
360        self.statements().filter_map(|statement| match statement {
361            Statement::EnumDefinition(handle) => Some(handle),
362            _ => None,
363        })
364    }
365
366    pub(crate) fn classes(&self) -> impl Iterator<Item = &Handle<Class<Validated>>> {
367        self.statements().filter_map(|statement| match statement {
368            Statement::ClassDefinition(handle) => Some(handle),
369            _ => None,
370        })
371    }
372
373    pub(crate) fn error_types(&self) -> impl Iterator<Item = &ErrorType<Validated>> {
374        self.statements().filter_map(|statement| match statement {
375            Statement::ErrorType(err) => Some(err),
376            _ => None,
377        })
378    }
379
380    pub(crate) fn static_classes(&self) -> impl Iterator<Item = &Handle<StaticClass<Validated>>> {
381        self.statements().filter_map(|statement| match statement {
382            Statement::StaticClassDefinition(handle) => Some(handle),
383            _ => None,
384        })
385    }
386
387    pub(crate) fn untyped_interfaces(&self) -> impl Iterator<Item = &Handle<Interface<Validated>>> {
388        self.interfaces().map(|x| x.untyped())
389    }
390
391    pub(crate) fn interfaces(&self) -> impl Iterator<Item = &InterfaceType<Validated>> {
392        self.statements
393            .iter()
394            .filter_map(|statement| match statement {
395                Statement::InterfaceDefinition(t) => Some(t),
396                _ => None,
397            })
398    }
399
400    pub(crate) fn iterators(&self) -> impl Iterator<Item = &Handle<AbstractIterator<Validated>>> {
401        self.statements().filter_map(|statement| match statement {
402            Statement::IteratorDeclaration(handle) => Some(handle),
403            _ => None,
404        })
405    }
406
407    pub(crate) fn collections(&self) -> impl Iterator<Item = &Handle<Collection<Validated>>> {
408        self.statements().filter_map(|statement| match statement {
409            Statement::CollectionDeclaration(handle) => Some(handle),
410            _ => None,
411        })
412    }
413}
414
415impl From<UniversalStructDeclaration> for FunctionReturnStructDeclaration {
416    fn from(x: UniversalStructDeclaration) -> Self {
417        FunctionReturnStructDeclaration::new(x.inner)
418    }
419}