1use std::{any::{type_name, Any}, borrow::Cow, collections::BTreeMap};
2
3use super::{generator::FunctionBuilder, Field, Func, Index, IntoDocComment, Type, Typed, TypedMultiValue};
4use crate::{
5 extras::{Module, ModuleFields, ModuleMethods},
6 MaybeSend,
7};
8use mlua::{FromLuaMulti, IntoLua, IntoLuaMulti};
9
10#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct TypedModuleBuilder {
13 pub doc: Option<Cow<'static, str>>,
14
15 pub nested_modules: BTreeMap<Index, TypedModuleBuilder>,
16
17 pub fields: BTreeMap<Index, Field>,
18 pub meta_fields: BTreeMap<Index, Field>,
19
20 pub functions: BTreeMap<Index, Func>,
21 pub methods: BTreeMap<Index, Func>,
22 pub meta_functions: BTreeMap<Index, Func>,
23 pub meta_methods: BTreeMap<Index, Func>,
24
25 queued_doc: Option<String>,
26 parents: Vec<&'static str>,
27}
28
29impl From<TypedModuleBuilder> for Type {
30 fn from(value: TypedModuleBuilder) -> Self {
31 Type::Module(Box::new(value))
32 }
33}
34
35impl TypedModuleBuilder {
36 pub fn new<M: TypedModule>() -> mlua::Result<Self> {
37 let mut builder = TypedModuleBuilder::default();
38
39 if let Some(doc) = M::documentation() {
40 builder.doc = Some(doc.into());
41 }
42
43 M::add_fields(&mut builder)?;
44 M::add_methods(&mut builder)?;
45
46 Ok(builder)
47 }
48
49 #[inline]
50 pub fn is_empty(&self) -> bool {
51 self.fields.is_empty()
52 && self.nested_modules.is_empty()
53 && self.functions.is_empty()
54 && self.methods.is_empty()
55 && self.is_meta_empty()
56 }
57
58 #[inline]
59 pub fn is_meta_empty(&self) -> bool {
60 self.meta_fields.is_empty()
61 && self.meta_functions.is_empty()
62 && self.meta_methods.is_empty()
63 }
64
65 pub fn field<S: AsRef<str>>(mut self, name: impl AsRef<str>, ty: Type, doc: impl IntoDocComment) -> Self {
80 self.fields.insert(name.as_ref().to_string().into(), Field::new(ty, doc));
81 self
82 }
83
84 pub fn function<Params, Returns>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment) -> Self
97 where
98 Params: TypedMultiValue,
99 Returns: TypedMultiValue,
100 {
101 self.functions.insert(name.as_ref().to_string().into(), Func::new::<Params, Returns>(doc));
102 self
103 }
104
105 pub fn function_with<Params, Returns, F, R>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment, generator: F) -> Self
124 where
125 Params: TypedMultiValue,
126 Returns: TypedMultiValue,
127 F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
128 R: Any,
129 {
130 let mut builder = FunctionBuilder::default();
131 generator(&mut builder);
132
133 self.functions.insert(name.as_ref().to_string().into(), Func {
134 params: builder.params,
135 returns: builder.returns,
136 doc: doc.into_doc_comment()
137 });
138 self
139 }
140
141 pub fn method<Params, Returns>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment) -> Self
157 where
158 Params: TypedMultiValue,
159 Returns: TypedMultiValue,
160 {
161 self.methods.insert(name.as_ref().to_string().into(), Func::new::<Params, Returns>(doc));
162 self
163 }
164
165 pub fn method_with<Params, Returns, F, R>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment, generator: F) -> Self
184 where
185 Params: TypedMultiValue,
186 Returns: TypedMultiValue,
187 F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
188 R: Any,
189 {
190 let mut builder = FunctionBuilder::default();
191 generator(&mut builder);
192
193 self.methods.insert(name.as_ref().to_string().into(), Func {
194 params: builder.params,
195 returns: builder.returns,
196 doc: doc.into_doc_comment()
197 });
198 self
199 }
200
201 pub fn meta_field<S: AsRef<str>>(mut self, name: impl AsRef<str>, ty: Type, doc: impl IntoDocComment) -> Self {
216 self.meta_fields.insert(name.as_ref().to_string().into(), Field::new(ty, doc));
217 self
218 }
219
220 pub fn meta_function<Params, Returns>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment) -> Self
233 where
234 Params: TypedMultiValue,
235 Returns: TypedMultiValue,
236 {
237 self.meta_functions.insert(name.as_ref().to_string().into(), Func::new::<Params, Returns>(doc));
238 self
239 }
240
241 pub fn meta_function_with<Params, Returns, F, R>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment, generator: F) -> Self
260 where
261 F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
262 R: Any,
263 Params: TypedMultiValue,
264 Returns: TypedMultiValue,
265 {
266 let mut builder = FunctionBuilder::default();
267 generator(&mut builder);
268
269 self.meta_functions.insert(name.as_ref().to_string().into(), Func {
270 params: builder.params,
271 returns: builder.returns,
272 doc: doc.into_doc_comment()
273 });
274 self
275 }
276
277 pub fn meta_method<Params, Returns>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment) -> Self
295 where
296 Params: TypedMultiValue,
297 Returns: TypedMultiValue,
298 {
299 self.meta_methods.insert(name.as_ref().to_string().into(), Func::new::<Params, Returns>(doc));
300 self
301 }
302
303 pub fn meta_method_with<Params, Returns, F, R>(mut self, name: impl AsRef<str>, doc: impl IntoDocComment, generator: F) -> Self
322 where
323 F: Fn(&mut FunctionBuilder<Params, Returns>) -> R,
324 R: Any,
325 Params: TypedMultiValue,
326 Returns: TypedMultiValue,
327 {
328 let mut builder = FunctionBuilder::default();
329 generator(&mut builder);
330
331 self.meta_methods.insert(name.as_ref().to_string().into(), Func {
332 params: builder.params,
333 returns: builder.returns,
334 doc: doc.into_doc_comment()
335 });
336 self
337 }
338}
339
340pub trait TypedModuleFields<'lua> {
342 fn document<V: AsRef<str>>(&mut self, doc: V) -> &mut Self;
344
345 fn add_field<K, V>(&mut self, name: K, value: V) -> mlua::Result<()>
347 where
348 K: Into<Index>,
349 V: IntoLua<'lua> + Typed;
350
351 fn add_meta_field<K, V>(&mut self, name: K, value: V) -> mlua::Result<()>
353 where
354 K: Into<Index>,
355 V: IntoLua<'lua> + Typed;
356
357 fn add_module<V>(&mut self, name: impl Into<Index>) -> mlua::Result<()>
359 where
360 V: TypedModule;
361}
362
363pub trait TypedModuleMethods<'lua> {
365 fn document<V: AsRef<str>>(&mut self, doc: V) -> &mut Self;
367
368 fn add_function<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
370 where
371 K: Into<Index>,
372 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
373 A: FromLuaMulti<'lua> + TypedMultiValue,
374 R: IntoLuaMulti<'lua> + TypedMultiValue;
375
376 fn add_function_with<K, F, A, R, G>(
381 &mut self,
382 name: K,
383 function: F,
384 generator: G,
385 ) -> mlua::Result<()>
386 where
387 K: Into<Index>,
388 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
389 A: FromLuaMulti<'lua> + TypedMultiValue,
390 R: IntoLuaMulti<'lua> + TypedMultiValue,
391 G: Fn(&mut FunctionBuilder<A, R>);
392
393 fn add_meta_function<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
395 where
396 K: Into<Index>,
397 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
398 A: FromLuaMulti<'lua> + TypedMultiValue,
399 R: IntoLuaMulti<'lua> + TypedMultiValue;
400
401 fn add_meta_function_with<K, F, A, R, G>(
406 &mut self,
407 name: K,
408 function: F,
409 generator: G,
410 ) -> mlua::Result<()>
411 where
412 K: Into<Index>,
413 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
414 A: FromLuaMulti<'lua> + TypedMultiValue,
415 R: IntoLuaMulti<'lua> + TypedMultiValue,
416 G: Fn(&mut FunctionBuilder<A, R>);
417
418 fn add_method<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
420 where
421 K: Into<Index>,
422 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
423 A: FromLuaMulti<'lua> + TypedMultiValue,
424 R: IntoLuaMulti<'lua> + TypedMultiValue;
425
426 fn add_method_with<K, F, A, R, G>(
431 &mut self,
432 name: K,
433 function: F,
434 generator: G,
435 ) -> mlua::Result<()>
436 where
437 K: Into<Index>,
438 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
439 A: FromLuaMulti<'lua> + TypedMultiValue,
440 R: IntoLuaMulti<'lua> + TypedMultiValue,
441 G: Fn(&mut FunctionBuilder<A, R>);
442
443 fn add_meta_method<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
445 where
446 K: Into<Index>,
447 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
448 A: FromLuaMulti<'lua> + TypedMultiValue,
449 R: IntoLuaMulti<'lua> + TypedMultiValue;
450
451 fn add_meta_method_with<K, F, A, R, G>(
456 &mut self,
457 name: K,
458 function: F,
459 generator: G,
460 ) -> mlua::Result<()>
461 where
462 K: Into<Index>,
463 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
464 A: FromLuaMulti<'lua> + TypedMultiValue,
465 R: IntoLuaMulti<'lua> + TypedMultiValue,
466 G: Fn(&mut FunctionBuilder<A, R>);
467}
468
469pub struct WrappedModule<'module, M>(pub &'module mut M);
470impl<'module, 'lua, M: ModuleFields<'lua>> TypedModuleFields<'lua> for WrappedModule<'module, M> {
471 fn document<V: AsRef<str>>(&mut self, _doc: V) -> &mut Self {
472 self
473 }
474
475 fn add_field<K, V>(&mut self, name: K, value: V) -> mlua::Result<()>
476 where
477 K: Into<Index>,
478 V: IntoLua<'lua> + Typed,
479 {
480 self.0.add_field(name.into(), value)
481 }
482
483 fn add_meta_field<K, V>(&mut self, name: K, value: V) -> mlua::Result<()>
484 where
485 K: Into<Index>,
486 V: IntoLua<'lua> + Typed,
487 {
488 self.0.add_meta_field(name.into(), value)
489 }
490
491 fn add_module<V>(&mut self, name: impl Into<Index>) -> mlua::Result<()>
492 where
493 V: TypedModule,
494 {
495 self.0.add_module::<Index, V>(name.into())
496 }
497}
498
499impl<'module, 'lua, M: ModuleMethods<'lua>> TypedModuleMethods<'lua> for WrappedModule<'module, M> {
500 fn document<V: AsRef<str>>(&mut self, _doc: V) -> &mut Self {
501 self
502 }
503
504 fn add_function<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
505 where
506 K: Into<Index>,
507 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
508 A: FromLuaMulti<'lua> + TypedMultiValue,
509 R: IntoLuaMulti<'lua> + TypedMultiValue,
510 {
511 self.0
512 .add_function::<Index, F, A, R>(name.into(), function)
513 }
514
515 fn add_function_with<K, F, A, R, G>(
516 &mut self,
517 name: K,
518 function: F,
519 _generator: G,
520 ) -> mlua::Result<()>
521 where
522 K: Into<Index>,
523 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
524 A: FromLuaMulti<'lua> + TypedMultiValue,
525 R: IntoLuaMulti<'lua> + TypedMultiValue,
526 G: Fn(&mut FunctionBuilder<A, R>),
527 {
528 self.0
529 .add_function::<Index, F, A, R>(name.into(), function)
530 }
531
532 fn add_meta_function<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
533 where
534 K: Into<Index>,
535 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
536 A: FromLuaMulti<'lua> + TypedMultiValue,
537 R: IntoLuaMulti<'lua> + TypedMultiValue,
538 {
539 self.0.add_meta_function::<Index, F, A, R>(name.into(), function)
540 }
541
542 fn add_meta_function_with<K, F, A, R, G>(
543 &mut self,
544 name: K,
545 function: F,
546 _generator: G,
547 ) -> mlua::Result<()>
548 where
549 K: Into<Index>,
550 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
551 A: FromLuaMulti<'lua> + TypedMultiValue,
552 R: IntoLuaMulti<'lua> + TypedMultiValue,
553 G: Fn(&mut FunctionBuilder<A, R>),
554 {
555 self.0.add_meta_function::<Index, F, A, R>(name.into(), function)
556 }
557
558 fn add_method<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
559 where
560 K: Into<Index>,
561 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
562 A: FromLuaMulti<'lua> + TypedMultiValue,
563 R: IntoLuaMulti<'lua> + TypedMultiValue,
564 {
565 self.0
566 .add_method::<Index, F, A, R>(name.into(), function)
567 }
568
569 fn add_method_with<K, F, A, R, G>(
570 &mut self,
571 name: K,
572 function: F,
573 _generator: G,
574 ) -> mlua::Result<()>
575 where
576 K: Into<Index>,
577 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
578 A: FromLuaMulti<'lua> + TypedMultiValue,
579 R: IntoLuaMulti<'lua> + TypedMultiValue,
580 G: Fn(&mut FunctionBuilder<A, R>),
581 {
582 self.0
583 .add_method::<Index, F, A, R>(name.into(), function)
584 }
585
586 fn add_meta_method<K, F, A, R>(&mut self, name: K, function: F) -> mlua::Result<()>
587 where
588 K: Into<Index>,
589 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
590 A: FromLuaMulti<'lua> + TypedMultiValue,
591 R: IntoLuaMulti<'lua> + TypedMultiValue,
592 {
593 self.0.add_meta_method::<Index, F, A, R>(name.into(), function)
594 }
595
596 fn add_meta_method_with<K, F, A, R, G>(
597 &mut self,
598 name: K,
599 function: F,
600 _generator: G,
601 ) -> mlua::Result<()>
602 where
603 K: Into<Index>,
604 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
605 A: FromLuaMulti<'lua> + TypedMultiValue,
606 R: IntoLuaMulti<'lua> + TypedMultiValue,
607 R: IntoLuaMulti<'lua> + TypedMultiValue,
608 {
609 self.0
610 .add_meta_method::<Index, F, A, R>(name.into(), function)
611 }
612}
613
614impl<'lua> TypedModuleFields<'lua> for TypedModuleBuilder {
615 fn document<V: AsRef<str>>(&mut self, doc: V) -> &mut Self {
616 self.queued_doc = Some(doc.as_ref().into());
617 self
618 }
619
620 fn add_module<V>(&mut self, name: impl Into<Index>) -> mlua::Result<()>
621 where
622 V: TypedModule,
623 {
624 if self.parents.contains(&type_name::<V>()) {
625 return Err(mlua::Error::runtime(format!(
626 "infinite nested modules using: '{}'",
627 type_name::<V>()
628 )));
629 }
630
631 let mut nested = TypedModuleBuilder {
632 parents: self
633 .parents
634 .iter()
635 .map(|v| *v)
636 .chain([type_name::<V>()])
637 .collect(),
638 ..Default::default()
639 };
640
641 if let Some(doc) = V::documentation() {
642 nested.doc = Some(doc.into());
643 }
644
645 V::add_fields(&mut nested)?;
646 V::add_methods(&mut nested)?;
647
648 self.nested_modules.insert(name.into(), nested);
649 Ok(())
650 }
651
652 fn add_field<K, V>(&mut self, name: K, _value: V) -> mlua::Result<()>
653 where
654 K: Into<Index>,
655 V: IntoLua<'lua> + Typed,
656 {
657 self.fields.insert(
658 name.into(),
659 Field {
660 ty: V::ty(),
661 doc: self.queued_doc.take().map(|v| v.into()),
662 },
663 );
664 Ok(())
665 }
666
667 fn add_meta_field<K, V>(&mut self, name: K, _value: V) -> mlua::Result<()>
668 where
669 K: Into<Index>,
670 V: IntoLua<'lua> + Typed,
671 {
672 self.meta_fields.insert(
673 name.into(),
674 Field {
675 ty: V::ty(),
676 doc: self.queued_doc.take().map(|v| v.into()),
677 },
678 );
679 Ok(())
680 }
681}
682
683impl<'lua> TypedModuleMethods<'lua> for TypedModuleBuilder {
684 fn document<V: AsRef<str>>(&mut self, doc: V) -> &mut Self {
685 self.queued_doc = Some(doc.as_ref().into());
686 self
687 }
688
689 fn add_function<K, F, A, R>(&mut self, name: K, _function: F) -> mlua::Result<()>
690 where
691 K: Into<Index>,
692 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
693 A: FromLuaMulti<'lua> + TypedMultiValue,
694 R: IntoLuaMulti<'lua> + TypedMultiValue,
695 {
696 self.functions.insert(
697 name.into(),
698 Func {
699 params: A::get_types_as_params(),
700 returns: R::get_types_as_returns(),
701 doc: self.queued_doc.take().map(|v| v.into()),
702 },
703 );
704 Ok(())
705 }
706
707 fn add_function_with<K, F, A, R, G>(
708 &mut self,
709 name: K,
710 _function: F,
711 generator: G,
712 ) -> mlua::Result<()>
713 where
714 K: Into<Index>,
715 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
716 A: FromLuaMulti<'lua> + TypedMultiValue,
717 R: IntoLuaMulti<'lua> + TypedMultiValue,
718 G: Fn(&mut FunctionBuilder<A, R>),
719 {
720 let mut builder = FunctionBuilder::<A, R>::default();
721 generator(&mut builder);
722
723 self.functions.insert(
724 name.into(),
725 Func {
726 params: builder.params,
727 returns: builder.returns,
728 doc: self.queued_doc.take().map(|v| v.into()),
729 },
730 );
731 Ok(())
732 }
733
734 fn add_meta_function<K, F, A, R>(&mut self, name: K, _function: F) -> mlua::Result<()>
735 where
736 K: Into<Index>,
737 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
738 A: FromLuaMulti<'lua> + TypedMultiValue,
739 R: IntoLuaMulti<'lua> + TypedMultiValue,
740 {
741 self.meta_functions.insert(
742 name.into(),
743 Func {
744 params: A::get_types_as_params(),
745 returns: R::get_types_as_returns(),
746 doc: self.queued_doc.take().map(|v| v.into()),
747 },
748 );
749 Ok(())
750 }
751
752 fn add_meta_function_with<K, F, A, R, G>(
753 &mut self,
754 name: K,
755 _function: F,
756 generator: G,
757 ) -> mlua::Result<()>
758 where
759 K: Into<Index>,
760 F: Fn(&'lua mlua::Lua, A) -> mlua::Result<R> + MaybeSend + 'static,
761 A: FromLuaMulti<'lua> + TypedMultiValue,
762 R: IntoLuaMulti<'lua> + TypedMultiValue,
763 G: Fn(&mut FunctionBuilder<A, R>),
764 {
765 let mut builder = FunctionBuilder::<A, R>::default();
766 generator(&mut builder);
767
768 self.meta_functions.insert(
769 name.into(),
770 Func {
771 params: builder.params,
772 returns: builder.returns,
773 doc: self.queued_doc.take().map(|v| v.into()),
774 },
775 );
776 Ok(())
777 }
778
779 fn add_method<K, F, A, R>(&mut self, name: K, _function: F) -> mlua::Result<()>
780 where
781 K: Into<Index>,
782 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
783 A: FromLuaMulti<'lua> + TypedMultiValue,
784 R: IntoLuaMulti<'lua> + TypedMultiValue,
785 {
786 self.methods.insert(
787 name.into(),
788 Func {
789 params: A::get_types_as_params(),
790 returns: R::get_types_as_returns(),
791 doc: self.queued_doc.take().map(|v| v.into()),
792 },
793 );
794 Ok(())
795 }
796
797 fn add_method_with<K, F, A, R, G>(
798 &mut self,
799 name: K,
800 _function: F,
801 generator: G,
802 ) -> mlua::Result<()>
803 where
804 K: Into<Index>,
805 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
806 A: FromLuaMulti<'lua> + TypedMultiValue,
807 R: IntoLuaMulti<'lua> + TypedMultiValue,
808 G: Fn(&mut FunctionBuilder<A, R>),
809 {
810 let mut builder = FunctionBuilder::<A, R>::default();
811 generator(&mut builder);
812
813 self.methods.insert(
814 name.into(),
815 Func {
816 params: builder.params,
817 returns: builder.returns,
818 doc: self.queued_doc.take().map(|v| v.into()),
819 },
820 );
821 Ok(())
822 }
823
824 fn add_meta_method<K, F, A, R>(&mut self, name: K, _function: F) -> mlua::Result<()>
825 where
826 K: Into<Index>,
827 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
828 A: FromLuaMulti<'lua> + TypedMultiValue,
829 R: IntoLuaMulti<'lua> + TypedMultiValue,
830 {
831 self.meta_methods.insert(
832 name.into(),
833 Func {
834 params: A::get_types_as_params(),
835 returns: R::get_types_as_returns(),
836 doc: self.queued_doc.take().map(|v| v.into()),
837 },
838 );
839 Ok(())
840 }
841
842 fn add_meta_method_with<K, F, A, R, G>(
843 &mut self,
844 name: K,
845 _function: F,
846 generator: G,
847 ) -> mlua::Result<()>
848 where
849 K: Into<Index>,
850 F: Fn(&'lua mlua::Lua, mlua::Table<'_>, A) -> mlua::Result<R> + MaybeSend + 'static,
851 A: FromLuaMulti<'lua> + TypedMultiValue,
852 R: IntoLuaMulti<'lua> + TypedMultiValue,
853 G: Fn(&mut FunctionBuilder<A, R>),
854 {
855 let mut builder = FunctionBuilder::<A, R>::default();
856 generator(&mut builder);
857
858 self.meta_methods.insert(
859 name.into(),
860 Func {
861 params: builder.params,
862 returns: builder.returns,
863 doc: self.queued_doc.take().map(|v| v.into()),
864 },
865 );
866 Ok(())
867 }
868}
869
870pub trait TypedModule: Sized {
874 #[inline]
876 fn documentation() -> Option<String> { None }
877
878 #[allow(unused_variables)]
880 fn add_fields<'lua, F: TypedModuleFields<'lua>>(fields: &mut F) -> mlua::Result<()> {
881 Ok(())
882 }
883
884 #[allow(unused_variables)]
886 fn add_methods<'lua, M: TypedModuleMethods<'lua>>(methods: &mut M) -> mlua::Result<()> {
887 Ok(())
888 }
889}
890
891impl<T: TypedModule> Module for T {
892 fn add_fields<'lua, F: ModuleFields<'lua>>(fields: &mut F) -> mlua::Result<()> {
893 let mut wrapped = WrappedModule(fields);
894 T::add_fields(&mut wrapped)
895 }
896
897 fn add_methods<'lua, M: ModuleMethods<'lua>>(methods: &mut M) -> mlua::Result<()> {
898 let mut wrapped = WrappedModule(methods);
899 T::add_methods(&mut wrapped)
900 }
901}