1use crate::data::Data;
15use crate::data::NULL;
16use crate::gc::GcState;
17use crate::gc::Heap;
18use crate::rt::DataType;
19use crate::rt::EnumType;
20use crate::rt::HostFnSig;
21use crate::rt::Pools;
22use crate::rt::Struct;
23use crate::vm::MapPool;
24use crate::vm::ObjectPool;
25use crate::vm::RegisterFile;
26use crate::vm::StringPool;
27use crate::vm::map_insert;
28use std::collections::BTreeMap;
29use std::collections::HashMap;
30use std::fmt;
31use std::rc::Rc;
32
33#[derive(Debug, Clone, PartialEq)]
38pub enum Value {
39 Null,
40 Int(i64),
41 Float(f64),
42 Bool(bool),
43 String(String),
44 Array(Vec<Self>),
47 Map(BTreeMap<String, Self>),
50 Enum {
55 variant: String,
56 payload: Vec<Self>,
57 },
58}
59
60impl Value {
61 #[must_use]
62 pub const fn as_i64(&self) -> Option<i64> {
63 if let Self::Int(i) = self {
64 Some(*i)
65 } else {
66 None
67 }
68 }
69 #[must_use]
70 pub const fn as_f64(&self) -> Option<f64> {
71 if let Self::Float(f) = self {
72 Some(*f)
73 } else {
74 None
75 }
76 }
77 #[must_use]
78 pub const fn as_bool(&self) -> Option<bool> {
79 if let Self::Bool(b) = self {
80 Some(*b)
81 } else {
82 None
83 }
84 }
85 #[must_use]
86 pub const fn as_str(&self) -> Option<&str> {
87 if let Self::String(s) = self {
88 Some(s.as_str())
89 } else {
90 None
91 }
92 }
93 #[must_use]
94 pub const fn as_array(&self) -> Option<&Vec<Self>> {
95 if let Self::Array(a) = self {
96 Some(a)
97 } else {
98 None
99 }
100 }
101 #[must_use]
102 pub const fn as_map(&self) -> Option<&BTreeMap<String, Self>> {
103 if let Self::Map(m) = self {
104 Some(m)
105 } else {
106 None
107 }
108 }
109 #[must_use]
110 pub fn into_string(self) -> Option<String> {
111 if let Self::String(s) = self {
112 Some(s)
113 } else {
114 None
115 }
116 }
117 #[must_use]
118 pub fn into_array(self) -> Option<Vec<Self>> {
119 if let Self::Array(a) = self {
120 Some(a)
121 } else {
122 None
123 }
124 }
125 #[must_use]
126 pub fn into_map(self) -> Option<BTreeMap<String, Self>> {
127 if let Self::Map(m) = self {
128 Some(m)
129 } else {
130 None
131 }
132 }
133 #[must_use]
134 pub const fn is_null(&self) -> bool {
135 matches!(self, Self::Null)
136 }
137}
138
139impl From<i64> for Value {
140 fn from(v: i64) -> Self {
141 Self::Int(v)
142 }
143}
144impl From<i32> for Value {
145 fn from(v: i32) -> Self {
146 Self::Int(i64::from(v))
147 }
148}
149impl From<f64> for Value {
150 fn from(v: f64) -> Self {
151 Self::Float(v)
152 }
153}
154impl From<bool> for Value {
155 fn from(v: bool) -> Self {
156 Self::Bool(v)
157 }
158}
159impl From<String> for Value {
160 fn from(v: String) -> Self {
161 Self::String(v)
162 }
163}
164impl From<&str> for Value {
165 fn from(v: &str) -> Self {
166 Self::String(v.to_owned())
167 }
168}
169impl From<()> for Value {
170 fn from((): ()) -> Self {
171 Self::Null
172 }
173}
174impl<T: Into<Self>> From<Vec<T>> for Value {
175 fn from(v: Vec<T>) -> Self {
176 Self::Array(v.into_iter().map(Into::into).collect())
177 }
178}
179impl<T: Into<Self>> From<BTreeMap<String, T>> for Value {
180 fn from(m: BTreeMap<String, T>) -> Self {
181 Self::Map(m.into_iter().map(|(k, v)| (k, v.into())).collect())
182 }
183}
184impl<T: Into<Self>> From<HashMap<String, T>> for Value {
185 fn from(m: HashMap<String, T>) -> Self {
186 Self::Map(m.into_iter().map(|(k, v)| (k, v.into())).collect())
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
197pub enum HostType {
198 Int,
199 Float,
200 Bool,
201 String,
202 Unit,
203 Array(Box<Self>),
204 Map(Box<Self>),
205 Struct(Vec<(String, Self)>),
209}
210
211impl HostType {
212 #[must_use]
216 pub fn from_datatype(dt: &DataType, structs: &[Struct]) -> Option<Self> {
217 Self::from_datatype_in(dt, structs, &mut Vec::new())
218 }
219
220 fn from_datatype_in(dt: &DataType, structs: &[Struct], open: &mut Vec<u16>) -> Option<Self> {
223 match dt {
224 DataType::Int => Some(Self::Int),
225 DataType::Float => Some(Self::Float),
226 DataType::Bool => Some(Self::Bool),
227 DataType::String => Some(Self::String),
228 DataType::Null => Some(Self::Unit),
229 DataType::Array(Some(inner)) => Some(Self::Array(Box::new(Self::from_datatype_in(
230 inner, structs, open,
231 )?))),
232 DataType::Map(kv) => {
233 match &kv.0 {
235 Some(DataType::String) | None => {}
236 Some(_) => return None,
237 }
238 let value = kv.1.as_ref().map_or(Some(Self::Unit), |t| {
239 Self::from_datatype_in(t, structs, open)
240 })?;
241 Some(Self::Map(Box::new(value)))
242 }
243 DataType::Struct(id) => {
244 if open.contains(id) {
245 return None;
246 }
247 let declared = structs.get(*id as usize)?;
248 open.push(*id);
249 let fields = declared
250 .fields
251 .iter()
252 .map(|(name, t, _)| {
253 Some((name.to_string(), Self::from_datatype_in(t, structs, open)?))
254 })
255 .collect::<Option<Vec<_>>>();
256 open.pop();
257 fields.map(Self::Struct)
258 }
259 _ => None,
260 }
261 }
262
263 fn holds_struct(&self) -> bool {
266 match self {
267 Self::Struct(_) => true,
268 Self::Array(inner) | Self::Map(inner) => inner.holds_struct(),
269 Self::Int | Self::Float | Self::Bool | Self::String | Self::Unit => false,
270 }
271 }
272
273 #[must_use]
274 pub fn describe(&self) -> String {
275 match self {
276 Self::Int => "int".to_owned(),
277 Self::Float => "float".to_owned(),
278 Self::Bool => "bool".to_owned(),
279 Self::String => "string".to_owned(),
280 Self::Unit => "null".to_owned(),
281 Self::Array(inner) => format!("{}[]", inner.describe()),
282 Self::Map(value) => format!("{{string: {}}}", value.describe()),
283 Self::Struct(fields) => {
284 let fields: Vec<String> = fields
285 .iter()
286 .map(|(name, t)| format!("{name}: {}", t.describe()))
287 .collect();
288 format!("struct {{ {} }}", fields.join(", "))
289 }
290 }
291 }
292}
293
294#[must_use]
301pub fn is_host_callable_type(ty: &DataType) -> bool {
302 match ty {
303 DataType::Int
304 | DataType::Float
305 | DataType::Bool
306 | DataType::String
307 | DataType::Null
308 | DataType::Unknown => true,
309 DataType::Array(element) => element.as_deref().is_none_or(is_host_callable_type),
310 DataType::Map(kv) => {
311 matches!(&kv.0, None | Some(DataType::String))
312 && kv.1.as_ref().is_none_or(is_host_callable_type)
313 }
314 DataType::Union(members) => members.iter().all(is_host_callable_type),
315 DataType::Fn(_) | DataType::FnValue(_) | DataType::Struct(_) | DataType::Enum(_) => false,
316 }
317}
318
319#[must_use]
327pub fn holds_enum(value: &Value) -> bool {
328 match value {
329 Value::Enum { .. } => true,
330 Value::Array(items) => items.iter().any(holds_enum),
331 Value::Map(entries) => entries.values().any(holds_enum),
332 Value::Null | Value::Int(_) | Value::Float(_) | Value::Bool(_) | Value::String(_) => false,
333 }
334}
335
336#[must_use]
338pub fn describe_value(value: &Value) -> String {
339 match value {
340 Value::Null => String::from("null"),
341 Value::Int(_) => String::from("int"),
342 Value::Float(_) => String::from("float"),
343 Value::Bool(_) => String::from("bool"),
344 Value::String(_) => String::from("string"),
345 Value::Array(_) => String::from("array"),
346 Value::Map(_) => String::from("map"),
347 Value::Enum { variant, .. } => format!("enum variant {variant}"),
348 }
349}
350
351#[must_use]
359pub fn value_matches_type(value: &Value, ty: &DataType) -> bool {
360 if holds_enum(value) {
364 return false;
365 }
366 match ty {
367 DataType::Unknown => true,
368 DataType::Int => matches!(value, Value::Int(_)),
369 DataType::Float => matches!(value, Value::Float(_)),
370 DataType::Bool => matches!(value, Value::Bool(_)),
371 DataType::String => matches!(value, Value::String(_)),
372 DataType::Null => matches!(value, Value::Null),
373 DataType::Array(element) => match value {
374 Value::Array(items) => element
375 .as_deref()
376 .is_none_or(|el| items.iter().all(|item| value_matches_type(item, el))),
377 _ => false,
378 },
379 DataType::Map(kv) => match value {
380 Value::Map(entries) => {
381 kv.1.as_ref()
382 .is_none_or(|v| entries.values().all(|entry| value_matches_type(entry, v)))
383 }
384 _ => false,
385 },
386 DataType::Union(members) => members
387 .iter()
388 .any(|member| value_matches_type(value, member)),
389 DataType::Fn(_) | DataType::FnValue(_) | DataType::Struct(_) | DataType::Enum(_) => false,
390 }
391}
392
393pub type HostDispatch = Rc<dyn Fn(&[Value]) -> Result<Value, HostError>>;
395
396#[derive(Debug, Clone, PartialEq, Eq)]
406pub struct HostError {
407 message: String,
408}
409
410impl HostError {
411 pub fn new(message: impl fmt::Display) -> Self {
413 Self {
414 message: message.to_string(),
415 }
416 }
417
418 #[must_use]
420 pub fn message(&self) -> &str {
421 &self.message
422 }
423}
424
425impl From<String> for HostError {
426 fn from(message: String) -> Self {
427 Self { message }
428 }
429}
430
431impl From<&str> for HostError {
432 fn from(message: &str) -> Self {
433 Self {
434 message: message.to_owned(),
435 }
436 }
437}
438
439impl fmt::Display for HostError {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 f.write_str(&self.message)
442 }
443}
444
445impl std::error::Error for HostError {}
446
447struct RegisteredFn {
451 func: HostDispatch,
452 arg_types: Vec<HostType>,
453 ret_type: HostType,
454 variadic: bool,
459}
460
461#[derive(Default)]
470pub struct HostRegistry {
471 fns: HashMap<(String, String), RegisteredFn>,
472}
473
474impl HostRegistry {
475 #[must_use]
476 pub fn new() -> Self {
477 Self::default()
478 }
479
480 pub fn register_host_fn<Marker, F>(&mut self, namespace: &str, name: &str, f: F)
489 where
490 F: IntoHostFn<Marker>,
491 {
492 let (func, arg_types, ret_type) = f.into_host_fn_parts();
493 self.fns.insert(
494 (namespace.to_owned(), name.to_owned()),
495 RegisteredFn {
496 func,
497 arg_types,
498 ret_type,
499 variadic: false,
500 },
501 );
502 }
503
504 pub fn register_host_fn_typed<F>(
515 &mut self,
516 namespace: &str,
517 name: &str,
518 arg_types: Vec<HostType>,
519 ret_type: HostType,
520 f: F,
521 ) where
522 F: Fn(&[Value]) -> Result<Value, HostError> + 'static,
523 {
524 self.fns.insert(
525 (namespace.to_owned(), name.to_owned()),
526 RegisteredFn {
527 func: Rc::new(f),
528 arg_types,
529 ret_type,
530 variadic: false,
531 },
532 );
533 }
534
535 pub fn register_host_fn_variadic<F>(&mut self, namespace: &str, name: &str, f: F)
544 where
545 F: Fn(&[Value]) -> Result<Value, HostError> + 'static,
546 {
547 self.fns.insert(
548 (namespace.to_owned(), name.to_owned()),
549 RegisteredFn {
550 func: Rc::new(f),
551 arg_types: Vec::new(),
552 ret_type: HostType::Unit,
553 variadic: true,
554 },
555 );
556 }
557
558 pub fn bind(
567 &self,
568 sigs: &[HostFnSig],
569 structs: &[Struct],
570 ) -> Result<Vec<HostDispatch>, HostBindError> {
571 let missing: Vec<String> = sigs
572 .iter()
573 .filter(|sig| !self.fns.contains_key(&key_of(sig)))
574 .map(|sig| qualified_name(&sig.namespace, &sig.name))
575 .collect();
576 if !missing.is_empty() {
577 return Err(HostBindError::Unregistered(missing));
578 }
579
580 let mut dispatch = Vec::with_capacity(sigs.len());
581 for sig in sigs {
582 let registered = &self.fns[&key_of(sig)];
583 validate_host_fn(sig, registered, structs)?;
584 dispatch.push(Rc::clone(®istered.func));
585 }
586 Ok(dispatch)
587 }
588}
589
590fn key_of(sig: &HostFnSig) -> (String, String) {
592 (sig.namespace.to_string(), sig.name.to_string())
593}
594
595pub(crate) fn qualified_name(namespace: &str, name: &str) -> String {
597 if namespace.is_empty() {
598 name.to_owned()
599 } else {
600 format!("{namespace}::{name}")
601 }
602}
603
604fn validate_host_fn(
607 sig: &HostFnSig,
608 registered: &RegisteredFn,
609 structs: &[Struct],
610) -> Result<(), HostBindError> {
611 let function = qualified_name(&sig.namespace, &sig.name);
612 let err = HostBindError::SignatureMismatch;
613
614 if sig.variadic || registered.variadic {
618 if sig.variadic != registered.variadic {
619 let (decl, reg) = if sig.variadic {
620 ("variadic (`...`)", "a fixed signature")
621 } else {
622 ("a fixed signature", "variadic")
623 };
624 return Err(err(format!(
625 "host function `{function}` is declared with {decl} but the registered closure has {reg}",
626 )));
627 }
628 return Ok(());
629 }
630
631 if sig.arg_count() != registered.arg_types.len() {
632 return Err(err(format!(
633 "host function `{function}` is declared with {} argument(s) but the registered closure takes {}",
634 sig.arg_count(),
635 registered.arg_types.len(),
636 )));
637 }
638
639 for (idx, want) in registered.arg_types.iter().enumerate() {
640 let declared = HostType::from_datatype(sig.get_arg(idx), structs).ok_or_else(|| {
641 err(format!(
642 "host function `{function}` argument {} has a type that cannot cross the host boundary",
643 idx + 1,
644 ))
645 })?;
646 if declared != *want {
647 return Err(err(format!(
648 "host function `{function}` argument {} is declared `{}` but the registered closure expects `{}`",
649 idx + 1,
650 declared.describe(),
651 want.describe(),
652 )));
653 }
654 }
655
656 let declared_ret = HostType::from_datatype(sig.get_return_type(), structs)
659 .filter(|t| !t.holds_struct())
660 .ok_or_else(|| {
661 err(format!(
662 "host function `{function}` has a return type that cannot cross the host boundary",
663 ))
664 })?;
665 if declared_ret != registered.ret_type {
666 return Err(err(format!(
667 "host function `{function}` is declared to return `{}` but the registered closure returns `{}`",
668 declared_ret.describe(),
669 registered.ret_type.describe(),
670 )));
671 }
672
673 Ok(())
674}
675
676#[derive(Debug, Clone, PartialEq, Eq)]
678pub enum HostBindError {
679 Unregistered(Vec<String>),
682 SignatureMismatch(String),
685}
686
687impl HostBindError {
688 #[must_use]
690 pub const fn code(&self) -> &'static str {
691 match self {
692 Self::Unregistered(_) => "unregistered_host_fn",
693 Self::SignatureMismatch(_) => "host_fn_signature_mismatch",
694 }
695 }
696}
697
698impl fmt::Display for HostBindError {
699 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
700 match self {
701 Self::Unregistered(names) => {
702 if let [name] = names.as_slice() {
703 write!(
704 f,
705 "no host function registered for `{name}` (declared in a `host` block)"
706 )
707 } else {
708 write!(
709 f,
710 "no host functions registered for `{}` (declared in `host` blocks)",
711 names.join("`, `")
712 )
713 }
714 }
715 Self::SignatureMismatch(message) => f.write_str(message),
716 }
717 }
718}
719
720impl std::error::Error for HostBindError {}
721
722pub trait FromHostValue: Sized {
724 fn from_host_value(v: &Value) -> Self;
725 fn host_type() -> HostType;
726}
727
728impl FromHostValue for i64 {
729 fn from_host_value(v: &Value) -> Self {
730 v.as_i64().unwrap_or(0)
731 }
732 fn host_type() -> HostType {
733 HostType::Int
734 }
735}
736impl FromHostValue for i32 {
737 fn from_host_value(v: &Value) -> Self {
738 v.as_i64().unwrap_or(0) as Self
739 }
740 fn host_type() -> HostType {
741 HostType::Int
742 }
743}
744impl FromHostValue for f64 {
745 fn from_host_value(v: &Value) -> Self {
746 v.as_f64().unwrap_or(0.0)
747 }
748 fn host_type() -> HostType {
749 HostType::Float
750 }
751}
752impl FromHostValue for bool {
753 fn from_host_value(v: &Value) -> Self {
754 v.as_bool().unwrap_or(false)
755 }
756 fn host_type() -> HostType {
757 HostType::Bool
758 }
759}
760impl FromHostValue for String {
761 fn from_host_value(v: &Value) -> Self {
762 v.as_str().unwrap_or_default().to_owned()
763 }
764 fn host_type() -> HostType {
765 HostType::String
766 }
767}
768impl<T: FromHostValue> FromHostValue for Vec<T> {
769 fn from_host_value(v: &Value) -> Self {
770 v.as_array()
771 .map(|items| items.iter().map(T::from_host_value).collect())
772 .unwrap_or_default()
773 }
774 fn host_type() -> HostType {
775 HostType::Array(Box::new(T::host_type()))
776 }
777}
778impl<T: FromHostValue> FromHostValue for BTreeMap<String, T> {
779 fn from_host_value(v: &Value) -> Self {
780 v.as_map()
781 .map(|m| {
782 m.iter()
783 .map(|(k, val)| (k.clone(), T::from_host_value(val)))
784 .collect()
785 })
786 .unwrap_or_default()
787 }
788 fn host_type() -> HostType {
789 HostType::Map(Box::new(T::host_type()))
790 }
791}
792impl<T: FromHostValue, S: std::hash::BuildHasher + Default> FromHostValue
793 for HashMap<String, T, S>
794{
795 fn from_host_value(v: &Value) -> Self {
796 v.as_map()
797 .map(|m| {
798 m.iter()
799 .map(|(k, val)| (k.clone(), T::from_host_value(val)))
800 .collect()
801 })
802 .unwrap_or_default()
803 }
804 fn host_type() -> HostType {
805 HostType::Map(Box::new(T::host_type()))
806 }
807}
808
809pub trait IntoHostValue {
811 fn into_host_value(self) -> Value;
812 fn host_type() -> HostType;
813}
814
815impl IntoHostValue for i64 {
816 fn into_host_value(self) -> Value {
817 Value::Int(self)
818 }
819 fn host_type() -> HostType {
820 HostType::Int
821 }
822}
823impl IntoHostValue for i32 {
824 fn into_host_value(self) -> Value {
825 Value::Int(i64::from(self))
826 }
827 fn host_type() -> HostType {
828 HostType::Int
829 }
830}
831impl IntoHostValue for f64 {
832 fn into_host_value(self) -> Value {
833 Value::Float(self)
834 }
835 fn host_type() -> HostType {
836 HostType::Float
837 }
838}
839impl IntoHostValue for bool {
840 fn into_host_value(self) -> Value {
841 Value::Bool(self)
842 }
843 fn host_type() -> HostType {
844 HostType::Bool
845 }
846}
847impl IntoHostValue for String {
848 fn into_host_value(self) -> Value {
849 Value::String(self)
850 }
851 fn host_type() -> HostType {
852 HostType::String
853 }
854}
855impl IntoHostValue for &str {
856 fn into_host_value(self) -> Value {
857 Value::String(self.to_owned())
858 }
859 fn host_type() -> HostType {
860 HostType::String
861 }
862}
863impl IntoHostValue for () {
864 fn into_host_value(self) -> Value {
865 Value::Null
866 }
867 fn host_type() -> HostType {
868 HostType::Unit
869 }
870}
871impl<T: IntoHostValue> IntoHostValue for Vec<T> {
872 fn into_host_value(self) -> Value {
873 Value::Array(
874 self.into_iter()
875 .map(IntoHostValue::into_host_value)
876 .collect(),
877 )
878 }
879 fn host_type() -> HostType {
880 HostType::Array(Box::new(T::host_type()))
881 }
882}
883impl<T: IntoHostValue> IntoHostValue for BTreeMap<String, T> {
884 fn into_host_value(self) -> Value {
885 Value::Map(
886 self.into_iter()
887 .map(|(k, v)| (k, v.into_host_value()))
888 .collect(),
889 )
890 }
891 fn host_type() -> HostType {
892 HostType::Map(Box::new(T::host_type()))
893 }
894}
895impl<T: IntoHostValue, S: std::hash::BuildHasher> IntoHostValue for HashMap<String, T, S> {
896 fn into_host_value(self) -> Value {
897 Value::Map(
898 self.into_iter()
899 .map(|(k, v)| (k, v.into_host_value()))
900 .collect(),
901 )
902 }
903 fn host_type() -> HostType {
904 HostType::Map(Box::new(T::host_type()))
905 }
906}
907
908pub trait IntoHostResult {
916 fn into_host_result(self) -> Result<Value, HostError>;
917 fn host_type() -> HostType;
918}
919
920impl<T: IntoHostValue> IntoHostResult for T {
921 fn into_host_result(self) -> Result<Value, HostError> {
922 Ok(self.into_host_value())
923 }
924 fn host_type() -> HostType {
925 <T as IntoHostValue>::host_type()
926 }
927}
928
929impl<T: IntoHostValue> IntoHostResult for Result<T, HostError> {
930 fn into_host_result(self) -> Result<Value, HostError> {
931 self.map(IntoHostValue::into_host_value)
932 }
933 fn host_type() -> HostType {
934 <T as IntoHostValue>::host_type()
935 }
936}
937
938pub trait IntoHostFn<Marker> {
944 fn into_host_fn_parts(self) -> (HostDispatch, Vec<HostType>, HostType);
948}
949
950pub struct Arity0;
952pub struct ArityStr1;
954
955impl<F, R> IntoHostFn<Arity0> for F
956where
957 F: Fn() -> R + 'static,
958 R: IntoHostResult,
959{
960 fn into_host_fn_parts(self) -> (HostDispatch, Vec<HostType>, HostType) {
961 (
962 Rc::new(move |_args: &[Value]| self().into_host_result()),
963 Vec::new(),
964 <R as IntoHostResult>::host_type(),
965 )
966 }
967}
968
969impl<F, R> IntoHostFn<ArityStr1> for F
970where
971 F: Fn(&str) -> R + 'static,
972 R: IntoHostResult,
973{
974 fn into_host_fn_parts(self) -> (HostDispatch, Vec<HostType>, HostType) {
975 (
976 Rc::new(move |args: &[Value]| {
977 let s = args.first().and_then(Value::as_str).unwrap_or_default();
978 self(s).into_host_result()
979 }),
980 vec![HostType::String],
981 <R as IntoHostResult>::host_type(),
982 )
983 }
984}
985
986macro_rules! impl_into_host_fn {
990 ($($ty:ident $idx:tt),+) => {
991 impl<F, R, $($ty,)+> IntoHostFn<($($ty,)+)> for F
992 where
993 F: Fn($($ty,)+) -> R + 'static,
994 R: IntoHostResult,
995 $( $ty: FromHostValue + 'static, )+
996 {
997 fn into_host_fn_parts(self) -> (HostDispatch, Vec<HostType>, HostType) {
998 (
999 Rc::new(move |args: &[Value]| {
1000 self( $( <$ty as FromHostValue>::from_host_value(&args[$idx]), )+ )
1001 .into_host_result()
1002 }),
1003 vec![ $( <$ty as FromHostValue>::host_type(), )+ ],
1004 <R as IntoHostResult>::host_type(),
1005 )
1006 }
1007 }
1008 };
1009}
1010
1011impl_into_host_fn!(A0 0);
1012impl_into_host_fn!(A0 0, A1 1);
1013impl_into_host_fn!(A0 0, A1 1, A2 2);
1014impl_into_host_fn!(A0 0, A1 1, A2 2, A3 3);
1015impl_into_host_fn!(A0 0, A1 1, A2 2, A3 3, A4 4);
1016
1017pub fn marshal_value(
1032 v: &Value,
1033 registers: &RegisterFile,
1034 recursion_stack: &mut RegisterFile,
1035 objs: &mut ObjectPool,
1036 maps: &mut MapPool,
1037 strings: &mut StringPool,
1038 gc: &mut GcState,
1039) -> Data {
1040 let mut heap = Heap {
1041 objs,
1042 maps,
1043 strings,
1044 gc,
1045 registers,
1046 recursion_stack,
1047 };
1048 let d = shell(&mut heap, v);
1049 if matches!(v, Value::Array(_) | Value::Map(_)) {
1050 heap.recursion_stack.0.push(d);
1051 fill(&mut heap, v, d);
1052 heap.recursion_stack.0.pop();
1053 }
1054 d
1055}
1056
1057pub fn marshal_args(
1060 args: &[Value],
1061 arg_registers: &[u16],
1062 registers: &mut Vec<Data>,
1063 pools: &mut Pools,
1064) {
1065 let mut file = RegisterFile(std::mem::take(registers));
1066 let mut stack = RegisterFile(Vec::new());
1067 for (arg, ®ister) in args.iter().zip(arg_registers) {
1068 let d = marshal_value(
1069 arg,
1070 &file,
1071 &mut stack,
1072 &mut pools.objs,
1073 &mut pools.maps,
1074 &mut pools.strings,
1075 &mut pools.gc,
1076 );
1077 file.0[register as usize] = d;
1078 }
1079 *registers = file.0;
1080}
1081
1082fn shell(heap: &mut Heap<'_>, v: &Value) -> Data {
1085 match v {
1086 Value::Null => NULL,
1087 Value::Int(i) => Data::int(*i),
1088 Value::Float(f) => Data::float(*f),
1089 Value::Bool(b) => Data::bool(*b),
1090 Value::String(s) => heap.string(s),
1091 Value::Array(_) => heap.array(),
1092 Value::Map(_) => heap.map(),
1093 Value::Enum { .. } => NULL,
1098 }
1099}
1100
1101fn fill(heap: &mut Heap<'_>, v: &Value, d: Data) {
1104 match v {
1105 Value::Array(items) => {
1106 let id = d.as_array();
1107 heap.objs[id].reserve(items.len());
1108 for item in items {
1109 let child = shell(heap, item);
1110 heap.objs[id].push(child);
1111 fill(heap, item, child);
1112 }
1113 }
1114 Value::Map(entries) => {
1115 let id = d.as_map();
1116 for (k, val) in entries {
1117 let key = heap.string(k);
1118 map_insert(&mut heap.maps[id], key, NULL, heap.strings);
1119 let child = shell(heap, val);
1120 map_insert(&mut heap.maps[id], key, child, heap.strings);
1121 fill(heap, val, child);
1122 }
1123 }
1124 _ => {}
1125 }
1126}
1127
1128pub fn unmarshal_value(
1134 d: Data,
1135 objs: &ObjectPool,
1136 maps: &MapPool,
1137 strings: &StringPool,
1138 structs: &[Struct],
1139 enums: &[EnumType],
1140) -> Value {
1141 if d.is_int() {
1142 Value::Int(d.as_int())
1143 } else if d.is_bool() {
1144 Value::Bool(d.as_bool())
1145 } else if d.is_string() {
1146 Value::String(d.as_str(strings).to_owned())
1147 } else if d.is_null() {
1148 Value::Null
1149 } else if d.is_array() {
1150 let items = objs[d.as_array()]
1151 .iter()
1152 .map(|e| unmarshal_value(*e, objs, maps, strings, structs, enums))
1153 .collect();
1154 Value::Array(items)
1155 } else if d.is_struct() {
1156 let fields = &structs[d.struct_type_id() as usize].fields;
1157 let values = &objs[d.as_struct()];
1158 let record = fields
1159 .iter()
1160 .zip(values.iter())
1161 .map(|((name, _, _), val)| {
1162 (
1163 name.to_string(),
1164 unmarshal_value(*val, objs, maps, strings, structs, enums),
1165 )
1166 })
1167 .collect();
1168 Value::Map(record)
1169 } else if d.is_enum() {
1170 let variants = &enums[d.enum_type_id() as usize].variants;
1173 let entry = &objs[d.as_enum()];
1174 let tag = entry[0].as_int() as usize;
1175 Value::Enum {
1176 variant: variants[tag].name.to_string(),
1177 payload: entry[1..]
1178 .iter()
1179 .map(|val| unmarshal_value(*val, objs, maps, strings, structs, enums))
1180 .collect(),
1181 }
1182 } else if d.is_map() {
1183 let record = maps[d.as_map()]
1184 .iter()
1185 .filter(|(k, _)| k.is_string())
1186 .map(|(k, val)| {
1187 (
1188 k.as_str(strings).to_owned(),
1189 unmarshal_value(*val, objs, maps, strings, structs, enums),
1190 )
1191 })
1192 .collect();
1193 Value::Map(record)
1194 } else if d.is_float() {
1195 Value::Float(d.as_float())
1196 } else {
1197 Value::Null
1198 }
1199}