mlua_extras/typed/class/
standard.rs

1use std::{any::Any, borrow::Cow, collections::BTreeMap};
2
3use mlua::{AnyUserData, FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Lua, MetaMethod};
4
5use crate::{typed::{function::Return, generator::FunctionBuilder, Field, Func, Index, IntoDocComment, Type}, 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, Hash)]
11pub struct TypedClassBuilder {
12    pub type_doc: Option<Cow<'static, str>>,
13    queued_doc: Option<String>,
14
15    pub fields: BTreeMap<Index, Field>,
16    pub static_fields: BTreeMap<Index, Field>,
17    pub meta_fields: BTreeMap<Index, Field>,
18    pub methods: BTreeMap<Index, Func>,
19    pub meta_methods: BTreeMap<Index, Func>,
20    pub functions: BTreeMap<Index, Func>,
21    pub meta_functions: BTreeMap<Index, Func>,
22}
23
24impl From<TypedClassBuilder> for Type {
25    fn from(value: TypedClassBuilder) -> Self {
26        Type::Class(Box::new(value))
27    }
28}
29
30impl TypedClassBuilder {
31    pub fn new<T: TypedUserData>() -> Self {
32        let mut gen = Self::default();
33        T::add_documentation(&mut gen);
34        T::add_fields(&mut gen);
35        T::add_methods(&mut gen);
36        gen
37    }
38
39    /// Check if any of there are any meta fields, functions, or methods present
40    pub fn is_meta_empty(&self) -> bool {
41        self.meta_fields.is_empty()
42            && self.meta_functions.is_empty()
43            && self.meta_methods.is_empty()
44    }
45
46    /// Creates a new typed field and adds it to the class's type information
47    ///
48    /// # Example
49    ///
50    /// ```
51    /// use mlua_extras::typed::{TypedClassBuilder, Type};
52    ///
53    /// static NAME: &str = "mlua_extras";
54    ///
55    /// TypedClassBuilder::default()
56    ///     .field("data1", Type::string() | Type::nil(), "doc comment goes last")
57    ///     .field("data2", Type::array(Type::string()), ()) // Can also use `None` instead of `()`
58    ///     .field("message", Type::string(), foramt!("A message for {NAME}"))
59    /// ```
60    pub fn field(mut self, key: impl Into<Index>, ty: Type, doc: impl IntoDocComment) -> Self {
61        self.fields.insert(key.into(), Field::new(ty, doc));
62        self
63    }
64
65    /// Creates a new typed function and adds it to the class's type information
66    ///
67    /// # Example
68    ///
69    /// ```
70    /// use mlua_extras::typed::{TypedClassBuilder, Type};
71    ///
72    /// TypedClassBuilder::default()
73    ///     .function::<String, ()>("greet", "Greet the given name")
74    ///     // Can use `None` instead of `()` for specifying the doc comment
75    ///     .function::<String, ()>("hello", ())
76    /// ```
77    pub fn function<Params, Returns>(mut self, key: impl Into<Index>, doc: impl IntoDocComment) -> Self
78    where
79        Params: TypedMultiValue,
80        Returns: TypedMultiValue,
81    {
82        self.functions.insert(key.into(), Func::new::<Params, Returns>(doc));
83        self
84    }
85
86    /// Same as [`function`][TypedClassBuilder::function] but with an extra generator function
87    /// parameter.
88    ///
89    /// This extra parameter allows for customization of parameter names, types, and doc comments
90    /// along with return types and doc comments.
91    ///
92    /// # Example
93    ///
94    /// ```
95    /// use mlua_extras::typed::{TypedClassBuilder, Type};
96    ///
97    /// TypedClassBuilder::default()
98    ///     // Can use `None` instead of `()` for specifying the doc comment
99    ///     .function_with::<String, String>("getMessage", (), |func| {
100    ///         func.param(0, |param| param.name("name").doc("Name to use when constructing the message"));
101    ///         func.ret(0, |ret| ret.doc("Message constructed using the provided name"))
102    ///     })
103    /// ```
104    pub fn function_with<Params, Returns, F, R>(mut self, key: impl Into<Index>, doc: impl IntoDocComment, generator: F) -> Self
105    where
106        Params: TypedMultiValue,
107        Returns: TypedMultiValue,
108        F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
109        R: Any,
110    {
111        let mut builder = FunctionBuilder::default();
112        generator(&mut builder);
113
114        self.functions.insert(key.into(), Func {
115            params: builder.params,
116            returns: builder.returns,
117            doc: doc.into_doc_comment()
118        });
119        self
120    }
121
122    /// Creates a new typed method and adds it to the class's type information.
123    ///
124    /// As with methods in lua, the `self` parameter is implicit and has the same type as the
125    /// parent class.
126    ///
127    /// # Example
128    ///
129    /// ```
130    /// use mlua_extras::typed::{TypedClassBuilder, Type};
131    ///
132    /// TypedClassBuilder::default()
133    ///     .method::<String, ()>("greet", "Greet the given name")
134    ///     // Can use `None` instead of `()` for specifying the doc comment
135    ///     .method::<String, ()>("hello", ())
136    /// ```
137    pub fn method<Params, Returns>(mut self, key: impl Into<Index>, doc: impl IntoDocComment) -> Self
138    where
139        Params: TypedMultiValue,
140        Returns: TypedMultiValue,
141    {
142        self.methods.insert(key.into(), Func::new::<Params, Returns>(doc));
143        self
144    }
145
146    /// Same as [`method`][TypedClassBuilder::method] but with an extra generator function
147    /// parameter.
148    ///
149    /// This extra parameter allows for customization of parameter names, types, and doc comments
150    /// along with return types and doc comments.
151    ///
152    /// # Example
153    ///
154    /// ```
155    /// use mlua_extras::typed::{TypedClassBuilder, Type};
156    ///
157    /// TypedClassBuilder::default()
158    ///     // Can use `None` instead of `()` for specifying the doc comment
159    ///     .method_with::<String, String>("getMessage", (), |func| {
160    ///         func.param(0, |param| param.name("name").doc("Name to use when constructing the message"));
161    ///         func.ret(0, |ret| ret.doc("Message constructed using the provided name"))
162    ///     })
163    /// ```
164    pub fn method_with<Params, Returns, F, R>(mut self, key: impl Into<Index>, doc: impl IntoDocComment, generator: F) -> Self
165    where
166        Params: TypedMultiValue,
167        Returns: TypedMultiValue,
168        F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
169        R: Any,
170    {
171        let mut builder = FunctionBuilder::default();
172        generator(&mut builder);
173
174        self.methods.insert(key.into(), Func {
175            params: builder.params,
176            returns: builder.returns,
177            doc: doc.into_doc_comment()
178        });
179        self
180    }
181
182    /// Creates a new typed field and adds it to the class's meta type information
183    ///
184    /// # Example
185    ///
186    /// ```
187    /// use mlua_extras::typed::{TypedClassBuilder, Type};
188    ///
189    /// static NAME: &str = "mlua_extras";
190    ///
191    /// TypedClassBuilder::default()
192    ///     .meta_field("data1", Type::string() | Type::nil(), "doc comment goes last")
193    ///     .meta_field("data2", Type::array(Type::string()), ()) // Can also use `None` instead of `()`
194    ///     .meta_field("message", Type::string(), foramt!("A message for {NAME}"))
195    /// ```
196    pub fn meta_field(mut self, key: impl Into<Index>, ty: Type, doc: impl IntoDocComment) -> Self {
197        self.meta_fields.insert(key.into(), Field::new(ty, doc));
198        self
199    }
200
201    /// Creates a new typed function and adds it to the class's meta type information
202    ///
203    /// # Example
204    ///
205    /// ```
206    /// use mlua_extras::typed::{TypedClassBuilder, Type};
207    ///
208    /// TypedClassBuilder::default()
209    ///     .meta_function::<String, ()>("greet", "Greet the given name")
210    ///     // Can use `None` instead of `()` for specifying the doc comment
211    ///     .meta_function::<String, ()>("hello", ())
212    /// ```
213    pub fn meta_function<Params, Returns>(mut self, key: impl Into<Index>, doc: impl IntoDocComment) -> Self
214    where
215        Params: TypedMultiValue,
216        Returns: TypedMultiValue,
217    {
218        self.meta_functions.insert(key.into(), Func::new::<Params, Returns>(doc));
219        self
220    }
221
222    /// Same as [`meta_function`][TypedClassBuilder::meta_function] but with an extra generator function
223    /// parameter.
224    ///
225    /// This extra parameter allows for customization of parameter names, types, and doc comments
226    /// along with return types and doc comments.
227    ///
228    /// # Example
229    ///
230    /// ```
231    /// use mlua_extras::typed::{TypedClassBuilder, Type};
232    ///
233    /// TypedClassBuilder::default()
234    ///     // Can use `None` instead of `()` for specifying the doc comment
235    ///     .meta_function_with::<String, String>("getMessage", (), |func| {
236    ///         func.param(0, |param| param.name("name").doc("Name to use when constructing the message"));
237    ///         func.ret(0, |ret| ret.doc("Message constructed using the provided name"))
238    ///     })
239    /// ```
240    pub fn meta_function_with<Params, Returns, F, R>(mut self, key: impl Into<Index>, doc: impl IntoDocComment, generator: F) -> Self
241    where
242        F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
243        R: Any,
244        Params: TypedMultiValue,
245        Returns: TypedMultiValue,
246    {
247        let mut builder = FunctionBuilder::default();
248        generator(&mut builder);
249
250        self.meta_functions.insert(key.into(), Func {
251            params: builder.params,
252            returns: builder.returns,
253            doc: doc.into_doc_comment()
254        });
255        self
256    }
257
258    /// Creates a new typed method and adds it to the class's type information.
259    ///
260    /// As with methods in lua, the `self` parameter is implicit and has the same type as the
261    /// parent class.
262    ///
263    /// # Example
264    ///
265    /// ```
266    /// use mlua_extras::typed::{TypedClassBuilder, Type};
267    ///
268    /// static NAME: &str = "mlua_extras";
269    ///
270    /// TypedClassBuilder::default()
271    ///     .method::<String, ()>("greet", "Greet the given name")
272    ///     // Can use `None` instead of `()` for specifying the doc comment
273    ///     .method::<String, ()>("hello", ())
274    /// ```
275    pub fn meta_method<Params, Returns>(mut self, key: impl Into<Index>, doc: impl IntoDocComment) -> Self
276    where
277        Params: TypedMultiValue,
278        Returns: TypedMultiValue,
279    {
280        self.meta_methods.insert(key.into(), Func::new::<Params, Returns>(doc));
281        self
282    }
283
284    /// Same as [`meta_method`][TypedClassBuilder::meta_method] but with an extra generator function
285    /// parameter.
286    ///
287    /// This extra parameter allows for customization of parameter names, types, and doc comments
288    /// along with return types and doc comments.
289    ///
290    /// # Example
291    ///
292    /// ```
293    /// use mlua_extras::typed::{TypedClassBuilder, Type};
294    ///
295    /// TypedClassBuilder::default()
296    ///     // Can use `None` instead of `()` for specifying the doc comment
297    ///     .meta_method_with::<String, String>("getMessage", (), |func| {
298    ///         func.param(0, |param| param.name("name").doc("Name to use when constructing the message"));
299    ///         func.ret(0, |ret| ret.doc("Message constructed using the provided name"))
300    ///     })
301    /// ```
302    pub fn meta_method_with<Params, Returns, F, R>(mut self, key: impl Into<Index>, doc: impl IntoDocComment, generator: F) -> Self
303    where
304        F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
305        R: Any,
306        Params: TypedMultiValue,
307        Returns: TypedMultiValue,
308    {
309        let mut builder = FunctionBuilder::default();
310        generator(&mut builder);
311
312        self.meta_methods.insert(key.into(), Func {
313            params: builder.params,
314            returns: builder.returns,
315            doc: doc.into_doc_comment()
316        });
317        self
318    }
319}
320
321impl<T: TypedUserData> TypedDataDocumentation<T> for TypedClassBuilder {
322    fn add(&mut self, doc: &str) -> &mut Self {
323        if let Some(type_doc) = self.type_doc.as_mut() {
324            *type_doc = format!("{type_doc}\n{doc}").into()
325        } else {
326            self.type_doc = Some(doc.to_string().into())
327        }
328        self
329    }
330}
331
332impl<'lua, T: TypedUserData> TypedDataFields<'lua, T> for TypedClassBuilder {
333    fn document(&mut self, doc: &str) -> &mut Self {
334        self.queued_doc = Some(doc.to_string());
335        self
336    }
337
338    fn add_field<V>(&mut self, name: impl AsRef<str>, _: V)
339    where
340        V: IntoLua<'lua> + Clone + 'static + Typed,
341    {
342        let name: Cow<'static, str> = name.as_ref().to_string().into();
343        self.static_fields
344            .entry(name.into())
345            .and_modify(|v| {
346                v.doc = self.queued_doc.take().map(|v| v.into());
347                v.ty = v.ty.clone() | V::ty();
348            })
349            .or_insert(Field {
350                ty: V::ty(),
351                doc: self.queued_doc.take().map(|v| v.into()),
352            });
353    }
354
355    fn add_field_function_set<S, A, F>(&mut self, name: &S, _: F)
356    where
357        S: AsRef<str> + ?Sized,
358        A: FromLua<'lua> + Typed,
359        F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> mlua::Result<()>,
360    {
361        let name: Cow<'static, str> = name.as_ref().to_string().into();
362        self.static_fields
363            .entry(name.into())
364            .and_modify(|v| {
365                v.doc = self.queued_doc.take().map(|v| v.into());
366                v.ty = v.ty.clone() | A::ty();
367            })
368            .or_insert(Field {
369                ty: A::ty(),
370                doc: self.queued_doc.take().map(|v| v.into()),
371            });
372    }
373
374    fn add_field_function_get<S, R, F>(&mut self, name: &S, _: F)
375    where
376        S: AsRef<str> + ?Sized,
377        R: IntoLua<'lua> + Typed,
378        F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> mlua::Result<R>,
379    {
380        let name: Cow<'static, str> = name.as_ref().to_string().into();
381        self.static_fields
382            .entry(name.into())
383            .and_modify(|v| {
384                v.doc = self.queued_doc.take().map(|v| v.into());
385                v.ty = v.ty.clone() | R::ty();
386            })
387            .or_insert(Field {
388                ty: R::ty(),
389                doc: self.queued_doc.take().map(|v| v.into()),
390            });
391    }
392
393    fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: &S, _: GET, _: SET)
394    where
395        S: AsRef<str> + ?Sized,
396        R: IntoLua<'lua> + Typed,
397        A: FromLua<'lua> + Typed,
398        GET: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> mlua::Result<R>,
399        SET: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>, A) -> mlua::Result<()>,
400    {
401        let name: Cow<'static, str> = name.as_ref().to_string().into();
402        self.static_fields
403            .entry(name.into())
404            .and_modify(|v| {
405                v.doc = self.queued_doc.take().map(|v| v.into());
406                v.ty = v.ty.clone() | A::ty() | R::ty();
407            })
408            .or_insert(Field {
409                ty: A::ty() | R::ty(),
410                doc: self.queued_doc.take().map(|v| v.into()),
411            });
412    }
413
414    fn add_field_method_set<S, A, M>(&mut self, name: &S, _: M)
415    where
416        S: AsRef<str> + ?Sized,
417        A: FromLua<'lua> + Typed,
418        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<()>,
419    {
420        let name: Cow<'static, str> = name.as_ref().to_string().into();
421        self.fields
422            .entry(name.into())
423            .and_modify(|v| {
424                v.doc = self.queued_doc.take().map(|v| v.into());
425                v.ty = v.ty.clone() | A::ty();
426            })
427            .or_insert(Field {
428                ty: A::ty(),
429                doc: self.queued_doc.take().map(|v| v.into()),
430            });
431    }
432
433    fn add_field_method_get<S, R, M>(&mut self, name: &S, _: M)
434    where
435        S: AsRef<str> + ?Sized,
436        R: IntoLua<'lua> + Typed,
437        M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> mlua::Result<R>,
438    {
439        let name: Cow<'static, str> = name.as_ref().to_string().into();
440        self.fields
441            .entry(name.into())
442            .and_modify(|v| {
443                v.doc = self.queued_doc.take().map(|v| v.into());
444                v.ty = v.ty.clone() | R::ty();
445            })
446            .or_insert(Field {
447                ty: R::ty(),
448                doc: self.queued_doc.take().map(|v| v.into()),
449            });
450    }
451
452    fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: &S, _: GET, _: SET)
453    where
454        S: AsRef<str> + ?Sized,
455        R: IntoLua<'lua> + Typed,
456        A: FromLua<'lua> + Typed,
457        GET: 'static + MaybeSend + Fn(&'lua Lua, &T) -> mlua::Result<R>,
458        SET: 'static + MaybeSend + Fn(&'lua Lua, &mut T, A) -> mlua::Result<()>,
459    {
460        let name: Cow<'static, str> = name.as_ref().to_string().into();
461        self.fields
462            .entry(name.into())
463            .and_modify(|v| {
464                v.doc = self.queued_doc.take().map(|v| v.into());
465                v.ty = v.ty.clone() | A::ty() | R::ty();
466            })
467            .or_insert(Field {
468                ty: A::ty() | R::ty(),
469                doc: self.queued_doc.take().map(|v| v.into()),
470            });
471    }
472
473    fn add_meta_field<R, F>(&mut self, meta: MetaMethod, _: F)
474    where
475        F: 'static + MaybeSend + Fn(&'lua Lua) -> mlua::Result<R>,
476        R: IntoLua<'lua> + Typed,
477    {
478        let name: Cow<'static, str> = meta.as_ref().to_string().into();
479        self.meta_fields
480            .entry(name.into())
481            .and_modify(|v| {
482                v.doc = self.queued_doc.take().map(|v| v.into());
483                v.ty = v.ty.clone() | R::ty();
484            })
485            .or_insert(Field {
486                ty: R::ty(),
487                doc: self.queued_doc.take().map(|v| v.into()),
488            });
489    }
490}
491
492impl<'lua, T: TypedUserData> TypedDataMethods<'lua, T> for TypedClassBuilder {
493    fn document(&mut self, documentation: &str) -> &mut Self {
494        self.queued_doc = Some(documentation.to_string());
495        self
496    }
497
498    fn add_method<S, A, R, M>(&mut self, name: &S, _: M)
499    where
500        S: ?Sized + AsRef<str>,
501        A: FromLuaMulti<'lua> + TypedMultiValue,
502        R: IntoLuaMulti<'lua> + TypedMultiValue,
503        M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
504    {
505        let name: Cow<'static, str> = name.as_ref().to_string().into();
506        self.methods.insert(
507            name.into(),
508            Func {
509                params: A::get_types_as_params(),
510                returns: R::get_types_as_returns(),
511                doc: self.queued_doc.take().map(|v| v.into()),
512            },
513        );
514    }
515
516    fn add_method_with<S, A, R, M, G>(&mut self, name: &S, _method: M, generator: G)
517        where
518            S: ?Sized + AsRef<str>,
519            A: FromLuaMulti<'lua> + TypedMultiValue,
520            R: IntoLuaMulti<'lua> + TypedMultiValue,
521            M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
522            G: Fn(&mut FunctionBuilder<A, R>) {
523        
524        let mut builder = FunctionBuilder::<A, R>::default();
525        generator(&mut builder);
526
527        let name: Cow<'static, str> = name.as_ref().to_string().into();
528        self.methods.insert(
529            name.into(),
530            Func {
531                params: builder.params,
532                returns: builder.returns,
533                doc: self.queued_doc.take().map(|v| v.into()),
534            },
535        );
536    }
537
538    fn add_function<S, A, R, F>(&mut self, name: &S, _: F)
539    where
540        S: ?Sized + AsRef<str>,
541        A: FromLuaMulti<'lua> + TypedMultiValue,
542        R: IntoLuaMulti<'lua> + TypedMultiValue,
543        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
544    {
545        let name: Cow<'static, str> = name.as_ref().to_string().into();
546        self.functions.insert(
547            name.into(),
548            Func {
549                params: A::get_types_as_params(),
550                returns: R::get_types_as_returns(),
551                doc: self.queued_doc.take().map(|v| v.into()),
552            },
553        );
554    }
555
556    fn add_function_with<S, A, R, F, G>(&mut self, name: &S, _function: F, generator: G)
557        where
558            S: ?Sized + AsRef<str>,
559            A: FromLuaMulti<'lua> + TypedMultiValue,
560            R: IntoLuaMulti<'lua> + TypedMultiValue,
561            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
562            G: Fn(&mut FunctionBuilder<A, R>) {
563        
564        let mut builder = FunctionBuilder::<A, R>::default();
565        generator(&mut builder);
566
567        let name: Cow<'static, str> = name.as_ref().to_string().into();
568        self.functions.insert(
569            name.into(),
570            Func {
571                params: builder.params,
572                returns: builder.returns,
573                doc: self.queued_doc.take().map(|v| v.into()),
574            },
575        );
576    }
577
578    fn add_method_mut<S, A, R, M>(&mut self, name: &S, _: M)
579    where
580        S: ?Sized + AsRef<str>,
581        A: FromLuaMulti<'lua> + TypedMultiValue,
582        R: IntoLuaMulti<'lua> + TypedMultiValue,
583        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
584    {
585        let name: Cow<'static, str> = name.as_ref().to_string().into();
586        self.methods.insert(
587            name.into(),
588            Func {
589                params: A::get_types_as_params(),
590                returns: R::get_types_as_returns(),
591                doc: self.queued_doc.take().map(|v| v.into()),
592            },
593        );
594    }
595
596    fn add_method_mut_with<S, A, R, M, G>(&mut self, name: &S, _method: M, generator: G)
597        where
598            S: ?Sized + AsRef<str>,
599            A: FromLuaMulti<'lua> + TypedMultiValue,
600            R: IntoLuaMulti<'lua> + TypedMultiValue,
601            M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
602            G: Fn(&mut FunctionBuilder<A, R>) {
603        
604        let mut builder = FunctionBuilder::<A, R>::default();
605        generator(&mut builder);
606
607        let name: Cow<'static, str> = name.as_ref().to_string().into();
608        self.methods.insert(
609            name.into(),
610            Func {
611                params: builder.params,
612                returns: builder.returns,
613                doc: self.queued_doc.take().map(|v| v.into()),
614            },
615        );
616    }
617
618    fn add_meta_method<A, R, M>(&mut self, meta: MetaMethod, _: M)
619    where
620        A: FromLuaMulti<'lua> + TypedMultiValue,
621        R: IntoLuaMulti<'lua> + TypedMultiValue,
622        M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
623    {
624        let name: Cow<'static, str> = meta.as_ref().to_string().into();
625        self.meta_methods.insert(
626            name.into(),
627            Func {
628                params: A::get_types_as_params(),
629                returns: R::get_types_as_returns(),
630                doc: self.queued_doc.take().map(|v| v.into()),
631            },
632        );
633    }
634
635    fn add_meta_method_with<A, R, M, G>(&mut self, meta: MetaMethod, _method: M, generator: G)
636        where
637            A: FromLuaMulti<'lua> + TypedMultiValue,
638            R: IntoLuaMulti<'lua> + TypedMultiValue,
639            M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> mlua::Result<R>,
640            G: Fn(&mut FunctionBuilder<A, R>) {
641        
642        let mut builder = FunctionBuilder::<A, R>::default();
643        generator(&mut builder);
644
645        let name: Cow<'static, str> = meta.as_ref().to_string().into();
646        self.meta_methods.insert(
647            name.into(),
648            Func {
649                params: builder.params,
650                returns: builder.returns,
651                doc: self.queued_doc.take().map(|v| v.into()),
652            },
653        );
654    }
655
656    #[cfg(feature = "async")]
657    fn add_async_method<'s, S: ?Sized + AsRef<str>, A, R, M, MR>(&mut self, name: &S, _: M)
658    where
659        'lua: 's,
660        T: 'static,
661        M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
662        A: FromLuaMulti<'lua> + TypedMultiValue,
663        MR: std::future::Future<Output = mlua::Result<R>> + 's,
664        R: IntoLuaMulti<'lua> + TypedMultiValue,
665    {
666        let name: Cow<'static, str> = name.as_ref().to_string().into();
667        self.methods.insert(
668            name.into(),
669            Func {
670                params: A::get_types_as_params(),
671                returns: R::get_types_as_returns(),
672                doc: self.queued_doc.take().map(|v| v.into()),
673            },
674        );
675    }
676
677    #[cfg(feature = "async")]
678    fn add_async_method_with<'s, S: ?Sized + AsRef<str>, A, R, M, MR, G>(&mut self, name: &S, _method: M, generator: G)
679        where
680            'lua: 's,
681            T: 'static,
682            M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
683            A: FromLuaMulti<'lua> + TypedMultiValue,
684            MR: std::future::Future<Output = mlua::Result<R>> + 's,
685            R: IntoLuaMulti<'lua> + TypedMultiValue,
686            G: Fn(&mut FunctionBuilder<A, R>) {
687        
688        let mut builder = FunctionBuilder::<A, R>::default();
689        generator(&mut builder);
690
691        let name: Cow<'static, str> = name.as_ref().to_string().into();
692        self.methods.insert(
693            name.into(),
694            Func {
695                params: builder.params,
696                returns: builder.returns,
697                doc: self.queued_doc.take().map(|v| v.into()),
698            },
699        );
700    }
701
702    #[cfg(feature = "async")]
703    fn add_async_method_mut<'s, S: ?Sized + AsRef<str>, A, R, M, MR>(&mut self, name: &S, method: M)
704        where
705            'lua: 's,
706            T: 'static,
707            M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
708            A: FromLuaMulti<'lua> + TypedMultiValue,
709            MR: std::future::Future<Output = mlua::Result<R>> + 's,
710            R: IntoLuaMulti<'lua> + TypedMultiValue {
711        
712        let name: Cow<'static, str> = name.as_ref().to_string().into();
713        self.methods.insert(
714            name.into(),
715            Func {
716                params: A::get_types_as_params(),
717                returns: R::get_types_as_returns(),
718                doc: self.queued_doc.take().map(|v| v.into()),
719            },
720        );
721    }
722
723    #[cfg(feature = "async")]
724    fn add_async_method_mut_with<'s, S: ?Sized + AsRef<str>, A, R, M, MR, G>(&mut self, name: &S, _method: M, generator: G)
725        where
726            'lua: 's,
727            T: 'static,
728            M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
729            A: FromLuaMulti<'lua> + TypedMultiValue,
730            MR: std::future::Future<Output = mlua::Result<R>> + 's,
731            R: IntoLuaMulti<'lua> + TypedMultiValue,
732            G: Fn(&mut FunctionBuilder<A, R>) {
733        
734        let mut builder = FunctionBuilder::<A, R>::default();
735        generator(&mut builder);
736
737        let name: Cow<'static, str> = name.as_ref().to_string().into();
738        self.methods.insert(
739            name.into(),
740            Func {
741                params: builder.params,
742                returns: builder.returns,
743                doc: self.queued_doc.take().map(|v| v.into()),
744            },
745        );
746    }
747
748    fn add_function_mut<S, A, R, F>(&mut self, name: &S, _: F)
749    where
750        S: ?Sized + AsRef<str>,
751        A: FromLuaMulti<'lua> + TypedMultiValue,
752        R: IntoLuaMulti<'lua> + TypedMultiValue,
753        F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
754    {
755        let name: Cow<'static, str> = name.as_ref().to_string().into();
756        self.functions.insert(
757            name.into(),
758            Func {
759                params: A::get_types_as_params(),
760                returns: R::get_types_as_returns(),
761                doc: self.queued_doc.take().map(|v| v.into()),
762            },
763        );
764    }
765
766    fn add_function_mut_with<S, A, R, F, G>(&mut self, name: &S, _function: F, generator: G)
767        where
768            S: ?Sized + AsRef<str>,
769            A: FromLuaMulti<'lua> + TypedMultiValue,
770            R: IntoLuaMulti<'lua> + TypedMultiValue,
771            F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
772            G: Fn(&mut FunctionBuilder<A, R>) {
773        
774        let mut builder = FunctionBuilder::<A, R>::default();
775        generator(&mut builder);
776
777        let name: Cow<'static, str> = name.as_ref().to_string().into();
778        self.functions.insert(
779            name.into(),
780            Func {
781                params: builder.params,
782                returns: builder.returns,
783                doc: self.queued_doc.take().map(|v| v.into()),
784            },
785        );
786    }
787
788    fn add_meta_function<A, R, F>(&mut self, meta: MetaMethod, _: F)
789    where
790        A: FromLuaMulti<'lua> + TypedMultiValue,
791        R: IntoLuaMulti<'lua> + TypedMultiValue,
792        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
793    {
794        let name: Cow<'static, str> = meta.as_ref().to_string().into();
795        self.meta_functions.insert(
796            name.into(),
797            Func {
798                params: A::get_types_as_params(),
799                returns: R::get_types_as_returns(),
800                doc: self.queued_doc.take().map(|v| v.into()),
801            },
802        );
803    }
804
805    fn add_meta_function_with<A, R, F, G>(&mut self, meta: MetaMethod, _function: F, generator: G)
806        where
807            A: FromLuaMulti<'lua> + TypedMultiValue,
808            R: IntoLuaMulti<'lua> + TypedMultiValue,
809            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> mlua::Result<R>,
810            G: Fn(&mut FunctionBuilder<A, R>) {
811        
812        let mut builder = FunctionBuilder::<A, R>::default();
813        generator(&mut builder);
814
815        let name: Cow<'static, str> = meta.as_ref().to_string().into();
816        self.functions.insert(
817            name.into(),
818            Func {
819                params: builder.params,
820                returns: builder.returns,
821                doc: self.queued_doc.take().map(|v| v.into()),
822            },
823        );
824    }
825
826    #[cfg(feature = "async")]
827    fn add_async_function<S: ?Sized, A, R, F, FR>(&mut self, name: &S, _: F)
828    where
829        S: AsRef<str>,
830        A: FromLuaMulti<'lua> + TypedMultiValue,
831        R: IntoLuaMulti<'lua> + TypedMultiValue,
832        F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
833        FR: 'lua + std::future::Future<Output = mlua::Result<R>>,
834    {
835        let name: Cow<'static, str> = name.as_ref().to_string().into();
836        self.functions.insert(
837            name.into(),
838            Func {
839                params: A::get_types_as_params(),
840                returns: R::get_types_as_returns(),
841                doc: self.queued_doc.take().map(|v| v.into()),
842            },
843        );
844    }
845
846    #[cfg(feature = "async")]
847    fn add_async_function_with<S: ?Sized, A, R, F, FR, G>(&mut self, name: &S, _function: F, generator: G)
848        where
849            S: AsRef<str>,
850            A: FromLuaMulti<'lua> + TypedMultiValue,
851            R: IntoLuaMulti<'lua> + TypedMultiValue,
852            F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
853            FR: 'lua + std::future::Future<Output = mlua::Result<R>>,
854            G: Fn(&mut FunctionBuilder<A, R>) {
855        
856        let mut builder = FunctionBuilder::<A, R>::default();
857        generator(&mut builder);
858
859        let name: Cow<'static, str> = name.as_ref().to_string().into();
860        self.functions.insert(
861            name.into(),
862            Func {
863                params: builder.params,
864                returns: builder.returns,
865                doc: self.queued_doc.take().map(|v| v.into()),
866            },
867        );
868    }
869
870    fn add_meta_method_mut<A, R, M>(&mut self, meta: MetaMethod, _: M)
871    where
872        A: FromLuaMulti<'lua> + TypedMultiValue,
873        R: IntoLuaMulti<'lua> + TypedMultiValue,
874        M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
875    {
876        let name: Cow<'static, str> = meta.as_ref().to_string().into();
877        self.meta_methods.insert(
878            name.into(),
879            Func {
880                params: A::get_types_as_params(),
881                returns: R::get_types_as_returns(),
882                doc: self.queued_doc.take().map(|v| v.into()),
883            },
884        );
885    }
886    
887    fn add_meta_method_mut_with<A, R, M, G>(&mut self, meta: MetaMethod, _method: M, generator: G)
888        where
889            A: FromLuaMulti<'lua> + TypedMultiValue,
890            R: IntoLuaMulti<'lua> + TypedMultiValue,
891            M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> mlua::Result<R>,
892            G: Fn(&mut FunctionBuilder<A, R>) {
893        
894        let mut builder = FunctionBuilder::<A, R>::default();
895        generator(&mut builder);
896
897        let name: Cow<'static, str> = meta.as_ref().to_string().into();
898        self.meta_methods.insert(
899            name.into(),
900            Func {
901                params: builder.params,
902                returns: builder.returns,
903                doc: self.queued_doc.take().map(|v| v.into()),
904            },
905        );
906    }
907
908    fn add_meta_function_mut<A, R, F>(&mut self, meta: MetaMethod, _: F)
909    where
910        A: FromLuaMulti<'lua> + TypedMultiValue,
911        R: IntoLuaMulti<'lua> + TypedMultiValue,
912        F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
913    {
914        let name: Cow<'static, str> = meta.as_ref().to_string().into();
915        self.meta_functions.insert(
916            name.into(),
917            Func {
918                params: A::get_types_as_params(),
919                returns: R::get_types().into_iter().map(|ty| Return { doc: None, ty }).collect(),
920                doc: self.queued_doc.take().map(|v| v.into()),
921            },
922        );
923    }
924
925    fn add_meta_function_mut_with<A, R, F, G>(&mut self, meta: MetaMethod, _function: F, generator: G)
926        where
927            A: FromLuaMulti<'lua> + TypedMultiValue,
928            R: IntoLuaMulti<'lua> + TypedMultiValue,
929            F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> mlua::Result<R>,
930            G: Fn(&mut FunctionBuilder<A, R>) {
931        
932        let mut builder = FunctionBuilder::<A, R>::default();
933        generator(&mut builder);
934
935        let name: Cow<'static, str> = meta.as_ref().to_string().into();
936        self.meta_functions.insert(
937            name.into(),
938            Func {
939                params: builder.params,
940                returns: builder.returns,
941                doc: self.queued_doc.take().map(|v| v.into()),
942            },
943        );
944    }
945}