1use std::{borrow::Cow, collections::BTreeMap};
2
3use mlua::{AnyUserData, FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Lua};
4
5use crate::{
6 MaybeSend, ser::to_lua_repr, typed::{Field, Func, Index, IntoDocComment, StaticField, Type}
7};
8
9use super::{
10 Typed, TypedDataDocumentation, TypedDataFields, TypedDataMethods, TypedMultiValue,
11 TypedUserData,
12};
13
14#[derive(Default, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
15pub struct TypedClass {
16 pub type_doc: Option<Cow<'static, str>>,
17
18 pub derives: Vec<String>,
19
20 pub fields: BTreeMap<Index, Field>,
21 pub static_fields: BTreeMap<Index, StaticField>,
22 pub meta_fields: BTreeMap<Index, Field>,
23 pub static_meta_fields: BTreeMap<Index, StaticField>,
24
25 pub methods: BTreeMap<Index, Func>,
26 pub meta_methods: BTreeMap<Index, Func>,
27
28 pub functions: BTreeMap<Index, Func>,
29 pub meta_functions: BTreeMap<Index, Func>,
30}
31impl TypedClass {
32 pub fn is_meta_empty(&self) -> bool {
34 self.meta_fields.is_empty()
35 && self.static_meta_fields.is_empty()
36 && self.meta_functions.is_empty()
37 && self.meta_methods.is_empty()
38 }
39}
40
41#[derive(Default, Debug, Clone)]
43pub struct TypedClassBuilder {
44 lua: Lua,
45
46 queued_doc: Option<Cow<'static, str>>,
47 queued_ty: Option<Type>,
48 queued_params: Vec<(Option<Type>, String, Option<Cow<'static, str>>)>,
49 queued_returns: Vec<(Option<Type>, Option<Cow<'static, str>>)>,
50
51 pub typed_class: TypedClass,
52}
53
54impl From<TypedClassBuilder> for Type {
55 fn from(value: TypedClassBuilder) -> Self {
56 Type::Class(Box::new(value.typed_class))
57 }
58}
59
60impl TypedClassBuilder {
61 pub fn new<T: TypedUserData>() -> Self {
62 let mut tcb = Self::default();
63 T::add_documentation(&mut tcb);
64 T::add_fields(&mut tcb);
65 T::add_methods(&mut tcb);
66 tcb
67 }
68
69 pub fn build(self) -> TypedClass {
70 self.typed_class
71 }
72
73 pub fn skip_field(mut self, idx: impl Into<Index>) -> Self {
75 self.typed_class.fields.remove(&idx.into());
76 self
77 }
78
79 pub fn skip_method(mut self, idx: impl Into<Index>) -> Self {
81 self.typed_class.methods.remove(&idx.into());
82 self
83 }
84
85 pub fn skip_meta_method(mut self, idx: impl Into<Index>) -> Self {
87 self.typed_class.meta_methods.remove(&idx.into());
88 self
89 }
90
91 pub fn skip_function(mut self, idx: impl Into<Index>) -> Self {
93 self.typed_class.functions.remove(&idx.into());
94 self
95 }
96
97 pub fn skip_meta_function(mut self, idx: impl Into<Index>) -> Self {
99 self.typed_class.meta_functions.remove(&idx.into());
100 self
101 }
102
103 pub fn field(mut self, key: impl Into<Index>, ty: Type, doc: impl IntoDocComment) -> Self {
118 self.typed_class.fields.insert(key.into(), Field::new(ty, doc));
119 self
120 }
121
122 pub fn static_field<V>(mut self, key: impl Into<Index>, value: V, doc: impl IntoDocComment) -> Self
123 where
124 V: Typed + IntoLua
125 {
126 let value = match value.into_lua(&self.lua) {
127 Ok(value) => to_lua_repr(&value).map_err(mlua::Error::runtime),
128 Err(err) => Err(err)
129 };
130
131 if let Ok(value) = value {
132 self.typed_class.static_fields.insert(key.into(), StaticField::new(V::ty(), doc, value));
133 }
134 self
135 }
136
137 pub fn inherit(mut self, parent: &TypedClass) -> Self {
138 self.typed_class.static_fields.extend(parent.static_fields.clone());
139 self
140 }
141
142 pub fn function<Params, Returns>(
155 mut self,
156 key: impl Into<Index>,
157 doc: impl IntoDocComment,
158 ) -> Self
159 where
160 Params: TypedMultiValue,
161 Returns: TypedMultiValue,
162 {
163 self.typed_class.functions.insert(
164 key.into(),
165 Func::new::<Params, Returns>(
166 doc,
167 self.queued_params.drain(..).collect(),
168 self.queued_returns.drain(..).collect(),
169 ),
170 );
171 self
172 }
173
174 pub fn method<Params, Returns>(
190 mut self,
191 key: impl Into<Index>,
192 doc: impl IntoDocComment,
193 ) -> Self
194 where
195 Params: TypedMultiValue,
196 Returns: TypedMultiValue,
197 {
198 self.typed_class.methods.insert(
199 key.into(),
200 Func::new::<Params, Returns>(
201 doc,
202 self.queued_params.drain(..).collect(),
203 self.queued_returns.drain(..).collect(),
204 ),
205 );
206 self
207 }
208
209 pub fn meta_field(mut self, key: impl Into<Index>, ty: Type, doc: impl IntoDocComment) -> Self {
224 self.typed_class.meta_fields.insert(key.into(), Field::new(ty, doc));
225 self
226 }
227
228 pub fn meta_function<Params, Returns>(
241 mut self,
242 key: impl Into<Index>,
243 doc: impl IntoDocComment,
244 ) -> Self
245 where
246 Params: TypedMultiValue,
247 Returns: TypedMultiValue,
248 {
249 self.typed_class.meta_functions.insert(
250 key.into(),
251 Func::new::<Params, Returns>(
252 doc,
253 self.queued_params.drain(..).collect(),
254 self.queued_returns.drain(..).collect(),
255 ),
256 );
257 self
258 }
259
260 pub fn meta_method<Params, Returns>(
278 mut self,
279 key: impl Into<Index>,
280 doc: impl IntoDocComment,
281 ) -> Self
282 where
283 Params: TypedMultiValue,
284 Returns: TypedMultiValue,
285 {
286 self.typed_class.meta_methods.insert(
287 key.into(),
288 Func::new::<Params, Returns>(
289 doc,
290 self.queued_params.drain(..).collect(),
291 self.queued_returns.drain(..).collect(),
292 ),
293 );
294 self
295 }
296
297 pub fn derive(mut self, parent: impl std::fmt::Display) -> Self {
299 self.typed_class.derives.push(parent.to_string());
300 self
301 }
302}
303
304impl<T: TypedUserData> TypedDataDocumentation<T> for TypedClassBuilder {
305 fn add(&mut self, doc: &str) -> &mut Self {
306 if let Some(type_doc) = self.typed_class.type_doc.as_mut() {
307 *type_doc = format!("{type_doc}\n{doc}").into()
308 } else {
309 self.typed_class.type_doc = Some(doc.to_string().into())
310 }
311 self
312 }
313}
314
315impl<T: TypedUserData> TypedDataFields<T> for TypedClassBuilder {
316 fn document(&mut self, doc: impl IntoDocComment) -> &mut Self {
317 self.queued_doc = doc.into_doc_comment();
318 self
319 }
320
321 fn coerce(&mut self, ty: impl Into<Type>) -> &mut Self {
322 self.queued_ty = Some(ty.into());
323 self
324 }
325
326 fn add_field<V>(&mut self, name: impl Into<String>, value: V)
327 where
328 V: IntoLua + Clone + 'static + Typed,
329 {
330 let value = match value.into_lua(&self.lua) {
331 Ok(value) => to_lua_repr(&value).map_err(mlua::Error::runtime),
332 Err(err) => Err(err)
333 };
334
335 if let Ok(value) = value {
336 let name: Cow<'static, str> = name.into().into();
337 let ty = self.queued_ty.take().unwrap_or(V::as_param());
338 let value: Cow<'static, str> = value.into();
339
340 self.typed_class.static_fields
341 .insert(
342 name.into(),
343 StaticField::new(
344 ty,
345 self.queued_doc.take(),
346 value,
347 )
348 );
349 }
350 }
351
352 fn add_field_function_set<S, A, F>(&mut self, name: S, _: F)
353 where
354 S: Into<String>,
355 A: FromLua + Typed,
356 F: 'static + MaybeSend + FnMut(&Lua, AnyUserData, A) -> mlua::Result<()>,
357 {
358 let name: Cow<'static, str> = name.into().into();
359 let ty = self.queued_ty.take().unwrap_or(A::as_param());
360 self.typed_class.fields
361 .entry(name.into())
362 .and_modify({
363 let ty = ty.clone();
364 |v| {
365 if let Some(doc) = self.queued_doc.take() {
366 v.doc = Some(match v.doc.take() {
367 Some(d) => format!("{d}\n{doc}").into(),
368 None => doc
369 });
370 }
371 v.ty = v.ty.clone() | ty;
372 }
373 })
374 .or_insert(Field {
375 ty,
376 doc: self.queued_doc.take().map(|v| v.into()),
377 });
378 }
379
380 fn add_field_function_get<S, R, F>(&mut self, name: S, _: F)
381 where
382 S: Into<String>,
383 R: IntoLua + Typed,
384 F: 'static + MaybeSend + Fn(&Lua, AnyUserData) -> mlua::Result<R>,
385 {
386 let name: Cow<'static, str> = name.into().into();
387 let ty = self.queued_ty.take().unwrap_or(R::as_return());
388 self.typed_class.fields
389 .entry(name.into())
390 .and_modify({
391 let ty = ty.clone();
392 |v| {
393 if let Some(doc) = self.queued_doc.take() {
394 v.doc = Some(match v.doc.take() {
395 Some(d) => format!("{d}\n{doc}").into(),
396 None => doc
397 });
398 }
399 v.ty = v.ty.clone() | ty;
400 }
401 })
402 .or_insert(Field {
403 ty,
404 doc: self.queued_doc.take().map(|v| v.into()),
405 });
406 }
407
408 fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: S, _: GET, _: SET)
409 where
410 S: Into<String>,
411 R: IntoLua + Typed,
412 A: FromLua + Typed,
413 GET: 'static + MaybeSend + Fn(&Lua, AnyUserData) -> mlua::Result<R>,
414 SET: 'static + MaybeSend + Fn(&Lua, AnyUserData, A) -> mlua::Result<()>,
415 {
416 let name: Cow<'static, str> = name.into().into();
417 let ty = self.queued_ty.take().unwrap_or(A::as_param() | R::as_return());
418 self.typed_class.fields
419 .entry(name.into())
420 .and_modify({
421 let ty = ty.clone();
422 |v| {
423 if let Some(doc) = self.queued_doc.take() {
424 v.doc = Some(match v.doc.take() {
425 Some(d) => format!("{d}\n{doc}").into(),
426 None => doc
427 });
428 }
429 v.ty = v.ty.clone() | ty;
430 }
431 })
432 .or_insert(Field {
433 ty,
434 doc: self.queued_doc.take().map(|v| v.into()),
435 });
436 }
437
438 fn add_field_method_set<S, A, M>(&mut self, name: S, _: M)
439 where
440 S: Into<String>,
441 A: FromLua + Typed,
442 M: 'static + MaybeSend + FnMut(&Lua, &mut T, A) -> mlua::Result<()>,
443 {
444 let name: Cow<'static, str> = name.into().into();
445 let ty = self.queued_ty.take().unwrap_or(A::as_param());
446 self.typed_class.fields
447 .entry(name.into())
448 .and_modify({
449 let ty = ty.clone();
450 |v| {
451 if let Some(doc) = self.queued_doc.take() {
452 v.doc = Some(match v.doc.take() {
453 Some(d) => format!("{d}\n{doc}").into(),
454 None => doc
455 });
456 }
457 v.ty = v.ty.clone() | ty;
458 }
459 })
460 .or_insert(Field {
461 ty,
462 doc: self.queued_doc.take().map(|v| v.into()),
463 });
464 }
465
466 fn add_field_method_get<S, R, M>(&mut self, name: S, _: M)
467 where
468 S: Into<String>,
469 R: IntoLua + Typed,
470 M: 'static + MaybeSend + Fn(&Lua, &T) -> mlua::Result<R>,
471 {
472 let name: Cow<'static, str> = name.into().into();
473 let ty = self.queued_ty.take().unwrap_or(R::as_return());
474 self.typed_class.fields
475 .entry(name.into())
476 .and_modify({
477 let ty = ty.clone();
478 |v| {
479 if let Some(doc) = self.queued_doc.take() {
480 v.doc = Some(match v.doc.take() {
481 Some(d) => format!("{d}\n{doc}").into(),
482 None => doc
483 });
484 }
485 v.ty = v.ty.clone() | ty;
486 }
487 })
488 .or_insert(Field {
489 ty,
490 doc: self.queued_doc.take().map(|v| v.into()),
491 });
492 }
493
494 fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: S, _: GET, _: SET)
495 where
496 S: Into<String>,
497 R: IntoLua + Typed,
498 A: FromLua + Typed,
499 GET: 'static + MaybeSend + Fn(&Lua, &T) -> mlua::Result<R>,
500 SET: 'static + MaybeSend + Fn(&Lua, &mut T, A) -> mlua::Result<()>,
501 {
502 let name: Cow<'static, str> = name.into().into();
503 let ty = self.queued_ty.take().unwrap_or(A::as_param() | R::as_return());
504 self.typed_class.fields
505 .entry(name.into())
506 .and_modify({
507 let ty = ty.clone();
508 |v| {
509 if let Some(doc) = self.queued_doc.take() {
510 v.doc = Some(match v.doc.take() {
511 Some(d) => format!("{d}\n{doc}").into(),
512 None => doc
513 });
514 }
515 v.ty = v.ty.clone() | ty;
516 }
517 })
518 .or_insert(Field {
519 ty,
520 doc: self.queued_doc.take().map(|v| v.into()),
521 });
522 }
523
524 fn add_meta_field<V>(&mut self, meta: impl Into<String>, value: V)
525 where
526 V: IntoLua + Typed + 'static,
527 {
528 let value = match value.into_lua(&self.lua) {
529 Ok(value) => to_lua_repr(&value).map_err(mlua::Error::runtime),
530 Err(err) => Err(err)
531 };
532
533 if let Ok(value) = value {
534 let name: Cow<'static, str> = meta.into().into();
535 let ty = self.queued_ty.take().unwrap_or(V::as_param());
536 let value: Cow<'static, str> = value.into();
537
538 self.typed_class.static_meta_fields
539 .insert(
540 name.into(),
541 StaticField::new(
542 ty,
543 self.queued_doc.take(),
544 value,
545 )
546 );
547 }
548 }
549
550 fn add_meta_field_with<R, F>(&mut self, meta: impl Into<String>, _: F)
551 where
552 F: 'static + MaybeSend + Fn(&Lua) -> mlua::Result<R>,
553 R: IntoLua + Typed {
554
555 let name: Cow<'static, str> = meta.into().into();
556 let ty = self.queued_ty.take().unwrap_or(R::as_return());
557 self.typed_class.meta_fields
558 .entry(name.into())
559 .and_modify({
560 let ty = ty.clone();
561 |v| {
562 if let Some(doc) = self.queued_doc.take() {
563 v.doc = Some(match v.doc.take() {
564 Some(d) => format!("{d}\n{doc}").into(),
565 None => doc
566 });
567 }
568 v.ty = v.ty.clone() | ty;
569 }
570 })
571 .or_insert(Field {
572 ty,
573 doc: self.queued_doc.take().map(|v| v.into()),
574 });
575 }
576}
577
578impl<T: TypedUserData> TypedDataMethods<T> for TypedClassBuilder {
579 fn document(&mut self, doc: impl IntoDocComment) -> &mut Self {
580 self.queued_doc = doc.into_doc_comment();
581 self
582 }
583
584 fn param(&mut self, name: impl std::fmt::Display, doc: impl IntoDocComment) -> &mut Self {
585 self.queued_params.push((None, name.to_string(), doc.into_doc_comment()));
586 self
587 }
588
589 fn param_as(&mut self, ty: impl Into<Type>, name: impl std::fmt::Display, doc: impl IntoDocComment) -> &mut Self {
590 self.queued_params.push((Some(ty.into()), name.to_string(), doc.into_doc_comment()));
591 self
592 }
593
594 fn ret(&mut self, doc: impl IntoDocComment) -> &mut Self {
595 if let Some(doc) = doc.into_doc_comment() {
596 self.queued_returns.push((None, Some(doc)));
597 }
598 self
599 }
600
601
602 fn ret_as(&mut self, ty: impl Into<Type>, doc: impl IntoDocComment) -> &mut Self {
603 self.queued_returns.push((Some(ty.into()), doc.into_doc_comment()));
604 self
605 }
606
607 fn index<I: Typed>(&mut self, idx: isize, doc: impl IntoDocComment) -> &mut Self {
608 self.typed_class.fields.insert(idx.into(), Field { ty: I::as_param(), doc: doc.into_doc_comment() });
609 self
610 }
611
612 fn index_as(&mut self, idx: isize, ty: impl Into<Type>, doc: impl IntoDocComment) -> &mut Self {
613 self.typed_class.fields.insert(idx.into(), Field { ty: ty.into(), doc: doc.into_doc_comment() });
614 self
615 }
616
617 fn add_method<S, A, R, M>(&mut self, name: S, _: M)
618 where
619 S: Into<String>,
620 A: FromLuaMulti + TypedMultiValue,
621 R: IntoLuaMulti + TypedMultiValue,
622 M: 'static + MaybeSend + Fn(&Lua, &T, A) -> mlua::Result<R>,
623 {
624 let name: Cow<'static, str> = name.into().into();
625 self.typed_class.methods.insert(
626 name.into(),
627 Func::new::<A, R>(
628 self.queued_doc.take(),
629 self.queued_params.drain(..).collect(),
630 self.queued_returns.drain(..).collect(),
631 ),
632 );
633 }
634
635 fn add_function<S, A, R, F>(&mut self, name: S, _: F)
636 where
637 S: Into<String>,
638 A: FromLuaMulti + TypedMultiValue,
639 R: IntoLuaMulti + TypedMultiValue,
640 F: 'static + MaybeSend + Fn(&Lua, A) -> mlua::Result<R>,
641 {
642 let name: Cow<'static, str> = name.into().into();
643 self.typed_class.functions.insert(
644 name.into(),
645 Func::new::<A, R>(
646 self.queued_doc.take(),
647 self.queued_params.drain(..).collect(),
648 self.queued_returns.drain(..).collect(),
649 ),
650 );
651 }
652
653 fn add_method_mut<S, A, R, M>(&mut self, name: S, _: M)
654 where
655 S: Into<String>,
656 A: FromLuaMulti + TypedMultiValue,
657 R: IntoLuaMulti + TypedMultiValue,
658 M: 'static + MaybeSend + FnMut(&Lua, &mut T, A) -> mlua::Result<R>,
659 {
660 let name: Cow<'static, str> = name.into().into();
661 self.typed_class.methods.insert(
662 name.into(),
663 Func::new::<A, R>(
664 self.queued_doc.take(),
665 self.queued_params.drain(..).collect(),
666 self.queued_returns.drain(..).collect(),
667 ),
668 );
669 }
670
671 fn add_meta_method<A, R, M>(&mut self, meta: impl Into<String>, _: M)
672 where
673 A: FromLuaMulti + TypedMultiValue,
674 R: IntoLuaMulti + TypedMultiValue,
675 M: 'static + MaybeSend + Fn(&Lua, &T, A) -> mlua::Result<R>,
676 {
677 let name: Cow<'static, str> = meta.into().into();
678 self.typed_class.meta_methods.insert(
679 name.into(),
680 Func::new::<A, R>(
681 self.queued_doc.take(),
682 self.queued_params.drain(..).collect(),
683 self.queued_returns.drain(..).collect(),
684 ),
685 );
686 }
687
688 #[cfg(feature = "async")]
689 fn add_async_method<S: Into<String>, A, R, M, MR>(&mut self, name: S, _: M)
690 where
691 T: 'static,
692 M: Fn(Lua, mlua::UserDataRef<T>, A) -> MR + MaybeSend + 'static,
693 A: FromLuaMulti + TypedMultiValue,
694 MR: std::future::Future<Output = mlua::Result<R>> + MaybeSend + 'static,
695 R: IntoLuaMulti + TypedMultiValue,
696 {
697 let name: Cow<'static, str> = name.into().into();
698 self.typed_class.methods.insert(
699 name.into(),
700 Func::new::<A, R>(
701 self.queued_doc.take(),
702 self.queued_params.drain(..).collect(),
703 self.queued_returns.drain(..).collect(),
704 ),
705 );
706 }
707
708 #[cfg(feature = "async")]
709 fn add_async_method_mut<S: Into<String>, A, R, M, MR>(&mut self, name: S, _method: M)
710 where
711 T: 'static,
712 M: Fn(Lua, mlua::UserDataRefMut<T>, A) -> MR + MaybeSend + 'static,
713 A: FromLuaMulti + TypedMultiValue,
714 MR: std::future::Future<Output = mlua::Result<R>> + MaybeSend + 'static,
715 R: IntoLuaMulti + TypedMultiValue,
716 {
717 let name: Cow<'static, str> = name.into().into();
718 self.typed_class.methods.insert(
719 name.into(),
720 Func::new::<A, R>(
721 self.queued_doc.take(),
722 self.queued_params.drain(..).collect(),
723 self.queued_returns.drain(..).collect(),
724 ),
725 );
726 }
727
728 fn add_function_mut<S, A, R, F>(&mut self, name: S, _: F)
729 where
730 S: Into<String>,
731 A: FromLuaMulti + TypedMultiValue,
732 R: IntoLuaMulti + TypedMultiValue,
733 F: 'static + MaybeSend + FnMut(&Lua, A) -> mlua::Result<R>,
734 {
735 let name: Cow<'static, str> = name.into().into();
736 self.typed_class.functions.insert(
737 name.into(),
738 Func::new::<A, R>(
739 self.queued_doc.take(),
740 self.queued_params.drain(..).collect(),
741 self.queued_returns.drain(..).collect(),
742 ),
743 );
744 }
745
746 fn add_meta_function<A, R, F>(&mut self, meta: impl Into<String>, _: F)
747 where
748 A: FromLuaMulti + TypedMultiValue,
749 R: IntoLuaMulti + TypedMultiValue,
750 F: 'static + MaybeSend + Fn(&Lua, A) -> mlua::Result<R>,
751 {
752 let name: Cow<'static, str> = meta.into().into();
753 self.typed_class.meta_functions.insert(
754 name.into(),
755 Func::new::<A, R>(
756 self.queued_doc.take(),
757 self.queued_params.drain(..).collect(),
758 self.queued_returns.drain(..).collect(),
759 ),
760 );
761 }
762
763 #[cfg(feature = "async")]
764 fn add_async_function<S, A, R, F, FR>(&mut self, name: S, _: F)
765 where
766 S: Into<String>,
767 A: FromLuaMulti + TypedMultiValue,
768 R: IntoLuaMulti + TypedMultiValue,
769 F: 'static + MaybeSend + Fn(Lua, A) -> FR,
770 FR: 'static + MaybeSend + std::future::Future<Output = mlua::Result<R>>,
771 {
772 let name: Cow<'static, str> = name.into().into();
773 self.typed_class.functions.insert(
774 name.into(),
775 Func::new::<A, R>(
776 self.queued_doc.take(),
777 self.queued_params.drain(..).collect(),
778 self.queued_returns.drain(..).collect(),
779 ),
780 );
781 }
782
783 fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<String>, _: M)
784 where
785 A: FromLuaMulti + TypedMultiValue,
786 R: IntoLuaMulti + TypedMultiValue,
787 M: 'static + MaybeSend + FnMut(&Lua, &mut T, A) -> mlua::Result<R>,
788 {
789 let name: Cow<'static, str> = meta.into().into();
790 self.typed_class.meta_methods.insert(
791 name.into(),
792 Func::new::<A, R>(
793 self.queued_doc.take(),
794 self.queued_params.drain(..).collect(),
795 self.queued_returns.drain(..).collect(),
796 ),
797 );
798 }
799
800 fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<String>, _: F)
801 where
802 A: FromLuaMulti + TypedMultiValue,
803 R: IntoLuaMulti + TypedMultiValue,
804 F: 'static + MaybeSend + FnMut(&Lua, A) -> mlua::Result<R>,
805 {
806 let name: Cow<'static, str> = meta.into().into();
807 self.typed_class.meta_functions.insert(
808 name.into(),
809 Func::new::<A, R>(
810 self.queued_doc.take(),
811 self.queued_params.drain(..).collect(),
812 self.queued_returns.drain(..).collect(),
813 ),
814 );
815 }
816}