oo_bindgen/model/builder/
function.rs

1use crate::model::*;
2
3pub struct FunctionBuilder<'a> {
4    lib: &'a mut LibraryBuilder,
5    name: Name,
6    function_type: FunctionCategory,
7    return_type: OptionalReturnType<FunctionReturnValue, Unvalidated>,
8    params: Vec<Arg<FunctionArgument, Unvalidated>>,
9    doc: OptionalDoc,
10    error_type: OptionalErrorType<Unvalidated>,
11}
12
13impl<'a> FunctionBuilder<'a> {
14    pub(crate) fn new(
15        lib: &'a mut LibraryBuilder,
16        name: Name,
17        function_type: FunctionCategory,
18    ) -> Self {
19        Self {
20            lib,
21            name: name.clone(),
22            function_type,
23            return_type: OptionalReturnType::new(),
24            params: Vec::new(),
25            doc: OptionalDoc::new(name),
26            error_type: OptionalErrorType::new(),
27        }
28    }
29
30    pub fn param<T: IntoName, D: Into<DocString<Unvalidated>>, P: Into<FunctionArgument>>(
31        mut self,
32        name: T,
33        param_type: P,
34        doc: D,
35    ) -> BindResult<Self> {
36        let param_type = param_type.into();
37        let name = name.into_name()?;
38        self.params.push(Arg {
39            name,
40            arg_type: param_type,
41            doc: doc.into(),
42        });
43        Ok(self)
44    }
45
46    pub fn returns<D: Into<DocString<Unvalidated>>, T: Into<FunctionReturnValue>>(
47        mut self,
48        return_type: T,
49        doc: D,
50    ) -> BindResult<Self> {
51        self.return_type
52            .set(&self.name, return_type.into(), doc.into())?;
53        Ok(self)
54    }
55
56    pub fn fails_with(mut self, err: ErrorType<Unvalidated>) -> BindResult<Self> {
57        self.error_type.set(&self.name, &err)?;
58        Ok(self)
59    }
60
61    pub fn doc<D: Into<Doc<Unvalidated>>>(mut self, doc: D) -> BindResult<Self> {
62        self.doc.set(doc.into())?;
63        Ok(self)
64    }
65
66    pub fn build(self) -> BindResult<FunctionHandle> {
67        let handle = Handle::new(Function {
68            name: self.name,
69            category: self.function_type,
70            return_type: self.return_type,
71            arguments: self.params,
72            error_type: self.error_type,
73            settings: self.lib.clone_settings(),
74            doc: self.doc.extract()?,
75        });
76
77        self.lib
78            .add_statement(Statement::FunctionDefinition(handle.clone()))?;
79
80        Ok(handle)
81    }
82
83    /// Build a static method with a different name than the native function
84    pub fn build_static<N: IntoName>(self, name: N) -> BindResult<StaticMethod<Unvalidated>> {
85        let handle = self.build()?;
86        Ok(StaticMethod {
87            name: name.into_name()?,
88            native_function: handle,
89        })
90    }
91
92    /// Build a static method with the same name as the native function
93    pub fn build_static_with_same_name(self) -> BindResult<StaticMethod<Unvalidated>> {
94        let handle = self.build()?;
95        Ok(StaticMethod {
96            name: handle.name.clone(),
97            native_function: handle,
98        })
99    }
100}
101
102pub struct ClassMethodBuilder<'a> {
103    method_name: Name,
104    class: ClassDeclarationHandle,
105    inner: FunctionBuilder<'a>,
106}
107
108impl<'a> ClassMethodBuilder<'a> {
109    pub(crate) fn new(
110        lib: &'a mut LibraryBuilder,
111        method_name: Name,
112        class: ClassDeclarationHandle,
113    ) -> BindResult<Self> {
114        if method_name.contains(class.name.as_ref()) {
115            return Err(BindingErrorVariant::BadMethodName { class, method_name }.into());
116        }
117
118        let instance_arg_name = lib.settings().class.method_instance_argument_name.clone();
119
120        let builder = lib
121            .define_function(class.name.append(&method_name))?
122            .param(
123                instance_arg_name,
124                class.clone(),
125                format!("Instance of {{class:{}}}", class.name),
126            )?;
127
128        Ok(Self {
129            method_name,
130            class,
131            inner: builder,
132        })
133    }
134
135    pub fn param<T: IntoName, D: Into<DocString<Unvalidated>>, P: Into<FunctionArgument>>(
136        self,
137        name: T,
138        param_type: P,
139        doc: D,
140    ) -> BindResult<Self> {
141        Ok(Self {
142            method_name: self.method_name,
143            class: self.class,
144            inner: self.inner.param(name, param_type, doc)?,
145        })
146    }
147
148    pub fn returns<D: Into<DocString<Unvalidated>>, T: Into<FunctionReturnValue>>(
149        self,
150        return_type: T,
151        doc: D,
152    ) -> BindResult<Self> {
153        let return_type = return_type.into();
154        let doc = doc.into();
155        Ok(Self {
156            method_name: self.method_name,
157            class: self.class,
158            inner: self.inner.returns(return_type, doc)?,
159        })
160    }
161
162    pub fn fails_with(self, err: ErrorType<Unvalidated>) -> BindResult<Self> {
163        Ok(Self {
164            method_name: self.method_name,
165            class: self.class,
166            inner: self.inner.fails_with(err)?,
167        })
168    }
169
170    pub fn doc<D: Into<Doc<Unvalidated>>>(self, doc: D) -> BindResult<Self> {
171        Ok(Self {
172            method_name: self.method_name,
173            class: self.class,
174            inner: self.inner.doc(doc)?,
175        })
176    }
177
178    pub fn build(self) -> BindResult<Method<Unvalidated>> {
179        let function = self.inner.build()?;
180        Ok(Method::new(self.method_name, self.class, function))
181    }
182}
183
184pub struct ClassConstructorBuilder<'a> {
185    class: ClassDeclarationHandle,
186    inner: FunctionBuilder<'a>,
187}
188
189impl<'a> ClassConstructorBuilder<'a> {
190    pub(crate) fn new(
191        lib: &'a mut LibraryBuilder,
192        class: ClassDeclarationHandle,
193    ) -> BindResult<Self> {
194        let builder = lib
195            .define_function(
196                class
197                    .name
198                    .append(&lib.settings().class.class_constructor_suffix),
199            )?
200            .returns(
201                class.clone(),
202                format!("Instance of {{class:{}}}", class.name),
203            )?;
204
205        Ok(Self {
206            class,
207            inner: builder,
208        })
209    }
210
211    pub fn param<T: IntoName, D: Into<DocString<Unvalidated>>, P: Into<FunctionArgument>>(
212        self,
213        name: T,
214        param_type: P,
215        doc: D,
216    ) -> BindResult<Self> {
217        Ok(Self {
218            class: self.class,
219            inner: self.inner.param(name, param_type, doc)?,
220        })
221    }
222
223    pub fn fails_with(self, err: ErrorType<Unvalidated>) -> BindResult<Self> {
224        Ok(Self {
225            class: self.class,
226            inner: self.inner.fails_with(err)?,
227        })
228    }
229
230    pub fn doc<D: Into<Doc<Unvalidated>>>(self, doc: D) -> BindResult<Self> {
231        Ok(Self {
232            class: self.class,
233            inner: self.inner.doc(doc)?,
234        })
235    }
236
237    pub fn build(self) -> BindResult<ClassConstructor<Unvalidated>> {
238        Ok(ClassConstructor::new(self.class, self.inner.build()?))
239    }
240}
241
242pub struct FutureMethodBuilder<'a> {
243    future: FutureInterface<Unvalidated>,
244    inner: ClassMethodBuilder<'a>,
245}
246
247impl<'a> FutureMethodBuilder<'a> {
248    pub(crate) fn new(
249        lib: &'a mut LibraryBuilder,
250        method_name: Name,
251        class: ClassDeclarationHandle,
252        future: FutureInterface<Unvalidated>,
253    ) -> BindResult<Self> {
254        let builder = lib.define_method(method_name, class)?;
255
256        Ok(Self {
257            future,
258            inner: builder,
259        })
260    }
261
262    pub fn param<T: IntoName, D: Into<DocString<Unvalidated>>, P: Into<FunctionArgument>>(
263        self,
264        name: T,
265        param_type: P,
266        doc: D,
267    ) -> BindResult<Self> {
268        let name = name.into_name()?;
269        let param_type = param_type.into();
270        let builder = self.inner.param(name, param_type, doc)?;
271        Ok(Self {
272            future: self.future,
273            inner: builder,
274        })
275    }
276
277    pub fn fails_with(self, err: ErrorType<Unvalidated>) -> BindResult<Self> {
278        Ok(Self {
279            future: self.future,
280            inner: self.inner.fails_with(err)?,
281        })
282    }
283
284    pub fn doc<D: Into<Doc<Unvalidated>>>(self, doc: D) -> BindResult<Self> {
285        Ok(Self {
286            future: self.future,
287            inner: self.inner.doc(doc)?,
288        })
289    }
290
291    pub fn build(self) -> BindResult<FutureMethod<Unvalidated>> {
292        let future = self.future.clone();
293        let callback_parameter_name = self
294            .inner
295            .inner
296            .lib
297            .settings()
298            .future
299            .async_method_callback_parameter_name
300            .clone();
301        let method = self
302            .inner
303            .param(
304                callback_parameter_name,
305                FunctionArgument::Interface(self.future.interface),
306                "callback invoked when the operation completes",
307            )?
308            .build()?;
309
310        Ok(FutureMethod {
311            name: method.name,
312            associated_class: method.associated_class,
313            future,
314            native_function: method.native_function,
315        })
316    }
317}