1use crate::module_exports::ModuleContext;
32use crate::typed_module_exports::TypedReturn;
33use shape_value::NativeKind;
34use std::sync::Arc;
35
36pub trait FromSlot: Sized {
44 const NATIVE_KIND: NativeKind;
45 fn from_slot(bits: u64) -> Self;
49}
50
51pub trait ToSlot {
59 const NATIVE_KIND: NativeKind;
60 fn to_slot(self) -> u64;
61}
62
63#[derive(Debug, Clone, PartialEq)]
70pub enum MarshalError {
71 ArgCount { expected: usize, got: usize },
74 Body(String),
76}
77
78impl std::fmt::Display for MarshalError {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 MarshalError::ArgCount { expected, got } => {
82 write!(f, "expected {} arg(s), got {}", expected, got)
83 }
84 MarshalError::Body(msg) => f.write_str(msg),
85 }
86 }
87}
88
89impl std::error::Error for MarshalError {}
90
91impl From<MarshalError> for String {
92 fn from(e: MarshalError) -> Self {
93 e.to_string()
94 }
95}
96
97impl FromSlot for i64 {
100 const NATIVE_KIND: NativeKind = NativeKind::Int64;
101 #[inline]
102 fn from_slot(bits: u64) -> Self {
103 bits as i64
104 }
105}
106
107impl FromSlot for f64 {
108 const NATIVE_KIND: NativeKind = NativeKind::Float64;
109 #[inline]
110 fn from_slot(bits: u64) -> Self {
111 f64::from_bits(bits)
112 }
113}
114
115impl FromSlot for Option<f64> {
119 const NATIVE_KIND: NativeKind = NativeKind::NullableFloat64;
120 #[inline]
121 fn from_slot(bits: u64) -> Self {
122 let v = f64::from_bits(bits);
123 if v.is_nan() {
124 None
125 } else {
126 Some(v)
127 }
128 }
129}
130
131impl FromSlot for bool {
132 const NATIVE_KIND: NativeKind = NativeKind::Bool;
133 #[inline]
134 fn from_slot(bits: u64) -> Self {
135 bits != 0
136 }
137}
138
139impl FromSlot for Arc<String> {
146 const NATIVE_KIND: NativeKind = NativeKind::String;
147 #[inline]
148 fn from_slot(bits: u64) -> Self {
149 let ptr = bits as *const String;
150 unsafe {
155 Arc::increment_strong_count(ptr);
156 Arc::from_raw(ptr)
157 }
158 }
159}
160
161impl ToSlot for i64 {
164 const NATIVE_KIND: NativeKind = NativeKind::Int64;
165 #[inline]
166 fn to_slot(self) -> u64 {
167 self as u64
168 }
169}
170
171impl ToSlot for f64 {
172 const NATIVE_KIND: NativeKind = NativeKind::Float64;
173 #[inline]
174 fn to_slot(self) -> u64 {
175 self.to_bits()
176 }
177}
178
179impl ToSlot for bool {
180 const NATIVE_KIND: NativeKind = NativeKind::Bool;
181 #[inline]
182 fn to_slot(self) -> u64 {
183 self as u64
184 }
185}
186
187impl ToSlot for Arc<String> {
188 const NATIVE_KIND: NativeKind = NativeKind::String;
189 #[inline]
190 fn to_slot(self) -> u64 {
191 Arc::into_raw(self) as u64
192 }
193}
194
195impl FromSlot for Arc<shape_value::DataTable>
210where
211 Self: Sized,
212{
213 const NATIVE_KIND: NativeKind =
214 NativeKind::Ptr(shape_value::HeapKind::DataTable);
215 #[inline]
216 fn from_slot(bits: u64) -> Self {
217 let ptr = bits as *const shape_value::HeapValue;
218 unsafe {
222 Arc::increment_strong_count(ptr);
223 let arc_hv = Arc::from_raw(ptr);
224 match &*arc_hv {
225 shape_value::HeapValue::DataTable(arc_dt) => Arc::clone(arc_dt),
226 other => panic!(
227 "FromSlot<Arc<DataTable>>: slot bits decoded to HeapValue::{:?}, \
228 not DataTable. Marshal kind contract violated by caller.",
229 other.kind()
230 ),
231 }
232 }
233 }
234}
235
236impl ToSlot for Arc<shape_value::DataTable> {
239 const NATIVE_KIND: NativeKind =
240 NativeKind::Ptr(shape_value::HeapKind::DataTable);
241 #[inline]
242 fn to_slot(self) -> u64 {
243 let hv = Arc::new(shape_value::HeapValue::DataTable(self));
244 Arc::into_raw(hv) as u64
245 }
246}
247
248impl FromSlot for Arc<shape_value::heap_value::IoHandleData>
268where
269 Self: Sized,
270{
271 const NATIVE_KIND: NativeKind =
272 NativeKind::Ptr(shape_value::HeapKind::IoHandle);
273 #[inline]
274 fn from_slot(bits: u64) -> Self {
275 let ptr = bits as *const shape_value::HeapValue;
276 unsafe {
280 Arc::increment_strong_count(ptr);
281 let arc_hv = Arc::from_raw(ptr);
282 match &*arc_hv {
283 shape_value::HeapValue::IoHandle(arc_io) => Arc::clone(arc_io),
284 other => panic!(
285 "FromSlot<Arc<IoHandleData>>: slot bits decoded to HeapValue::{:?}, \
286 not IoHandle. Marshal kind contract violated by caller.",
287 other.kind()
288 ),
289 }
290 }
291 }
292}
293
294impl ToSlot for Arc<shape_value::heap_value::IoHandleData> {
297 const NATIVE_KIND: NativeKind =
298 NativeKind::Ptr(shape_value::HeapKind::IoHandle);
299 #[inline]
300 fn to_slot(self) -> u64 {
301 let hv = Arc::new(shape_value::HeapValue::IoHandle(self));
302 Arc::into_raw(hv) as u64
303 }
304}
305
306impl FromSlot for Vec<u8> {
363 const NATIVE_KIND: NativeKind =
364 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
365 #[inline]
366 fn from_slot(bits: u64) -> Self {
367 let arr = bits as usize as *const shape_value::v2::typed_array::TypedArray<u8>;
374 if arr.is_null() {
375 return Vec::new();
376 }
377 unsafe {
378 shape_value::v2::typed_array::TypedArray::<u8>::as_slice(arr).to_vec()
379 }
380 }
381}
382
383impl FromSlot for Vec<i64> {
388 const NATIVE_KIND: NativeKind =
389 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
390 #[inline]
391 fn from_slot(bits: u64) -> Self {
392 let arr = bits as usize as *const shape_value::v2::typed_array::TypedArray<i64>;
394 if arr.is_null() {
395 return Vec::new();
396 }
397 unsafe {
398 shape_value::v2::typed_array::TypedArray::<i64>::as_slice(arr).to_vec()
399 }
400 }
401}
402
403impl FromSlot for Vec<Arc<String>> {
412 const NATIVE_KIND: NativeKind =
413 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
414 #[inline]
415 fn from_slot(bits: u64) -> Self {
416 let arr = bits as usize
419 as *const shape_value::v2::typed_array::TypedArray<
420 *const shape_value::v2::string_obj::StringObj,
421 >;
422 if arr.is_null() {
423 return Vec::new();
424 }
425 unsafe {
426 let slice = shape_value::v2::typed_array::TypedArray::<
427 *const shape_value::v2::string_obj::StringObj,
428 >::as_slice(arr);
429 slice
430 .iter()
431 .map(|&p| {
432 Arc::new(
433 shape_value::v2::string_obj::StringObj::as_str(p).to_owned(),
434 )
435 })
436 .collect()
437 }
438 }
439}
440
441impl FromSlot for Vec<Arc<shape_value::heap_value::HeapValue>> {
465 const NATIVE_KIND: NativeKind =
466 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
467 #[inline]
468 fn from_slot(_bits: u64) -> Self {
469 panic!(
470 "FromSlot<Vec<Arc<HeapValue>>>: V3-S5 ckpt-5-prime²c SURFACE — \
471 the polymorphic Vec<Arc<HeapValue>> marshal path needs a \
472 per-element-T dispatcher over the v2-raw *mut TypedArray<T> \
473 carrier. Round 2 `Vec<Arc<HeapValue>>` rewire follow-up \
474 (pairs with from_typed_array_<T> constructor wave). \
475 ADR-006 §2.7.24 Q25.A SUPERSEDED."
476 )
477 }
478}
479
480impl ToSlot for Vec<Arc<String>> {
489 const NATIVE_KIND: NativeKind =
490 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
491 #[inline]
492 fn to_slot(self) -> u64 {
493 let elems: Vec<*const shape_value::v2::string_obj::StringObj> = self
494 .into_iter()
495 .map(|s| {
496 shape_value::v2::string_obj::StringObj::new(s.as_str())
497 as *const shape_value::v2::string_obj::StringObj
498 })
499 .collect();
500 let arr = shape_value::v2::typed_array::TypedArray::<
501 *const shape_value::v2::string_obj::StringObj,
502 >::from_slice(&elems);
503 arr as usize as u64
504 }
505}
506
507impl ToSlot for Vec<Arc<shape_value::heap_value::HeapValue>> {
519 const NATIVE_KIND: NativeKind =
520 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
521 #[inline]
522 fn to_slot(self) -> u64 {
523 panic!(
524 "ToSlot<Vec<Arc<HeapValue>>>: V3-S5 ckpt-5-prime²c SURFACE — \
525 polymorphic Vec<Arc<HeapValue>> projection needs a per-element-T \
526 dispatcher over the v2-raw *mut TypedArray<T> carrier (mirror \
527 of the deleted build_specialized_from_heap_arcs). Round 2 \
528 `Vec<Arc<HeapValue>>` rewire follow-up. ADR-006 §2.7.24 Q25.A \
529 SUPERSEDED."
530 )
531 }
532}
533
534impl FromSlot for Vec<(Arc<String>, Arc<String>)> {
576 const NATIVE_KIND: NativeKind =
577 NativeKind::Ptr(shape_value::HeapKind::HashMap);
578 #[inline]
579 fn from_slot(bits: u64) -> Self {
580 let ptr = bits as *const shape_value::HeapValue;
581 unsafe {
584 Arc::increment_strong_count(ptr);
585 let arc_hv = Arc::from_raw(ptr);
586 match &*arc_hv {
587 shape_value::HeapValue::HashMap(kref) => {
588 use shape_value::heap_value::HashMapKindedRef;
594 match kref {
595 HashMapKindedRef::String(arc) => {
596 let n = arc.len();
597 let mut out: Vec<(Arc<String>, Arc<String>)> =
598 Vec::with_capacity(n);
599 for i in 0..n {
600 let key = unsafe {
601 let ptr = shape_value::v2::typed_array::TypedArray::get_unchecked(
602 arc.keys, i as u32,
603 );
604 Arc::new(
605 shape_value::v2::string_obj::StringObj::as_str(ptr)
606 .to_owned(),
607 )
608 };
609 let val = unsafe {
610 let v_ptr: *const shape_value::v2::string_obj::StringObj =
611 *(*arc.values).data.add(i);
612 Arc::new(
613 shape_value::v2::string_obj::StringObj::as_str(v_ptr)
614 .to_owned(),
615 )
616 };
617 out.push((key, val));
618 }
619 out
620 }
621 other => panic!(
622 "FromSlot<Vec<(Arc<String>, Arc<String>)>>: HashMap V \
623 variant {:?} not supported — marshal contract requires \
624 V=String. ADR-006 §2.7.24 Q25.B SUPERSEDED.",
625 other.values_kind()
626 ),
627 }
628 }
629 other => panic!(
630 "FromSlot<Vec<(Arc<String>, Arc<String>)>>: slot bits decoded to \
631 HeapValue::{:?}, not HashMap. Marshal kind contract violated by caller.",
632 other.kind()
633 ),
634 }
635 }
636 }
637}
638
639impl FromSlot for Vec<(Arc<String>, Arc<shape_value::heap_value::HeapValue>)> {
649 const NATIVE_KIND: NativeKind =
650 NativeKind::Ptr(shape_value::HeapKind::HashMap);
651 #[inline]
652 fn from_slot(bits: u64) -> Self {
653 let ptr = bits as *const shape_value::HeapValue;
654 unsafe {
656 Arc::increment_strong_count(ptr);
657 let arc_hv = Arc::from_raw(ptr);
658 match &*arc_hv {
659 shape_value::HeapValue::HashMap(kref) => {
660 use shape_value::heap_value::{HashMapKindedRef, HeapValue};
665 let n = kref.len();
666 let mut out: Vec<(Arc<String>, Arc<HeapValue>)> = Vec::with_capacity(n);
667 let keys_ptr = match kref {
668 HashMapKindedRef::I64(arc) => arc.keys,
669 HashMapKindedRef::F64(arc) => arc.keys,
670 HashMapKindedRef::Bool(arc) => arc.keys,
671 HashMapKindedRef::Char(arc) => arc.keys,
672 HashMapKindedRef::String(arc) => arc.keys,
673 HashMapKindedRef::Decimal(arc) => arc.keys,
674 HashMapKindedRef::TypedObject(arc) => arc.keys,
675 HashMapKindedRef::TraitObject(arc) => arc.keys,
676 HashMapKindedRef::HashMap(arc) => arc.keys,
677 };
678 for i in 0..n {
679 let key = unsafe {
680 let ptr = shape_value::v2::typed_array::TypedArray::get_unchecked(
681 keys_ptr, i as u32,
682 );
683 Arc::new(
684 shape_value::v2::string_obj::StringObj::as_str(ptr)
685 .to_owned(),
686 )
687 };
688 let value: Arc<HeapValue> = match kref {
689 HashMapKindedRef::I64(arc) => {
690 let v: i64 = unsafe { *(*arc.values).data.add(i) };
691 Arc::new(HeapValue::BigInt(Arc::new(v)))
692 }
693 HashMapKindedRef::F64(_) => {
694 panic!(
695 "FromSlot<Vec<(Arc<String>, Arc<HeapValue>)>>: \
696 HashMap<string, number> has no canonical \
697 HeapValue arm (number is inline-scalar). \
698 Marshal contract violation."
699 );
700 }
701 HashMapKindedRef::Bool(_) => {
702 panic!(
703 "FromSlot<Vec<(Arc<String>, Arc<HeapValue>)>>: \
704 HashMap<string, bool> has no canonical \
705 HeapValue arm (bool is inline-scalar). \
706 Marshal contract violation."
707 );
708 }
709 HashMapKindedRef::Char(arc) => {
710 let v: char = unsafe { *(*arc.values).data.add(i) };
711 Arc::new(HeapValue::Char(v))
712 }
713 HashMapKindedRef::String(arc) => {
714 let ptr: *const shape_value::v2::string_obj::StringObj =
715 unsafe { *(*arc.values).data.add(i) };
716 let s = unsafe {
717 shape_value::v2::string_obj::StringObj::as_str(ptr)
718 .to_owned()
719 };
720 Arc::new(HeapValue::String(Arc::new(s)))
721 }
722 HashMapKindedRef::Decimal(arc) => {
723 let ptr: *const shape_value::v2::decimal_obj::DecimalObj =
724 unsafe { *(*arc.values).data.add(i) };
725 let d = unsafe { (*ptr).value };
726 Arc::new(HeapValue::Decimal(Arc::new(d)))
727 }
728 HashMapKindedRef::TypedObject(arc) => {
729 let elem: &shape_value::heap_value::TypedObjectPtr =
730 unsafe { &*(*arc.values).data.add(i) };
731 Arc::new(HeapValue::TypedObject(elem.clone()))
732 }
733 HashMapKindedRef::TraitObject(_) => {
734 panic!(
735 "FromSlot<Vec<(Arc<String>, Arc<HeapValue>)>>: \
736 HashMap<string, TraitObject> marshal not yet \
737 wired (HeapValue::TraitObject arm exists but \
738 payload kind dispatch is its own cluster)."
739 );
740 }
741 HashMapKindedRef::HashMap(arc) => {
742 let inner_ref: &HashMapKindedRef =
753 &*(*arc.values).data.add(i);
754 Arc::new(HeapValue::HashMap(inner_ref.clone()))
755 }
756 };
757 out.push((key, value));
758 }
759 out
760 }
761 other => panic!(
762 "FromSlot<Vec<(Arc<String>, Arc<HeapValue>)>>: slot bits decoded to \
763 HeapValue::{:?}, not HashMap. Marshal kind contract violated by caller.",
764 other.kind()
765 ),
766 }
767 }
768 }
769}
770
771impl FromSlot for Arc<Vec<f64>> {
805 const NATIVE_KIND: NativeKind =
806 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
807 #[inline]
808 fn from_slot(bits: u64) -> Self {
809 let arr = bits as usize as *const shape_value::v2::typed_array::TypedArray<f64>;
813 if arr.is_null() {
814 return Arc::new(Vec::new());
815 }
816 unsafe {
817 Arc::new(
818 shape_value::v2::typed_array::TypedArray::<f64>::as_slice(arr).to_vec(),
819 )
820 }
821 }
822}
823
824impl ToSlot for Arc<Vec<f64>> {
829 const NATIVE_KIND: NativeKind =
830 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
831 #[inline]
832 fn to_slot(self) -> u64 {
833 let arr = shape_value::v2::typed_array::TypedArray::<f64>::from_slice(self.as_slice());
834 arr as usize as u64
835 }
836}
837
838impl FromSlot for Arc<Vec<i64>> {
843 const NATIVE_KIND: NativeKind =
844 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
845 #[inline]
846 fn from_slot(bits: u64) -> Self {
847 let arr = bits as usize as *const shape_value::v2::typed_array::TypedArray<i64>;
849 if arr.is_null() {
850 return Arc::new(Vec::new());
851 }
852 unsafe {
853 Arc::new(
854 shape_value::v2::typed_array::TypedArray::<i64>::as_slice(arr).to_vec(),
855 )
856 }
857 }
858}
859
860impl ToSlot for Arc<Vec<i64>> {
864 const NATIVE_KIND: NativeKind =
865 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
866 #[inline]
867 fn to_slot(self) -> u64 {
868 let arr = shape_value::v2::typed_array::TypedArray::<i64>::from_slice(self.as_slice());
869 arr as usize as u64
870 }
871}
872
873impl FromSlot for Arc<Vec<u8>> {
886 const NATIVE_KIND: NativeKind =
887 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
888 #[inline]
889 fn from_slot(bits: u64) -> Self {
890 let arr = bits as usize as *const shape_value::v2::typed_array::TypedArray<u8>;
892 if arr.is_null() {
893 return Arc::new(Vec::new());
894 }
895 unsafe {
896 Arc::new(
897 shape_value::v2::typed_array::TypedArray::<u8>::as_slice(arr).to_vec(),
898 )
899 }
900 }
901}
902
903impl ToSlot for Arc<Vec<u8>> {
907 const NATIVE_KIND: NativeKind =
908 NativeKind::Ptr(shape_value::HeapKind::TypedArray);
909 #[inline]
910 fn to_slot(self) -> u64 {
911 let arr = shape_value::v2::typed_array::TypedArray::<u8>::from_slice(self.as_slice());
912 arr as usize as u64
913 }
914}
915
916type TypedInvoke = Arc<
923 dyn for<'ctx> Fn(&[u64], &ModuleContext<'ctx>) -> Result<TypedReturn, String>
924 + Send
925 + Sync,
926>;
927
928pub fn register_typed_fn_0<F>(
931 module: &mut crate::module_exports::ModuleExports,
932 name: impl Into<String>,
933 description: impl Into<String>,
934 return_type: crate::typed_module_exports::ConcreteType,
935 body: F,
936) where
937 F: for<'ctx> Fn(&ModuleContext<'ctx>) -> Result<TypedReturn, String>
938 + Send
939 + Sync
940 + 'static,
941{
942 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
943 if !slots.is_empty() {
944 return Err(MarshalError::ArgCount {
945 expected: 0,
946 got: slots.len(),
947 }
948 .into());
949 }
950 body(ctx)
951 });
952 install(module, name, description, vec![], return_type, vec![], invoke);
953}
954
955pub fn register_typed_fn_1<F, P0>(
959 module: &mut crate::module_exports::ModuleExports,
960 name: impl Into<String>,
961 description: impl Into<String>,
962 param_name: impl Into<String>,
963 param_type_name: impl Into<String>,
964 return_type: crate::typed_module_exports::ConcreteType,
965 body: F,
966) where
967 F: for<'ctx> Fn(P0, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
968 + Send
969 + Sync
970 + 'static,
971 P0: FromSlot + Send + Sync + 'static,
972{
973 let arg_kinds = vec![P0::NATIVE_KIND];
974 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
975 if slots.len() != 1 {
976 return Err(MarshalError::ArgCount {
977 expected: 1,
978 got: slots.len(),
979 }
980 .into());
981 }
982 let p0 = P0::from_slot(slots[0]);
983 body(p0, ctx)
984 });
985 let params = vec![crate::module_exports::ModuleParam {
986 name: param_name.into(),
987 type_name: param_type_name.into(),
988 required: true,
989 ..Default::default()
990 }];
991 install(
992 module,
993 name,
994 description,
995 params,
996 return_type,
997 arg_kinds,
998 invoke,
999 );
1000}
1001
1002pub fn register_typed_fn_2<F, P0, P1>(
1004 module: &mut crate::module_exports::ModuleExports,
1005 name: impl Into<String>,
1006 description: impl Into<String>,
1007 param_names: [(&str, &str); 2],
1008 return_type: crate::typed_module_exports::ConcreteType,
1009 body: F,
1010) where
1011 F: for<'ctx> Fn(P0, P1, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1012 + Send
1013 + Sync
1014 + 'static,
1015 P0: FromSlot + Send + Sync + 'static,
1016 P1: FromSlot + Send + Sync + 'static,
1017{
1018 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND];
1019 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1020 if slots.len() != 2 {
1021 return Err(MarshalError::ArgCount {
1022 expected: 2,
1023 got: slots.len(),
1024 }
1025 .into());
1026 }
1027 let p0 = P0::from_slot(slots[0]);
1028 let p1 = P1::from_slot(slots[1]);
1029 body(p0, p1, ctx)
1030 });
1031 let params = param_names
1032 .iter()
1033 .map(|(name, ty)| crate::module_exports::ModuleParam {
1034 name: (*name).to_string(),
1035 type_name: (*ty).to_string(),
1036 required: true,
1037 ..Default::default()
1038 })
1039 .collect();
1040 install(
1041 module,
1042 name,
1043 description,
1044 params,
1045 return_type,
1046 arg_kinds,
1047 invoke,
1048 );
1049}
1050
1051pub fn register_typed_fn_3<F, P0, P1, P2>(
1053 module: &mut crate::module_exports::ModuleExports,
1054 name: impl Into<String>,
1055 description: impl Into<String>,
1056 param_names: [(&str, &str); 3],
1057 return_type: crate::typed_module_exports::ConcreteType,
1058 body: F,
1059) where
1060 F: for<'ctx> Fn(P0, P1, P2, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1061 + Send
1062 + Sync
1063 + 'static,
1064 P0: FromSlot + Send + Sync + 'static,
1065 P1: FromSlot + Send + Sync + 'static,
1066 P2: FromSlot + Send + Sync + 'static,
1067{
1068 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND, P2::NATIVE_KIND];
1069 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1070 if slots.len() != 3 {
1071 return Err(MarshalError::ArgCount {
1072 expected: 3,
1073 got: slots.len(),
1074 }
1075 .into());
1076 }
1077 let p0 = P0::from_slot(slots[0]);
1078 let p1 = P1::from_slot(slots[1]);
1079 let p2 = P2::from_slot(slots[2]);
1080 body(p0, p1, p2, ctx)
1081 });
1082 let params = param_names
1083 .iter()
1084 .map(|(name, ty)| crate::module_exports::ModuleParam {
1085 name: (*name).to_string(),
1086 type_name: (*ty).to_string(),
1087 required: true,
1088 ..Default::default()
1089 })
1090 .collect();
1091 install(
1092 module,
1093 name,
1094 description,
1095 params,
1096 return_type,
1097 arg_kinds,
1098 invoke,
1099 );
1100}
1101
1102pub fn register_typed_fn_1_full<F, P0>(
1121 module: &mut crate::module_exports::ModuleExports,
1122 name: impl Into<String>,
1123 description: impl Into<String>,
1124 params: [crate::module_exports::ModuleParam; 1],
1125 return_type: crate::typed_module_exports::ConcreteType,
1126 body: F,
1127) where
1128 F: for<'ctx> Fn(P0, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1129 + Send
1130 + Sync
1131 + 'static,
1132 P0: FromSlot + Send + Sync + 'static,
1133{
1134 let arg_kinds = vec![P0::NATIVE_KIND];
1135 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1136 if slots.len() != 1 {
1137 return Err(MarshalError::ArgCount {
1138 expected: 1,
1139 got: slots.len(),
1140 }
1141 .into());
1142 }
1143 let p0 = P0::from_slot(slots[0]);
1144 body(p0, ctx)
1145 });
1146 install(
1147 module,
1148 name,
1149 description,
1150 params.into_iter().collect(),
1151 return_type,
1152 arg_kinds,
1153 invoke,
1154 );
1155}
1156
1157pub fn register_typed_fn_2_full<F, P0, P1>(
1159 module: &mut crate::module_exports::ModuleExports,
1160 name: impl Into<String>,
1161 description: impl Into<String>,
1162 params: [crate::module_exports::ModuleParam; 2],
1163 return_type: crate::typed_module_exports::ConcreteType,
1164 body: F,
1165) where
1166 F: for<'ctx> Fn(P0, P1, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1167 + Send
1168 + Sync
1169 + 'static,
1170 P0: FromSlot + Send + Sync + 'static,
1171 P1: FromSlot + Send + Sync + 'static,
1172{
1173 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND];
1174 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1175 if slots.len() != 2 {
1176 return Err(MarshalError::ArgCount {
1177 expected: 2,
1178 got: slots.len(),
1179 }
1180 .into());
1181 }
1182 let p0 = P0::from_slot(slots[0]);
1183 let p1 = P1::from_slot(slots[1]);
1184 body(p0, p1, ctx)
1185 });
1186 install(
1187 module,
1188 name,
1189 description,
1190 params.into_iter().collect(),
1191 return_type,
1192 arg_kinds,
1193 invoke,
1194 );
1195}
1196
1197pub fn register_typed_fn_3_full<F, P0, P1, P2>(
1199 module: &mut crate::module_exports::ModuleExports,
1200 name: impl Into<String>,
1201 description: impl Into<String>,
1202 params: [crate::module_exports::ModuleParam; 3],
1203 return_type: crate::typed_module_exports::ConcreteType,
1204 body: F,
1205) where
1206 F: for<'ctx> Fn(P0, P1, P2, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1207 + Send
1208 + Sync
1209 + 'static,
1210 P0: FromSlot + Send + Sync + 'static,
1211 P1: FromSlot + Send + Sync + 'static,
1212 P2: FromSlot + Send + Sync + 'static,
1213{
1214 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND, P2::NATIVE_KIND];
1215 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1216 if slots.len() != 3 {
1217 return Err(MarshalError::ArgCount {
1218 expected: 3,
1219 got: slots.len(),
1220 }
1221 .into());
1222 }
1223 let p0 = P0::from_slot(slots[0]);
1224 let p1 = P1::from_slot(slots[1]);
1225 let p2 = P2::from_slot(slots[2]);
1226 body(p0, p1, p2, ctx)
1227 });
1228 install(
1229 module,
1230 name,
1231 description,
1232 params.into_iter().collect(),
1233 return_type,
1234 arg_kinds,
1235 invoke,
1236 );
1237}
1238
1239pub fn register_typed_fn_4<F, P0, P1, P2, P3>(
1254 module: &mut crate::module_exports::ModuleExports,
1255 name: impl Into<String>,
1256 description: impl Into<String>,
1257 param_names: [(&str, &str); 4],
1258 return_type: crate::typed_module_exports::ConcreteType,
1259 body: F,
1260) where
1261 F: for<'ctx> Fn(P0, P1, P2, P3, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1262 + Send
1263 + Sync
1264 + 'static,
1265 P0: FromSlot + Send + Sync + 'static,
1266 P1: FromSlot + Send + Sync + 'static,
1267 P2: FromSlot + Send + Sync + 'static,
1268 P3: FromSlot + Send + Sync + 'static,
1269{
1270 let arg_kinds = vec![
1271 P0::NATIVE_KIND,
1272 P1::NATIVE_KIND,
1273 P2::NATIVE_KIND,
1274 P3::NATIVE_KIND,
1275 ];
1276 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1277 if slots.len() != 4 {
1278 return Err(MarshalError::ArgCount {
1279 expected: 4,
1280 got: slots.len(),
1281 }
1282 .into());
1283 }
1284 let p0 = P0::from_slot(slots[0]);
1285 let p1 = P1::from_slot(slots[1]);
1286 let p2 = P2::from_slot(slots[2]);
1287 let p3 = P3::from_slot(slots[3]);
1288 body(p0, p1, p2, p3, ctx)
1289 });
1290 let params = param_names
1291 .iter()
1292 .map(|(name, ty)| crate::module_exports::ModuleParam {
1293 name: (*name).to_string(),
1294 type_name: (*ty).to_string(),
1295 required: true,
1296 ..Default::default()
1297 })
1298 .collect();
1299 install(
1300 module,
1301 name,
1302 description,
1303 params,
1304 return_type,
1305 arg_kinds,
1306 invoke,
1307 );
1308}
1309
1310pub fn register_typed_fn_5<F, P0, P1, P2, P3, P4>(
1312 module: &mut crate::module_exports::ModuleExports,
1313 name: impl Into<String>,
1314 description: impl Into<String>,
1315 param_names: [(&str, &str); 5],
1316 return_type: crate::typed_module_exports::ConcreteType,
1317 body: F,
1318) where
1319 F: for<'ctx> Fn(P0, P1, P2, P3, P4, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1320 + Send
1321 + Sync
1322 + 'static,
1323 P0: FromSlot + Send + Sync + 'static,
1324 P1: FromSlot + Send + Sync + 'static,
1325 P2: FromSlot + Send + Sync + 'static,
1326 P3: FromSlot + Send + Sync + 'static,
1327 P4: FromSlot + Send + Sync + 'static,
1328{
1329 let arg_kinds = vec![
1330 P0::NATIVE_KIND,
1331 P1::NATIVE_KIND,
1332 P2::NATIVE_KIND,
1333 P3::NATIVE_KIND,
1334 P4::NATIVE_KIND,
1335 ];
1336 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1337 if slots.len() != 5 {
1338 return Err(MarshalError::ArgCount {
1339 expected: 5,
1340 got: slots.len(),
1341 }
1342 .into());
1343 }
1344 let p0 = P0::from_slot(slots[0]);
1345 let p1 = P1::from_slot(slots[1]);
1346 let p2 = P2::from_slot(slots[2]);
1347 let p3 = P3::from_slot(slots[3]);
1348 let p4 = P4::from_slot(slots[4]);
1349 body(p0, p1, p2, p3, p4, ctx)
1350 });
1351 let params = param_names
1352 .iter()
1353 .map(|(name, ty)| crate::module_exports::ModuleParam {
1354 name: (*name).to_string(),
1355 type_name: (*ty).to_string(),
1356 required: true,
1357 ..Default::default()
1358 })
1359 .collect();
1360 install(
1361 module,
1362 name,
1363 description,
1364 params,
1365 return_type,
1366 arg_kinds,
1367 invoke,
1368 );
1369}
1370
1371pub fn register_typed_fn_6<F, P0, P1, P2, P3, P4, P5>(
1373 module: &mut crate::module_exports::ModuleExports,
1374 name: impl Into<String>,
1375 description: impl Into<String>,
1376 param_names: [(&str, &str); 6],
1377 return_type: crate::typed_module_exports::ConcreteType,
1378 body: F,
1379) where
1380 F: for<'ctx> Fn(P0, P1, P2, P3, P4, P5, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1381 + Send
1382 + Sync
1383 + 'static,
1384 P0: FromSlot + Send + Sync + 'static,
1385 P1: FromSlot + Send + Sync + 'static,
1386 P2: FromSlot + Send + Sync + 'static,
1387 P3: FromSlot + Send + Sync + 'static,
1388 P4: FromSlot + Send + Sync + 'static,
1389 P5: FromSlot + Send + Sync + 'static,
1390{
1391 let arg_kinds = vec![
1392 P0::NATIVE_KIND,
1393 P1::NATIVE_KIND,
1394 P2::NATIVE_KIND,
1395 P3::NATIVE_KIND,
1396 P4::NATIVE_KIND,
1397 P5::NATIVE_KIND,
1398 ];
1399 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1400 if slots.len() != 6 {
1401 return Err(MarshalError::ArgCount {
1402 expected: 6,
1403 got: slots.len(),
1404 }
1405 .into());
1406 }
1407 let p0 = P0::from_slot(slots[0]);
1408 let p1 = P1::from_slot(slots[1]);
1409 let p2 = P2::from_slot(slots[2]);
1410 let p3 = P3::from_slot(slots[3]);
1411 let p4 = P4::from_slot(slots[4]);
1412 let p5 = P5::from_slot(slots[5]);
1413 body(p0, p1, p2, p3, p4, p5, ctx)
1414 });
1415 let params = param_names
1416 .iter()
1417 .map(|(name, ty)| crate::module_exports::ModuleParam {
1418 name: (*name).to_string(),
1419 type_name: (*ty).to_string(),
1420 required: true,
1421 ..Default::default()
1422 })
1423 .collect();
1424 install(
1425 module,
1426 name,
1427 description,
1428 params,
1429 return_type,
1430 arg_kinds,
1431 invoke,
1432 );
1433}
1434
1435pub fn register_typed_fn_4_full<F, P0, P1, P2, P3>(
1437 module: &mut crate::module_exports::ModuleExports,
1438 name: impl Into<String>,
1439 description: impl Into<String>,
1440 params: [crate::module_exports::ModuleParam; 4],
1441 return_type: crate::typed_module_exports::ConcreteType,
1442 body: F,
1443) where
1444 F: for<'ctx> Fn(P0, P1, P2, P3, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1445 + Send
1446 + Sync
1447 + 'static,
1448 P0: FromSlot + Send + Sync + 'static,
1449 P1: FromSlot + Send + Sync + 'static,
1450 P2: FromSlot + Send + Sync + 'static,
1451 P3: FromSlot + Send + Sync + 'static,
1452{
1453 let arg_kinds = vec![
1454 P0::NATIVE_KIND,
1455 P1::NATIVE_KIND,
1456 P2::NATIVE_KIND,
1457 P3::NATIVE_KIND,
1458 ];
1459 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1460 if slots.len() != 4 {
1461 return Err(MarshalError::ArgCount {
1462 expected: 4,
1463 got: slots.len(),
1464 }
1465 .into());
1466 }
1467 let p0 = P0::from_slot(slots[0]);
1468 let p1 = P1::from_slot(slots[1]);
1469 let p2 = P2::from_slot(slots[2]);
1470 let p3 = P3::from_slot(slots[3]);
1471 body(p0, p1, p2, p3, ctx)
1472 });
1473 install(
1474 module,
1475 name,
1476 description,
1477 params.into_iter().collect(),
1478 return_type,
1479 arg_kinds,
1480 invoke,
1481 );
1482}
1483
1484pub fn register_typed_fn_5_full<F, P0, P1, P2, P3, P4>(
1486 module: &mut crate::module_exports::ModuleExports,
1487 name: impl Into<String>,
1488 description: impl Into<String>,
1489 params: [crate::module_exports::ModuleParam; 5],
1490 return_type: crate::typed_module_exports::ConcreteType,
1491 body: F,
1492) where
1493 F: for<'ctx> Fn(P0, P1, P2, P3, P4, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1494 + Send
1495 + Sync
1496 + 'static,
1497 P0: FromSlot + Send + Sync + 'static,
1498 P1: FromSlot + Send + Sync + 'static,
1499 P2: FromSlot + Send + Sync + 'static,
1500 P3: FromSlot + Send + Sync + 'static,
1501 P4: FromSlot + Send + Sync + 'static,
1502{
1503 let arg_kinds = vec![
1504 P0::NATIVE_KIND,
1505 P1::NATIVE_KIND,
1506 P2::NATIVE_KIND,
1507 P3::NATIVE_KIND,
1508 P4::NATIVE_KIND,
1509 ];
1510 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1511 if slots.len() != 5 {
1512 return Err(MarshalError::ArgCount {
1513 expected: 5,
1514 got: slots.len(),
1515 }
1516 .into());
1517 }
1518 let p0 = P0::from_slot(slots[0]);
1519 let p1 = P1::from_slot(slots[1]);
1520 let p2 = P2::from_slot(slots[2]);
1521 let p3 = P3::from_slot(slots[3]);
1522 let p4 = P4::from_slot(slots[4]);
1523 body(p0, p1, p2, p3, p4, ctx)
1524 });
1525 install(
1526 module,
1527 name,
1528 description,
1529 params.into_iter().collect(),
1530 return_type,
1531 arg_kinds,
1532 invoke,
1533 );
1534}
1535
1536pub fn register_typed_fn_6_full<F, P0, P1, P2, P3, P4, P5>(
1538 module: &mut crate::module_exports::ModuleExports,
1539 name: impl Into<String>,
1540 description: impl Into<String>,
1541 params: [crate::module_exports::ModuleParam; 6],
1542 return_type: crate::typed_module_exports::ConcreteType,
1543 body: F,
1544) where
1545 F: for<'ctx> Fn(P0, P1, P2, P3, P4, P5, &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1546 + Send
1547 + Sync
1548 + 'static,
1549 P0: FromSlot + Send + Sync + 'static,
1550 P1: FromSlot + Send + Sync + 'static,
1551 P2: FromSlot + Send + Sync + 'static,
1552 P3: FromSlot + Send + Sync + 'static,
1553 P4: FromSlot + Send + Sync + 'static,
1554 P5: FromSlot + Send + Sync + 'static,
1555{
1556 let arg_kinds = vec![
1557 P0::NATIVE_KIND,
1558 P1::NATIVE_KIND,
1559 P2::NATIVE_KIND,
1560 P3::NATIVE_KIND,
1561 P4::NATIVE_KIND,
1562 P5::NATIVE_KIND,
1563 ];
1564 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
1565 if slots.len() != 6 {
1566 return Err(MarshalError::ArgCount {
1567 expected: 6,
1568 got: slots.len(),
1569 }
1570 .into());
1571 }
1572 let p0 = P0::from_slot(slots[0]);
1573 let p1 = P1::from_slot(slots[1]);
1574 let p2 = P2::from_slot(slots[2]);
1575 let p3 = P3::from_slot(slots[3]);
1576 let p4 = P4::from_slot(slots[4]);
1577 let p5 = P5::from_slot(slots[5]);
1578 body(p0, p1, p2, p3, p4, p5, ctx)
1579 });
1580 install(
1581 module,
1582 name,
1583 description,
1584 params.into_iter().collect(),
1585 return_type,
1586 arg_kinds,
1587 invoke,
1588 );
1589}
1590
1591fn install(
1594 module: &mut crate::module_exports::ModuleExports,
1595 name: impl Into<String>,
1596 description: impl Into<String>,
1597 params: Vec<crate::module_exports::ModuleParam>,
1598 return_type: crate::typed_module_exports::ConcreteType,
1599 arg_kinds: Vec<NativeKind>,
1600 invoke: TypedInvoke,
1601) {
1602 use crate::module_exports::ModuleFunction;
1603 use crate::typed_module_exports::TypedModuleFunction;
1604
1605 let name = name.into();
1606 let arg_types: Vec<String> = params.iter().map(|p| p.type_name.clone()).collect();
1607 let return_type_str = return_type.shape_type_name();
1608 module.add_schema_only(
1609 name.clone(),
1610 ModuleFunction {
1611 description: description.into(),
1612 params,
1613 return_type: Some(return_type_str),
1614 },
1615 );
1616 module.typed_exports_mut().functions.insert(
1617 name,
1618 TypedModuleFunction {
1619 invoke,
1620 return_type,
1621 arg_types,
1622 arg_kinds,
1623 },
1624 );
1625}
1626
1627type TypedAsyncInvoke = Arc<
1645 dyn Fn(
1646 Vec<u64>,
1647 )
1648 -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<TypedReturn, String>> + Send>>
1649 + Send
1650 + Sync,
1651>;
1652
1653pub fn register_typed_async_fn_1<F, Fut, P0>(
1656 module: &mut crate::module_exports::ModuleExports,
1657 name: impl Into<String>,
1658 description: impl Into<String>,
1659 param_name: impl Into<String>,
1660 param_type_name: impl Into<String>,
1661 return_type: crate::typed_module_exports::ConcreteType,
1662 body: F,
1663) where
1664 F: Fn(P0) -> Fut + Send + Sync + Clone + 'static,
1665 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1666 P0: FromSlot + Send + Sync + 'static,
1667{
1668 let arg_kinds = vec![P0::NATIVE_KIND];
1669 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1670 if slots.len() != 1 {
1671 let err = MarshalError::ArgCount {
1672 expected: 1,
1673 got: slots.len(),
1674 };
1675 return Box::pin(async move { Err(err.into()) });
1676 }
1677 let p0 = P0::from_slot(slots[0]);
1678 let body = body.clone();
1679 Box::pin(async move { body(p0).await })
1680 });
1681 let params = vec![crate::module_exports::ModuleParam {
1682 name: param_name.into(),
1683 type_name: param_type_name.into(),
1684 required: true,
1685 ..Default::default()
1686 }];
1687 install_async(module, name, description, params, return_type, arg_kinds, invoke);
1688}
1689
1690pub fn register_typed_async_fn_2<F, Fut, P0, P1>(
1692 module: &mut crate::module_exports::ModuleExports,
1693 name: impl Into<String>,
1694 description: impl Into<String>,
1695 param_names: [(&str, &str); 2],
1696 return_type: crate::typed_module_exports::ConcreteType,
1697 body: F,
1698) where
1699 F: Fn(P0, P1) -> Fut + Send + Sync + Clone + 'static,
1700 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1701 P0: FromSlot + Send + Sync + 'static,
1702 P1: FromSlot + Send + Sync + 'static,
1703{
1704 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND];
1705 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1706 if slots.len() != 2 {
1707 let err = MarshalError::ArgCount {
1708 expected: 2,
1709 got: slots.len(),
1710 };
1711 return Box::pin(async move { Err(err.into()) });
1712 }
1713 let p0 = P0::from_slot(slots[0]);
1714 let p1 = P1::from_slot(slots[1]);
1715 let body = body.clone();
1716 Box::pin(async move { body(p0, p1).await })
1717 });
1718 let params = param_names
1719 .iter()
1720 .map(|(name, ty)| crate::module_exports::ModuleParam {
1721 name: (*name).to_string(),
1722 type_name: (*ty).to_string(),
1723 required: true,
1724 ..Default::default()
1725 })
1726 .collect();
1727 install_async(module, name, description, params, return_type, arg_kinds, invoke);
1728}
1729
1730pub fn register_typed_async_fn_3<F, Fut, P0, P1, P2>(
1732 module: &mut crate::module_exports::ModuleExports,
1733 name: impl Into<String>,
1734 description: impl Into<String>,
1735 param_names: [(&str, &str); 3],
1736 return_type: crate::typed_module_exports::ConcreteType,
1737 body: F,
1738) where
1739 F: Fn(P0, P1, P2) -> Fut + Send + Sync + Clone + 'static,
1740 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1741 P0: FromSlot + Send + Sync + 'static,
1742 P1: FromSlot + Send + Sync + 'static,
1743 P2: FromSlot + Send + Sync + 'static,
1744{
1745 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND, P2::NATIVE_KIND];
1746 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1747 if slots.len() != 3 {
1748 let err = MarshalError::ArgCount {
1749 expected: 3,
1750 got: slots.len(),
1751 };
1752 return Box::pin(async move { Err(err.into()) });
1753 }
1754 let p0 = P0::from_slot(slots[0]);
1755 let p1 = P1::from_slot(slots[1]);
1756 let p2 = P2::from_slot(slots[2]);
1757 let body = body.clone();
1758 Box::pin(async move { body(p0, p1, p2).await })
1759 });
1760 let params = param_names
1761 .iter()
1762 .map(|(name, ty)| crate::module_exports::ModuleParam {
1763 name: (*name).to_string(),
1764 type_name: (*ty).to_string(),
1765 required: true,
1766 ..Default::default()
1767 })
1768 .collect();
1769 install_async(module, name, description, params, return_type, arg_kinds, invoke);
1770}
1771
1772pub fn register_typed_async_fn_1_full<F, Fut, P0>(
1779 module: &mut crate::module_exports::ModuleExports,
1780 name: impl Into<String>,
1781 description: impl Into<String>,
1782 params: [crate::module_exports::ModuleParam; 1],
1783 return_type: crate::typed_module_exports::ConcreteType,
1784 body: F,
1785) where
1786 F: Fn(P0) -> Fut + Send + Sync + Clone + 'static,
1787 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1788 P0: FromSlot + Send + Sync + 'static,
1789{
1790 let arg_kinds = vec![P0::NATIVE_KIND];
1791 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1792 if slots.len() != 1 {
1793 let err = MarshalError::ArgCount {
1794 expected: 1,
1795 got: slots.len(),
1796 };
1797 return Box::pin(async move { Err(err.into()) });
1798 }
1799 let p0 = P0::from_slot(slots[0]);
1800 let body = body.clone();
1801 Box::pin(async move { body(p0).await })
1802 });
1803 install_async(
1804 module,
1805 name,
1806 description,
1807 params.into_iter().collect(),
1808 return_type,
1809 arg_kinds,
1810 invoke,
1811 );
1812}
1813
1814pub fn register_typed_async_fn_2_full<F, Fut, P0, P1>(
1816 module: &mut crate::module_exports::ModuleExports,
1817 name: impl Into<String>,
1818 description: impl Into<String>,
1819 params: [crate::module_exports::ModuleParam; 2],
1820 return_type: crate::typed_module_exports::ConcreteType,
1821 body: F,
1822) where
1823 F: Fn(P0, P1) -> Fut + Send + Sync + Clone + 'static,
1824 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1825 P0: FromSlot + Send + Sync + 'static,
1826 P1: FromSlot + Send + Sync + 'static,
1827{
1828 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND];
1829 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1830 if slots.len() != 2 {
1831 let err = MarshalError::ArgCount {
1832 expected: 2,
1833 got: slots.len(),
1834 };
1835 return Box::pin(async move { Err(err.into()) });
1836 }
1837 let p0 = P0::from_slot(slots[0]);
1838 let p1 = P1::from_slot(slots[1]);
1839 let body = body.clone();
1840 Box::pin(async move { body(p0, p1).await })
1841 });
1842 install_async(
1843 module,
1844 name,
1845 description,
1846 params.into_iter().collect(),
1847 return_type,
1848 arg_kinds,
1849 invoke,
1850 );
1851}
1852
1853pub fn register_typed_async_fn_3_full<F, Fut, P0, P1, P2>(
1855 module: &mut crate::module_exports::ModuleExports,
1856 name: impl Into<String>,
1857 description: impl Into<String>,
1858 params: [crate::module_exports::ModuleParam; 3],
1859 return_type: crate::typed_module_exports::ConcreteType,
1860 body: F,
1861) where
1862 F: Fn(P0, P1, P2) -> Fut + Send + Sync + Clone + 'static,
1863 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
1864 P0: FromSlot + Send + Sync + 'static,
1865 P1: FromSlot + Send + Sync + 'static,
1866 P2: FromSlot + Send + Sync + 'static,
1867{
1868 let arg_kinds = vec![P0::NATIVE_KIND, P1::NATIVE_KIND, P2::NATIVE_KIND];
1869 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
1870 if slots.len() != 3 {
1871 let err = MarshalError::ArgCount {
1872 expected: 3,
1873 got: slots.len(),
1874 };
1875 return Box::pin(async move { Err(err.into()) });
1876 }
1877 let p0 = P0::from_slot(slots[0]);
1878 let p1 = P1::from_slot(slots[1]);
1879 let p2 = P2::from_slot(slots[2]);
1880 let body = body.clone();
1881 Box::pin(async move { body(p0, p1, p2).await })
1882 });
1883 install_async(
1884 module,
1885 name,
1886 description,
1887 params.into_iter().collect(),
1888 return_type,
1889 arg_kinds,
1890 invoke,
1891 );
1892}
1893
1894fn install_async(
1895 module: &mut crate::module_exports::ModuleExports,
1896 name: impl Into<String>,
1897 description: impl Into<String>,
1898 params: Vec<crate::module_exports::ModuleParam>,
1899 return_type: crate::typed_module_exports::ConcreteType,
1900 arg_kinds: Vec<NativeKind>,
1901 invoke: TypedAsyncInvoke,
1902) {
1903 use crate::module_exports::ModuleFunction;
1904 use crate::typed_module_exports::TypedModuleAsyncFunction;
1905
1906 let name = name.into();
1907 let arg_types: Vec<String> = params.iter().map(|p| p.type_name.clone()).collect();
1908 let return_type_str = return_type.shape_type_name();
1909 module.add_schema_only(
1910 name.clone(),
1911 ModuleFunction {
1912 description: description.into(),
1913 params,
1914 return_type: Some(return_type_str),
1915 },
1916 );
1917 module.typed_exports_mut().async_functions.insert(
1918 name,
1919 TypedModuleAsyncFunction {
1920 invoke,
1921 return_type,
1922 arg_types,
1923 arg_kinds,
1924 },
1925 );
1926}
1927
1928use crate::typed_module_exports::TypedModuleFunction;
1950use shape_value::KindedSlot;
1951
1952pub type VariadicTypedBody = dyn for<'ctx> Fn(
1960 &[KindedSlot],
1961 &ModuleContext<'ctx>,
1962 ) -> Result<TypedReturn, String>
1963 + Send
1964 + Sync;
1965
1966pub fn register_typed_function<F>(
1977 module: &mut crate::module_exports::ModuleExports,
1978 name: impl Into<String>,
1979 description: impl Into<String>,
1980 params: Vec<crate::module_exports::ModuleParam>,
1981 return_type: crate::typed_module_exports::ConcreteType,
1982 body: F,
1983) where
1984 F: for<'ctx> Fn(&[KindedSlot], &ModuleContext<'ctx>) -> Result<TypedReturn, String>
1985 + Send
1986 + Sync
1987 + 'static,
1988{
1989 use crate::module_exports::ModuleFunction;
1990
1991 let name = name.into();
1992 let arg_types: Vec<String> = params.iter().map(|p| p.type_name.clone()).collect();
1993 let arg_kinds: Vec<NativeKind> = params.iter().map(|_| NativeKind::Bool).collect();
2000 let return_type_str = return_type.shape_type_name();
2001
2002 let body = Arc::new(body);
2003 let invoke: TypedInvoke = Arc::new(move |slots, ctx| {
2004 let kinded: Vec<KindedSlot> = slots
2011 .iter()
2012 .map(|&bits| {
2013 KindedSlot::new(
2014 shape_value::ValueSlot::from_raw(bits),
2015 NativeKind::Bool,
2016 )
2017 })
2018 .collect();
2019 body(&kinded, ctx)
2020 });
2021
2022 module.add_schema_only(
2023 name.clone(),
2024 ModuleFunction {
2025 description: description.into(),
2026 params,
2027 return_type: Some(return_type_str),
2028 },
2029 );
2030 module.typed_exports_mut().functions.insert(
2031 name,
2032 TypedModuleFunction {
2033 invoke,
2034 return_type,
2035 arg_types,
2036 arg_kinds,
2037 },
2038 );
2039}
2040
2041pub type VariadicTypedAsyncBody<Fut> =
2047 dyn Fn(Vec<KindedSlot>) -> Fut + Send + Sync;
2048
2049pub fn register_typed_async_function<F, Fut>(
2052 module: &mut crate::module_exports::ModuleExports,
2053 name: impl Into<String>,
2054 description: impl Into<String>,
2055 params: Vec<crate::module_exports::ModuleParam>,
2056 return_type: crate::typed_module_exports::ConcreteType,
2057 body: F,
2058) where
2059 F: Fn(Vec<KindedSlot>) -> Fut + Send + Sync + Clone + 'static,
2060 Fut: std::future::Future<Output = Result<TypedReturn, String>> + Send + 'static,
2061{
2062 use crate::module_exports::ModuleFunction;
2063 use crate::typed_module_exports::TypedModuleAsyncFunction;
2064
2065 let name = name.into();
2066 let arg_types: Vec<String> = params.iter().map(|p| p.type_name.clone()).collect();
2067 let arg_kinds: Vec<NativeKind> = params.iter().map(|_| NativeKind::Bool).collect();
2068 let return_type_str = return_type.shape_type_name();
2069
2070 let invoke: TypedAsyncInvoke = Arc::new(move |slots: Vec<u64>| {
2071 let kinded: Vec<KindedSlot> = slots
2072 .into_iter()
2073 .map(|bits| {
2074 KindedSlot::new(
2075 shape_value::ValueSlot::from_raw(bits),
2076 NativeKind::Bool,
2077 )
2078 })
2079 .collect();
2080 let body = body.clone();
2081 Box::pin(async move { body(kinded).await })
2082 });
2083
2084 module.add_schema_only(
2085 name.clone(),
2086 ModuleFunction {
2087 description: description.into(),
2088 params,
2089 return_type: Some(return_type_str),
2090 },
2091 );
2092 module.typed_exports_mut().async_functions.insert(
2093 name,
2094 TypedModuleAsyncFunction {
2095 invoke,
2096 return_type,
2097 arg_types,
2098 arg_kinds,
2099 },
2100 );
2101}