oo_bindgen/model/
class.rs

1use std::rc::Rc;
2
3use crate::model::*;
4
5/// Different types of classes
6#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub(crate) enum ClassType {
8    /// A normal user class which will have a constructor, destructor, methods, etc
9    Normal,
10    /// An iterator class
11    Iterator,
12    /// A collection class
13    Collection,
14}
15
16/// C-style structure forward declaration
17#[derive(Debug)]
18pub struct ClassDeclaration {
19    pub(crate) name: Name,
20    pub(crate) class_type: ClassType,
21    pub(crate) settings: Rc<LibrarySettings>,
22}
23
24#[derive(Debug, Clone)]
25pub(crate) struct IteratorClassDeclaration {
26    pub(crate) inner: ClassDeclarationHandle,
27}
28
29impl IteratorClassDeclaration {
30    pub(crate) fn new(inner: ClassDeclarationHandle) -> Self {
31        Self { inner }
32    }
33}
34
35#[derive(Debug, Clone)]
36pub(crate) struct CollectionClassDeclaration {
37    pub(crate) inner: ClassDeclarationHandle,
38}
39
40impl CollectionClassDeclaration {
41    pub(crate) fn new(inner: ClassDeclarationHandle) -> Self {
42        Self { inner }
43    }
44}
45
46impl ClassDeclaration {
47    pub(crate) fn new(name: Name, class_type: ClassType, settings: Rc<LibrarySettings>) -> Self {
48        Self {
49            name,
50            class_type,
51            settings,
52        }
53    }
54}
55
56pub type ClassDeclarationHandle = Handle<ClassDeclaration>;
57
58/// Represents an instance method on a class
59#[derive(Debug, Clone)]
60pub struct Method<T>
61where
62    T: DocReference,
63{
64    pub(crate) name: Name,
65    pub(crate) associated_class: Handle<ClassDeclaration>,
66    pub(crate) native_function: Handle<Function<T>>,
67}
68
69impl Method<Unvalidated> {
70    pub(crate) fn new(
71        name: Name,
72        associated_class: Handle<ClassDeclaration>,
73        function: Handle<Function<Unvalidated>>,
74    ) -> Self {
75        Self {
76            name,
77            associated_class,
78            native_function: function,
79        }
80    }
81
82    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Method<Validated>> {
83        Ok(Method {
84            name: self.name.clone(),
85            associated_class: self.associated_class.clone(),
86            native_function: self.native_function.validate(lib)?,
87        })
88    }
89}
90
91pub type MethodHandle = Method<Unvalidated>;
92
93/// represents a static method associated with a class
94///
95/// name given to the class method may differ from the name of the native function
96#[derive(Debug)]
97pub struct StaticMethod<T>
98where
99    T: DocReference,
100{
101    pub(crate) name: Name,
102    pub(crate) native_function: Handle<Function<T>>,
103}
104
105impl StaticMethod<Unvalidated> {
106    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<StaticMethod<Validated>> {
107        Ok(StaticMethod {
108            name: self.name.clone(),
109            native_function: self.native_function.validate(lib)?,
110        })
111    }
112}
113
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub(crate) enum DestructionMode {
116    /// Object is automatically deleted by the GC
117    Automatic,
118    /// Object is disposed of manually by calling a custom method
119    ///
120    /// For safety, if the user never calls the destruction method, the object
121    /// will still be deleted by the GC at some point. However, it is
122    /// strongly advised to take care of the destruction manually.
123    Custom(Name),
124    /// Object is disposed of manually by calling a dispose()/close() method
125    ///
126    /// For safety, if the user never calls the destruction method, the object
127    /// will still be deleted by the GC at some point. However, it is
128    /// strongly advised to take care of the destruction manually.
129    Dispose,
130}
131
132impl DestructionMode {
133    pub(crate) fn is_manual_destruction(&self) -> bool {
134        match self {
135            Self::Automatic => false,
136            Self::Custom(_) => true,
137            Self::Dispose => true,
138        }
139    }
140}
141
142/// Object-oriented class definition
143#[derive(Debug)]
144pub struct Class<T>
145where
146    T: DocReference,
147{
148    pub(crate) declaration: ClassDeclarationHandle,
149    pub(crate) constructor: Option<ClassConstructor<T>>,
150    pub(crate) destructor: Option<ClassDestructor<T>>,
151    pub(crate) methods: Vec<Method<T>>,
152    pub(crate) static_methods: Vec<StaticMethod<T>>,
153    pub(crate) future_methods: Vec<FutureMethod<T>>,
154    pub(crate) doc: Doc<T>,
155    pub(crate) destruction_mode: DestructionMode,
156    pub(crate) settings: Rc<LibrarySettings>,
157}
158
159impl Class<Unvalidated> {
160    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Handle<Class<Validated>>> {
161        let constructor = match &self.constructor {
162            None => None,
163            Some(x) => Some(x.validate(lib)?),
164        };
165        let destructor = match &self.destructor {
166            None => None,
167            Some(x) => Some(x.validate(lib)?),
168        };
169        let methods: BindResult<Vec<Method<Validated>>> =
170            self.methods.iter().map(|x| x.validate(lib)).collect();
171        let static_methods: BindResult<Vec<StaticMethod<Validated>>> = self
172            .static_methods
173            .iter()
174            .map(|x| x.validate(lib))
175            .collect();
176        let async_methods: BindResult<Vec<FutureMethod<Validated>>> = self
177            .future_methods
178            .iter()
179            .map(|x| x.validate(lib))
180            .collect();
181
182        Ok(Handle::new(Class {
183            declaration: self.declaration.clone(),
184            constructor,
185            destructor,
186            methods: methods?,
187            static_methods: static_methods?,
188            future_methods: async_methods?,
189            doc: self.doc.validate(self.name(), lib)?,
190            destruction_mode: self.destruction_mode.clone(),
191            settings: self.settings.clone(),
192        }))
193    }
194}
195
196impl<T> Class<T>
197where
198    T: DocReference,
199{
200    pub fn name(&self) -> &Name {
201        &self.declaration.name
202    }
203
204    pub fn declaration(&self) -> ClassDeclarationHandle {
205        self.declaration.clone()
206    }
207}
208
209impl Class<Unvalidated> {
210    pub(crate) fn find_method<S: AsRef<str>>(
211        &self,
212        method_name: S,
213    ) -> Option<(Name, FunctionHandle)> {
214        let method_name = method_name.as_ref();
215
216        for method in &self.methods {
217            if method.name.as_ref() == method_name {
218                return Some((method.name.clone(), method.native_function.clone()));
219            }
220        }
221
222        for method in &self.static_methods {
223            if method.name.as_ref() == method_name {
224                return Some((method.name.clone(), method.native_function.clone()));
225            }
226        }
227
228        for async_method in &self.future_methods {
229            if async_method.name.as_ref() == method_name {
230                return Some((
231                    async_method.name.clone(),
232                    async_method.native_function.clone(),
233                ));
234            }
235        }
236
237        None
238    }
239}
240
241pub type ClassHandle = Handle<Class<Unvalidated>>;
242
243/// Static class definition
244#[derive(Debug)]
245pub struct StaticClass<T>
246where
247    T: DocReference,
248{
249    pub(crate) name: Name,
250    pub(crate) static_methods: Vec<StaticMethod<T>>,
251    pub(crate) doc: Doc<T>,
252}
253
254impl StaticClass<Unvalidated> {
255    pub(crate) fn validate(
256        &self,
257        lib: &LibraryFields,
258    ) -> BindResult<Handle<StaticClass<Validated>>> {
259        let methods: BindResult<Vec<StaticMethod<Validated>>> = self
260            .static_methods
261            .iter()
262            .map(|x| x.validate(lib))
263            .collect();
264        Ok(Handle::new(StaticClass {
265            name: self.name.clone(),
266            static_methods: methods?,
267            doc: self.doc.validate(&self.name, lib)?,
268        }))
269    }
270}
271
272pub type StaticClassHandle = Handle<StaticClass<Unvalidated>>;