mlua_extras/typed/class/
standard.rs

1use std::{borrow::Cow, collections::BTreeMap};
2
3use mlua::{AnyUserData, FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Lua, MetaMethod};
4
5use crate::{typed::{function::Return, generator::FunctionBuilder, Func, Field}, MaybeSend};
6
7use super::{Typed, TypedDataDocumentation, TypedDataFields, TypedDataMethods, TypedMultiValue, TypedUserData};
8
9/// Type information for a lua `class`. This happens to be a [`TypedUserData`]
10#[derive(Default, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
11pub struct TypedClassBuilder {
12    pub type_doc: Option<Cow<'static, str>>,
13    queued_doc: Option<String>,
14
15    pub fields: BTreeMap<Cow<'static, str>, Field>,
16    pub static_fields: BTreeMap<Cow<'static, str>, Field>,
17    pub meta_fields: BTreeMap<Cow<'static, str>, Field>,
18    pub methods: BTreeMap<Cow<'static, str>, Func>,
19    pub meta_methods: BTreeMap<Cow<'static, str>, Func>,
20    pub functions: BTreeMap<Cow<'static, str>, Func>,
21    pub meta_functions: BTreeMap<Cow<'static, str>, Func>,
22}
23
24impl TypedClassBuilder {
25    pub fn new<T: TypedUserData>() -> Self {
26        let mut gen = Self::default();
27        T::add_documentation(&mut gen);
28        T::add_fields(&mut gen);
29        T::add_methods(&mut gen);
30        gen
31    }
32}
33
34impl<T: TypedUserData> TypedDataDocumentation<T> for TypedClassBuilder {
35    fn add(&mut self, doc: &str) -> &mut Self {
36        if let Some(type_doc) = self.type_doc.as_mut() {
37            *type_doc = format!("{type_doc}\n{doc}").into()
38        } else {
39            self.type_doc = Some(doc.to_string().into())
40        }
41        self
42    }
43}
44
45impl<'lua, T: TypedUserData> TypedDataFields<'lua, T> for TypedClassBuilder {
46    fn document(&mut self, doc: &str) -> &mut Self {
47        self.queued_doc = Some(doc.to_string());
48        self
49    }
50
51    fn add_field<V>(&mut self, name: impl AsRef<str>, _: V)
52    where
53        V: IntoLua<'lua> + Clone + 'static + Typed,
54    {
55        let name: Cow<'static, str> = name.as_ref().to_string().into();
56        self.static_fields
57            .entry(name)
58            .and_modify(|v| {
59                v.doc = self.queued_doc.take().map(|v| v.into());
60                v.ty = v.ty.clone() | V::ty();
61            })
62            .or_insert(Field {
63                ty: V::ty(),
64                doc: self.queued_doc.take().map(|v| v.into()),
65            });
66    }
67
68    fn add_field_function_set<S, A, F>(&mut self, name: &S, _: F)
69    where
70        S: AsRef<str> + ?Sized,
71        A: FromLua<'lua> + Typed,
72        F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> mlua::Result<()>,
73    {
74        let name: Cow<'static, str> = name.as_ref().to_string().into();
75        self.static_fields
76            .entry(name)
77            .and_modify(|v| {
78                v.doc = self.queued_doc.take().map(|v| v.into());
79                v.ty = v.ty.clone() | A::ty();
80            })
81            .or_insert(Field {
82                ty: A::ty(),
83                doc: self.queued_doc.take().map(|v| v.into()),
84            });
85    }
86
87    fn add_field_function_get<S, R, F>(&mut self, name: &S, _: F)
88    where
89        S: AsRef<str> + ?Sized,
90        R: IntoLua<'lua> + Typed,
91        F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> mlua::Result<R>,
92    {
93        let name: Cow<'static, str> = name.as_ref().to_string().into();
94        self.static_fields
95            .entry(name)
96            .and_modify(|v| {
97                v.doc = self.queued_doc.take().map(|v| v.into());
98                v.ty = v.ty.clone() | R::ty();
99            })
100            .or_insert(Field {
101                ty: R::ty(),
102                doc: self.queued_doc.take().map(|v| v.into()),
103            });
104    }
105
106    fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: &S, _: GET, _: SET)
107    where
108        S: AsRef<str> + ?Sized,
109        R: IntoLua<'lua> + Typed,
110        A: FromLua<'lua> + Typed,
111        GET: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> mlua::Result<R>,
112        SET: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>, A) -> mlua::Result<()>,
113    {
114        let name: Cow<'static, str> = name.as_ref().to_string().into();
115        self.static_fields
116            .entry(name)
117            .and_modify(|v| {
118                v.doc = self.queued_doc.take().map(|v| v.into());
119                v.ty = v.ty.clone() | A::ty() | R::ty();
120            })
121            .or_insert(Field {
122                ty: A::ty() | R::ty(),
123                doc: self.queued_doc.take().map(|v| v.into()),
124            });
125    }
126
127    fn add_field_method_set<S, A, M>(&mut self, name: &S, _: M)
128    where
129        S: AsRef<str> + ?Sized,
130        A: FromLua<'lua> + Typed,
131        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<()>,
132    {
133        let name: Cow<'static, str> = name.as_ref().to_string().into();
134        self.fields
135            .entry(name)
136            .and_modify(|v| {
137                v.doc = self.queued_doc.take().map(|v| v.into());
138                v.ty = v.ty.clone() | A::ty();
139            })
140            .or_insert(Field {
141                ty: A::ty(),
142                doc: self.queued_doc.take().map(|v| v.into()),
143            });
144    }
145
146    fn add_field_method_get<S, R, M>(&mut self, name: &S, _: M)
147    where
148        S: AsRef<str> + ?Sized,
149        R: IntoLua<'lua> + Typed,
150        M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> mlua::Result<R>,
151    {
152        let name: Cow<'static, str> = name.as_ref().to_string().into();
153        self.fields
154            .entry(name)
155            .and_modify(|v| {
156                v.doc = self.queued_doc.take().map(|v| v.into());
157                v.ty = v.ty.clone() | R::ty();
158            })
159            .or_insert(Field {
160                ty: R::ty(),
161                doc: self.queued_doc.take().map(|v| v.into()),
162            });
163    }
164
165    fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: &S, _: GET, _: SET)
166    where
167        S: AsRef<str> + ?Sized,
168        R: IntoLua<'lua> + Typed,
169        A: FromLua<'lua> + Typed,
170        GET: 'static + MaybeSend + Fn(&'lua Lua, &T) -> mlua::Result<R>,
171        SET: 'static + MaybeSend + Fn(&'lua Lua, &mut T, A) -> mlua::Result<()>,
172    {
173        let name: Cow<'static, str> = name.as_ref().to_string().into();
174        self.fields
175            .entry(name)
176            .and_modify(|v| {
177                v.doc = self.queued_doc.take().map(|v| v.into());
178                v.ty = v.ty.clone() | A::ty() | R::ty();
179            })
180            .or_insert(Field {
181                ty: A::ty() | R::ty(),
182                doc: self.queued_doc.take().map(|v| v.into()),
183            });
184    }
185
186    fn add_meta_field<R, F>(&mut self, meta: MetaMethod, _: F)
187    where
188        F: 'static + MaybeSend + Fn(&'lua Lua) -> mlua::Result<R>,
189        R: IntoLua<'lua> + Typed,
190    {
191        let name: Cow<'static, str> = meta.as_ref().to_string().into();
192        self.meta_fields
193            .entry(name)
194            .and_modify(|v| {
195                v.doc = self.queued_doc.take().map(|v| v.into());
196                v.ty = v.ty.clone() | R::ty();
197            })
198            .or_insert(Field {
199                ty: R::ty(),
200                doc: self.queued_doc.take().map(|v| v.into()),
201            });
202    }
203}
204
205impl<'lua, T: TypedUserData> TypedDataMethods<'lua, T> for TypedClassBuilder {
206    fn document(&mut self, documentation: &str) -> &mut Self {
207        self.queued_doc = Some(documentation.to_string());
208        self
209    }
210
211    fn add_method<S, A, R, M>(&mut self, name: &S, _: M)
212    where
213        S: ?Sized + AsRef<str>,
214        A: FromLuaMulti<'lua> + TypedMultiValue,
215        R: IntoLuaMulti<'lua> + TypedMultiValue,
216        M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
217    {
218        let name: Cow<'static, str> = name.as_ref().to_string().into();
219        self.methods.insert(
220            name,
221            Func {
222                params: A::get_types_as_params(),
223                returns: R::get_types_as_returns(),
224                doc: self.queued_doc.take().map(|v| v.into()),
225            },
226        );
227    }
228
229    fn add_method_with<S, A, R, M, G>(&mut self, name: &S, _method: M, generator: G)
230        where
231            S: ?Sized + AsRef<str>,
232            A: FromLuaMulti<'lua> + TypedMultiValue,
233            R: IntoLuaMulti<'lua> + TypedMultiValue,
234            M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
235            G: Fn(&mut FunctionBuilder<A, R>) {
236        
237        let mut builder = FunctionBuilder::<A, R>::default();
238        generator(&mut builder);
239
240        let name: Cow<'static, str> = name.as_ref().to_string().into();
241        self.methods.insert(
242            name,
243            Func {
244                params: builder.params,
245                returns: builder.returns,
246                doc: self.queued_doc.take().map(|v| v.into()),
247            },
248        );
249    }
250
251    fn add_function<S, A, R, F>(&mut self, name: &S, _: F)
252    where
253        S: ?Sized + AsRef<str>,
254        A: FromLuaMulti<'lua> + TypedMultiValue,
255        R: IntoLuaMulti<'lua> + TypedMultiValue,
256        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
257    {
258        let name: Cow<'static, str> = name.as_ref().to_string().into();
259        self.functions.insert(
260            name,
261            Func {
262                params: A::get_types_as_params(),
263                returns: R::get_types_as_returns(),
264                doc: self.queued_doc.take().map(|v| v.into()),
265            },
266        );
267    }
268
269    fn add_function_with<S, A, R, F, G>(&mut self, name: &S, _function: F, generator: G)
270        where
271            S: ?Sized + AsRef<str>,
272            A: FromLuaMulti<'lua> + TypedMultiValue,
273            R: IntoLuaMulti<'lua> + TypedMultiValue,
274            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
275            G: Fn(&mut FunctionBuilder<A, R>) {
276        
277        let mut builder = FunctionBuilder::<A, R>::default();
278        generator(&mut builder);
279
280        let name: Cow<'static, str> = name.as_ref().to_string().into();
281        self.functions.insert(
282            name,
283            Func {
284                params: builder.params,
285                returns: builder.returns,
286                doc: self.queued_doc.take().map(|v| v.into()),
287            },
288        );
289    }
290
291    fn add_method_mut<S, A, R, M>(&mut self, name: &S, _: M)
292    where
293        S: ?Sized + AsRef<str>,
294        A: FromLuaMulti<'lua> + TypedMultiValue,
295        R: IntoLuaMulti<'lua> + TypedMultiValue,
296        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
297    {
298        let name: Cow<'static, str> = name.as_ref().to_string().into();
299        self.methods.insert(
300            name,
301            Func {
302                params: A::get_types_as_params(),
303                returns: R::get_types_as_returns(),
304                doc: self.queued_doc.take().map(|v| v.into()),
305            },
306        );
307    }
308
309    fn add_method_mut_with<S, A, R, M, G>(&mut self, name: &S, _method: M, generator: G)
310        where
311            S: ?Sized + AsRef<str>,
312            A: FromLuaMulti<'lua> + TypedMultiValue,
313            R: IntoLuaMulti<'lua> + TypedMultiValue,
314            M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
315            G: Fn(&mut FunctionBuilder<A, R>) {
316        
317        let mut builder = FunctionBuilder::<A, R>::default();
318        generator(&mut builder);
319
320        let name: Cow<'static, str> = name.as_ref().to_string().into();
321        self.methods.insert(
322            name,
323            Func {
324                params: builder.params,
325                returns: builder.returns,
326                doc: self.queued_doc.take().map(|v| v.into()),
327            },
328        );
329    }
330
331    fn add_meta_method<A, R, M>(&mut self, meta: MetaMethod, _: M)
332    where
333        A: FromLuaMulti<'lua> + TypedMultiValue,
334        R: IntoLuaMulti<'lua> + TypedMultiValue,
335        M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
336    {
337        let name: Cow<'static, str> = meta.as_ref().to_string().into();
338        self.meta_methods.insert(
339            name,
340            Func {
341                params: A::get_types_as_params(),
342                returns: R::get_types_as_returns(),
343                doc: self.queued_doc.take().map(|v| v.into()),
344            },
345        );
346    }
347
348    fn add_meta_method_with<A, R, M, G>(&mut self, meta: MetaMethod, _method: M, generator: G)
349        where
350            A: FromLuaMulti<'lua> + TypedMultiValue,
351            R: IntoLuaMulti<'lua> + TypedMultiValue,
352            M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
353            G: Fn(&mut FunctionBuilder<A, R>) {
354        
355        let mut builder = FunctionBuilder::<A, R>::default();
356        generator(&mut builder);
357
358        let name: Cow<'static, str> = meta.as_ref().to_string().into();
359        self.meta_methods.insert(
360            name,
361            Func {
362                params: builder.params,
363                returns: builder.returns,
364                doc: self.queued_doc.take().map(|v| v.into()),
365            },
366        );
367    }
368
369    #[cfg(feature = "async")]
370    fn add_async_method<'s, S: ?Sized + AsRef<str>, A, R, M, MR>(&mut self, name: &S, _: M)
371    where
372        'lua: 's,
373        T: 'static,
374        M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
375        A: FromLuaMulti<'lua> + TypedMultiValue,
376        MR: std::future::Future<Output = mlua::Result<R>> + 's,
377        R: IntoLuaMulti<'lua> + TypedMultiValue,
378    {
379        let name: Cow<'static, str> = name.as_ref().to_string().into();
380        self.methods.insert(
381            name,
382            Func {
383                params: A::get_types_as_params(),
384                returns: R::get_types_as_returns(),
385                doc: self.queued_doc.take().map(|v| v.into()),
386            },
387        );
388    }
389
390    #[cfg(feature = "async")]
391    fn add_async_method_with<'s, S: ?Sized + AsRef<str>, A, R, M, MR, G>(&mut self, name: &S, _method: M, generator: G)
392        where
393            'lua: 's,
394            T: 'static,
395            M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
396            A: FromLuaMulti<'lua> + TypedMultiValue,
397            MR: std::future::Future<Output = mlua::Result<R>> + 's,
398            R: IntoLuaMulti<'lua> + TypedMultiValue,
399            G: Fn(&mut FunctionBuilder<A, R>) {
400        
401        let mut builder = FunctionBuilder::<A, R>::default();
402        generator(&mut builder);
403
404        let name: Cow<'static, str> = name.as_ref().to_string().into();
405        self.methods.insert(
406            name,
407            Func {
408                params: builder.params,
409                returns: builder.returns,
410                doc: self.queued_doc.take().map(|v| v.into()),
411            },
412        );
413    }
414
415    #[cfg(feature = "async")]
416    fn add_async_method_mut<'s, S: ?Sized + AsRef<str>, A, R, M, MR>(&mut self, name: &S, method: M)
417        where
418            'lua: 's,
419            T: 'static,
420            M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
421            A: FromLuaMulti<'lua> + TypedMultiValue,
422            MR: std::future::Future<Output = mlua::Result<R>> + 's,
423            R: IntoLuaMulti<'lua> + TypedMultiValue {
424        
425        let name: Cow<'static, str> = name.as_ref().to_string().into();
426        self.methods.insert(
427            name,
428            Func {
429                params: A::get_types_as_params(),
430                returns: R::get_types_as_returns(),
431                doc: self.queued_doc.take().map(|v| v.into()),
432            },
433        );
434    }
435
436    #[cfg(feature = "async")]
437    fn add_async_method_mut_with<'s, S: ?Sized + AsRef<str>, A, R, M, MR, G>(&mut self, name: &S, _method: M, generator: G)
438        where
439            'lua: 's,
440            T: 'static,
441            M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
442            A: FromLuaMulti<'lua> + TypedMultiValue,
443            MR: std::future::Future<Output = mlua::Result<R>> + 's,
444            R: IntoLuaMulti<'lua> + TypedMultiValue,
445            G: Fn(&mut FunctionBuilder<A, R>) {
446        
447        let mut builder = FunctionBuilder::<A, R>::default();
448        generator(&mut builder);
449
450        let name: Cow<'static, str> = name.as_ref().to_string().into();
451        self.methods.insert(
452            name,
453            Func {
454                params: builder.params,
455                returns: builder.returns,
456                doc: self.queued_doc.take().map(|v| v.into()),
457            },
458        );
459    }
460
461    fn add_function_mut<S, A, R, F>(&mut self, name: &S, _: F)
462    where
463        S: ?Sized + AsRef<str>,
464        A: FromLuaMulti<'lua> + TypedMultiValue,
465        R: IntoLuaMulti<'lua> + TypedMultiValue,
466        F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
467    {
468        let name: Cow<'static, str> = name.as_ref().to_string().into();
469        self.functions.insert(
470            name,
471            Func {
472                params: A::get_types_as_params(),
473                returns: R::get_types_as_returns(),
474                doc: self.queued_doc.take().map(|v| v.into()),
475            },
476        );
477    }
478
479    fn add_function_mut_with<S, A, R, F, G>(&mut self, name: &S, _function: F, generator: G)
480        where
481            S: ?Sized + AsRef<str>,
482            A: FromLuaMulti<'lua> + TypedMultiValue,
483            R: IntoLuaMulti<'lua> + TypedMultiValue,
484            F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
485            G: Fn(&mut FunctionBuilder<A, R>) {
486        
487        let mut builder = FunctionBuilder::<A, R>::default();
488        generator(&mut builder);
489
490        let name: Cow<'static, str> = name.as_ref().to_string().into();
491        self.functions.insert(
492            name,
493            Func {
494                params: builder.params,
495                returns: builder.returns,
496                doc: self.queued_doc.take().map(|v| v.into()),
497            },
498        );
499    }
500
501    fn add_meta_function<A, R, F>(&mut self, meta: MetaMethod, _: F)
502    where
503        A: FromLuaMulti<'lua> + TypedMultiValue,
504        R: IntoLuaMulti<'lua> + TypedMultiValue,
505        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
506    {
507        let name: Cow<'static, str> = meta.as_ref().to_string().into();
508        self.meta_functions.insert(
509            name,
510            Func {
511                params: A::get_types_as_params(),
512                returns: R::get_types_as_returns(),
513                doc: self.queued_doc.take().map(|v| v.into()),
514            },
515        );
516    }
517
518    fn add_meta_function_with<A, R, F, G>(&mut self, meta: MetaMethod, _function: F, generator: G)
519        where
520            A: FromLuaMulti<'lua> + TypedMultiValue,
521            R: IntoLuaMulti<'lua> + TypedMultiValue,
522            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
523            G: Fn(&mut FunctionBuilder<A, R>) {
524        
525        let mut builder = FunctionBuilder::<A, R>::default();
526        generator(&mut builder);
527
528        let name: Cow<'static, str> = meta.as_ref().to_string().into();
529        self.functions.insert(
530            name,
531            Func {
532                params: builder.params,
533                returns: builder.returns,
534                doc: self.queued_doc.take().map(|v| v.into()),
535            },
536        );
537    }
538
539    #[cfg(feature = "async")]
540    fn add_async_function<S: ?Sized, A, R, F, FR>(&mut self, name: &S, _: F)
541    where
542        S: AsRef<str>,
543        A: FromLuaMulti<'lua> + TypedMultiValue,
544        R: IntoLuaMulti<'lua> + TypedMultiValue,
545        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
546        FR: 'lua + std::future::Future<Output = mlua::Result<R>>,
547    {
548        let name: Cow<'static, str> = name.as_ref().to_string().into();
549        self.functions.insert(
550            name,
551            Func {
552                params: A::get_types_as_params(),
553                returns: R::get_types_as_returns(),
554                doc: self.queued_doc.take().map(|v| v.into()),
555            },
556        );
557    }
558
559    #[cfg(feature = "async")]
560    fn add_async_function_with<S: ?Sized, A, R, F, FR, G>(&mut self, name: &S, _function: F, generator: G)
561        where
562            S: AsRef<str>,
563            A: FromLuaMulti<'lua> + TypedMultiValue,
564            R: IntoLuaMulti<'lua> + TypedMultiValue,
565            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
566            FR: 'lua + std::future::Future<Output = mlua::Result<R>>,
567            G: Fn(&mut FunctionBuilder<A, R>) {
568        
569        let mut builder = FunctionBuilder::<A, R>::default();
570        generator(&mut builder);
571
572        let name: Cow<'static, str> = name.as_ref().to_string().into();
573        self.functions.insert(
574            name,
575            Func {
576                params: builder.params,
577                returns: builder.returns,
578                doc: self.queued_doc.take().map(|v| v.into()),
579            },
580        );
581    }
582
583    fn add_meta_method_mut<A, R, M>(&mut self, meta: MetaMethod, _: M)
584    where
585        A: FromLuaMulti<'lua> + TypedMultiValue,
586        R: IntoLuaMulti<'lua> + TypedMultiValue,
587        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
588    {
589        let name: Cow<'static, str> = meta.as_ref().to_string().into();
590        self.meta_methods.insert(
591            name,
592            Func {
593                params: A::get_types_as_params(),
594                returns: R::get_types_as_returns(),
595                doc: self.queued_doc.take().map(|v| v.into()),
596            },
597        );
598    }
599    
600    fn add_meta_method_mut_with<A, R, M, G>(&mut self, meta: MetaMethod, _method: M, generator: G)
601        where
602            A: FromLuaMulti<'lua> + TypedMultiValue,
603            R: IntoLuaMulti<'lua> + TypedMultiValue,
604            M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
605            G: Fn(&mut FunctionBuilder<A, R>) {
606        
607        let mut builder = FunctionBuilder::<A, R>::default();
608        generator(&mut builder);
609
610        let name: Cow<'static, str> = meta.as_ref().to_string().into();
611        self.meta_methods.insert(
612            name,
613            Func {
614                params: builder.params,
615                returns: builder.returns,
616                doc: self.queued_doc.take().map(|v| v.into()),
617            },
618        );
619    }
620
621    fn add_meta_function_mut<A, R, F>(&mut self, meta: MetaMethod, _: F)
622    where
623        A: FromLuaMulti<'lua> + TypedMultiValue,
624        R: IntoLuaMulti<'lua> + TypedMultiValue,
625        F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
626    {
627        let name: Cow<'static, str> = meta.as_ref().to_string().into();
628        self.meta_functions.insert(
629            name,
630            Func {
631                params: A::get_types_as_params(),
632                returns: R::get_types().into_iter().map(|ty| Return { doc: None, ty }).collect(),
633                doc: self.queued_doc.take().map(|v| v.into()),
634            },
635        );
636    }
637
638    fn add_meta_function_mut_with<A, R, F, G>(&mut self, meta: MetaMethod, _function: F, generator: G)
639        where
640            A: FromLuaMulti<'lua> + TypedMultiValue,
641            R: IntoLuaMulti<'lua> + TypedMultiValue,
642            F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
643            G: Fn(&mut FunctionBuilder<A, R>) {
644        
645        let mut builder = FunctionBuilder::<A, R>::default();
646        generator(&mut builder);
647
648        let name: Cow<'static, str> = meta.as_ref().to_string().into();
649        self.meta_functions.insert(
650            name,
651            Func {
652                params: builder.params,
653                returns: builder.returns,
654                doc: self.queued_doc.take().map(|v| v.into()),
655            },
656        );
657    }
658}