golem_wasm/
value_and_type.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://license.golem.cloud/LICENSE
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::analysis::analysed_type::{
16    case, list, option, result, result_err, result_ok, str, tuple, u32, unit_case, variant,
17};
18use crate::analysis::{
19    analysed_type, AnalysedResourceId, AnalysedResourceMode, AnalysedType, NameTypePair, TypeEnum,
20    TypeFlags,
21};
22use crate::golem_rpc_0_2_x::types::NamedWitTypeNode;
23use crate::{NodeIndex, ResourceMode, RpcError, Value, WitNode, WitType, WitTypeNode, WitValue};
24use std::collections::{BTreeMap, BTreeSet, HashMap};
25use std::ops::Bound;
26use std::time::{Duration, Instant};
27use uuid::Uuid;
28
29#[derive(Clone, Debug, PartialEq)]
30#[cfg_attr(feature = "host", derive(::bincode::Encode, ::bincode::Decode))]
31pub struct ValueAndType {
32    pub value: Value,
33    pub typ: AnalysedType,
34}
35
36#[cfg(feature = "host")]
37impl std::fmt::Display for ValueAndType {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        write!(
40            f,
41            "{}",
42            crate::text::print_value_and_type(self).unwrap_or("<unprintable>".to_string())
43        )
44    }
45}
46
47impl ValueAndType {
48    pub fn new(value: Value, typ: AnalysedType) -> Self {
49        Self { value, typ }
50    }
51
52    pub fn into_list_items(self) -> Option<Vec<ValueAndType>> {
53        match (self.value, self.typ) {
54            (Value::List(items), AnalysedType::List(item_type)) => Some(
55                items
56                    .into_iter()
57                    .map(|item| ValueAndType::new(item, (*item_type.inner).clone()))
58                    .collect(),
59            ),
60            _ => None,
61        }
62    }
63}
64
65impl From<ValueAndType> for Value {
66    fn from(value_and_type: ValueAndType) -> Self {
67        value_and_type.value
68    }
69}
70
71impl From<ValueAndType> for AnalysedType {
72    fn from(value_and_type: ValueAndType) -> Self {
73        value_and_type.typ
74    }
75}
76
77#[cfg(feature = "host")]
78impl From<ValueAndType> for WitValue {
79    fn from(value_and_type: ValueAndType) -> Self {
80        value_and_type.value.into()
81    }
82}
83
84#[cfg(feature = "host")]
85impl From<ValueAndType> for WitType {
86    fn from(value_and_type: ValueAndType) -> Self {
87        value_and_type.typ.into()
88    }
89}
90
91/// Specific trait to convert a type into a pair of `Value` and `AnalysedType`.
92pub trait IntoValue {
93    fn into_value(self) -> Value;
94    fn get_type() -> AnalysedType;
95}
96
97pub trait IntoValueAndType {
98    fn into_value_and_type(self) -> ValueAndType;
99}
100
101impl<T: IntoValue + Sized> IntoValueAndType for T {
102    fn into_value_and_type(self) -> ValueAndType {
103        ValueAndType::new(self.into_value(), Self::get_type())
104    }
105}
106
107impl IntoValue for u8 {
108    fn into_value(self) -> Value {
109        Value::U8(self)
110    }
111
112    fn get_type() -> AnalysedType {
113        analysed_type::u8()
114    }
115}
116
117impl IntoValue for u16 {
118    fn into_value(self) -> Value {
119        Value::U16(self)
120    }
121
122    fn get_type() -> AnalysedType {
123        analysed_type::u16()
124    }
125}
126
127impl IntoValue for u32 {
128    fn into_value(self) -> Value {
129        Value::U32(self)
130    }
131
132    fn get_type() -> AnalysedType {
133        u32()
134    }
135}
136
137impl IntoValue for u64 {
138    fn into_value(self) -> Value {
139        Value::U64(self)
140    }
141
142    fn get_type() -> AnalysedType {
143        analysed_type::u64()
144    }
145}
146
147impl IntoValue for i8 {
148    fn into_value(self) -> Value {
149        Value::S8(self)
150    }
151
152    fn get_type() -> AnalysedType {
153        analysed_type::s8()
154    }
155}
156
157impl IntoValue for i16 {
158    fn into_value(self) -> Value {
159        Value::S16(self)
160    }
161
162    fn get_type() -> AnalysedType {
163        analysed_type::s16()
164    }
165}
166
167impl IntoValue for i32 {
168    fn into_value(self) -> Value {
169        Value::S32(self)
170    }
171
172    fn get_type() -> AnalysedType {
173        analysed_type::s32()
174    }
175}
176
177impl IntoValue for i64 {
178    fn into_value(self) -> Value {
179        Value::S64(self)
180    }
181
182    fn get_type() -> AnalysedType {
183        analysed_type::s64()
184    }
185}
186
187impl IntoValue for f32 {
188    fn into_value(self) -> Value {
189        Value::F32(self)
190    }
191
192    fn get_type() -> AnalysedType {
193        analysed_type::f32()
194    }
195}
196
197impl IntoValue for f64 {
198    fn into_value(self) -> Value {
199        Value::F64(self)
200    }
201
202    fn get_type() -> AnalysedType {
203        analysed_type::f64()
204    }
205}
206
207impl IntoValue for bool {
208    fn into_value(self) -> Value {
209        Value::Bool(self)
210    }
211
212    fn get_type() -> AnalysedType {
213        analysed_type::bool()
214    }
215}
216
217impl IntoValue for char {
218    fn into_value(self) -> Value {
219        Value::Char(self)
220    }
221
222    fn get_type() -> AnalysedType {
223        analysed_type::chr()
224    }
225}
226
227impl IntoValue for String {
228    fn into_value(self) -> Value {
229        Value::String(self)
230    }
231
232    fn get_type() -> AnalysedType {
233        str()
234    }
235}
236
237impl IntoValue for &str {
238    fn into_value(self) -> Value {
239        Value::String(self.to_string())
240    }
241
242    fn get_type() -> AnalysedType {
243        str()
244    }
245}
246
247impl<S: IntoValue, E: IntoValue> IntoValue for Result<S, E> {
248    fn into_value(self) -> Value {
249        match self {
250            Ok(s) => Value::Result(Ok(Some(Box::new(s.into_value())))),
251            Err(e) => Value::Result(Err(Some(Box::new(e.into_value())))),
252        }
253    }
254
255    fn get_type() -> AnalysedType {
256        result(S::get_type(), E::get_type())
257    }
258}
259
260impl<E: IntoValue> IntoValue for Result<(), E> {
261    fn into_value(self) -> Value {
262        match self {
263            Ok(_) => Value::Result(Ok(None)),
264            Err(e) => Value::Result(Err(Some(Box::new(e.into_value())))),
265        }
266    }
267
268    fn get_type() -> AnalysedType {
269        result_err(E::get_type())
270    }
271}
272
273impl<S: IntoValue> IntoValue for Result<S, ()> {
274    fn into_value(self) -> Value {
275        match self {
276            Ok(s) => Value::Result(Ok(Some(Box::new(s.into_value())))),
277            Err(_) => Value::Result(Err(None)),
278        }
279    }
280
281    fn get_type() -> AnalysedType {
282        result_ok(S::get_type())
283    }
284}
285
286impl<T: IntoValue> IntoValue for Box<T> {
287    fn into_value(self) -> Value {
288        (*self).into_value()
289    }
290
291    fn get_type() -> AnalysedType {
292        T::get_type()
293    }
294}
295
296impl<T: IntoValue> IntoValue for Option<T> {
297    fn into_value(self) -> Value {
298        match self {
299            Some(t) => Value::Option(Some(Box::new(t.into_value()))),
300            None => Value::Option(None),
301        }
302    }
303
304    fn get_type() -> AnalysedType {
305        option(T::get_type())
306    }
307}
308
309impl<T: IntoValue> IntoValue for Bound<T> {
310    fn into_value(self) -> Value {
311        match self {
312            Bound::Included(t) => Value::Variant {
313                case_idx: 0,
314                case_value: Some(Box::new(t.into_value())),
315            },
316            Bound::Excluded(t) => Value::Variant {
317                case_idx: 1,
318                case_value: Some(Box::new(t.into_value())),
319            },
320            Bound::Unbounded => Value::Variant {
321                case_idx: 2,
322                case_value: None,
323            },
324        }
325    }
326
327    fn get_type() -> AnalysedType {
328        variant(vec![
329            case("included", T::get_type()),
330            case("excluded", T::get_type()),
331            unit_case("unbounded"),
332        ])
333    }
334}
335
336impl<T: IntoValue> IntoValue for Vec<T> {
337    fn into_value(self) -> Value {
338        Value::List(self.into_iter().map(IntoValue::into_value).collect())
339    }
340
341    fn get_type() -> AnalysedType {
342        list(T::get_type())
343    }
344}
345
346impl<A: IntoValue, B: IntoValue> IntoValue for (A, B) {
347    fn into_value(self) -> Value {
348        Value::Tuple(vec![self.0.into_value(), self.1.into_value()])
349    }
350
351    fn get_type() -> AnalysedType {
352        tuple(vec![A::get_type(), B::get_type()])
353    }
354}
355
356impl<A: IntoValue, B: IntoValue, C: IntoValue> IntoValue for (A, B, C) {
357    fn into_value(self) -> Value {
358        Value::Tuple(vec![
359            self.0.into_value(),
360            self.1.into_value(),
361            self.2.into_value(),
362        ])
363    }
364
365    fn get_type() -> AnalysedType {
366        tuple(vec![A::get_type(), B::get_type(), C::get_type()])
367    }
368}
369
370impl<K: IntoValue, V: IntoValue> IntoValue for HashMap<K, V> {
371    fn into_value(self) -> Value {
372        Value::List(
373            self.into_iter()
374                .map(|(k, v)| Value::Tuple(vec![k.into_value(), v.into_value()]))
375                .collect(),
376        )
377    }
378
379    fn get_type() -> AnalysedType {
380        list(tuple(vec![K::get_type(), V::get_type()]))
381    }
382}
383
384impl<K: IntoValue, V: IntoValue> IntoValue for BTreeMap<K, V> {
385    fn into_value(self) -> Value {
386        Value::List(
387            self.into_iter()
388                .map(|(k, v)| Value::Tuple(vec![k.into_value(), v.into_value()]))
389                .collect(),
390        )
391    }
392
393    fn get_type() -> AnalysedType {
394        list(tuple(vec![K::get_type(), V::get_type()]))
395    }
396}
397
398impl<T: IntoValue> IntoValue for BTreeSet<T> {
399    fn into_value(self) -> Value {
400        Value::List(self.into_iter().map(IntoValue::into_value).collect())
401    }
402
403    fn get_type() -> AnalysedType {
404        list(T::get_type())
405    }
406}
407
408impl IntoValue for Uuid {
409    fn into_value(self) -> Value {
410        Value::String(self.to_string())
411    }
412
413    fn get_type() -> AnalysedType {
414        analysed_type::str()
415    }
416}
417
418/// Helper for dynamically creating record ValueAndType values with String keys
419pub struct Record<K: AsRef<str>>(pub Vec<(K, ValueAndType)>);
420
421impl<K: AsRef<str>> IntoValueAndType for Record<K> {
422    fn into_value_and_type(self) -> ValueAndType {
423        let mut field_types = Vec::<NameTypePair>::with_capacity(self.0.len());
424        let mut field_values = Vec::<Value>::with_capacity(self.0.len());
425
426        for (field_name, value_and_type) in self.0 {
427            field_types.push(NameTypePair {
428                name: field_name.as_ref().to_string(),
429                typ: value_and_type.typ,
430            });
431            field_values.push(value_and_type.value);
432        }
433
434        ValueAndType {
435            value: Value::Record(field_values),
436            typ: analysed_type::record(field_types),
437        }
438    }
439}
440
441#[cfg(feature = "host")]
442impl IntoValue for crate::WitValue {
443    fn into_value(self) -> Value {
444        // NOTE: this is different than From<WitValue> for Value. That conversion creates
445        // the Value the WitValue describes, while this conversion creates a Value version of
446        // the WitValue representation itself.
447        Value::Record(vec![self.nodes.into_value()])
448    }
449
450    fn get_type() -> AnalysedType {
451        analysed_type::record(vec![analysed_type::field(
452            "nodes",
453            list(crate::WitNode::get_type()),
454        )])
455    }
456}
457
458#[cfg(feature = "host")]
459impl IntoValue for WitNode {
460    fn into_value(self) -> Value {
461        use crate::WitNode;
462
463        match self {
464            WitNode::RecordValue(indices) => Value::Variant {
465                case_idx: 0,
466                case_value: Some(Box::new(indices.into_value())),
467            },
468            WitNode::VariantValue((idx, value)) => Value::Variant {
469                case_idx: 1,
470                case_value: Some(Box::new(Value::Tuple(vec![
471                    idx.into_value(),
472                    value
473                        .map(|idx| Value::Option(Some(Box::new(idx.into_value()))))
474                        .unwrap_or(Value::Option(None)),
475                ]))),
476            },
477            WitNode::EnumValue(idx) => Value::Variant {
478                case_idx: 2,
479                case_value: Some(Box::new(idx.into_value())),
480            },
481            WitNode::FlagsValue(flags) => Value::Variant {
482                case_idx: 3,
483                case_value: Some(Box::new(flags.into_value())),
484            },
485            WitNode::TupleValue(indices) => Value::Variant {
486                case_idx: 4,
487                case_value: Some(Box::new(indices.into_value())),
488            },
489            WitNode::ListValue(indices) => Value::Variant {
490                case_idx: 5,
491                case_value: Some(Box::new(indices.into_value())),
492            },
493            WitNode::OptionValue(index) => Value::Variant {
494                case_idx: 6,
495                case_value: Some(Box::new(index.into_value())),
496            },
497            WitNode::ResultValue(result) => Value::Variant {
498                case_idx: 7,
499                case_value: Some(Box::new(result.into_value())),
500            },
501            WitNode::PrimU8(value) => Value::Variant {
502                case_idx: 8,
503                case_value: Some(Box::new(value.into_value())),
504            },
505            WitNode::PrimU16(value) => Value::Variant {
506                case_idx: 9,
507                case_value: Some(Box::new(value.into_value())),
508            },
509            WitNode::PrimU32(value) => Value::Variant {
510                case_idx: 10,
511                case_value: Some(Box::new(value.into_value())),
512            },
513            WitNode::PrimU64(value) => Value::Variant {
514                case_idx: 11,
515                case_value: Some(Box::new(value.into_value())),
516            },
517            WitNode::PrimS8(value) => Value::Variant {
518                case_idx: 12,
519                case_value: Some(Box::new(value.into_value())),
520            },
521            WitNode::PrimS16(value) => Value::Variant {
522                case_idx: 13,
523                case_value: Some(Box::new(value.into_value())),
524            },
525            WitNode::PrimS32(value) => Value::Variant {
526                case_idx: 14,
527                case_value: Some(Box::new(value.into_value())),
528            },
529            WitNode::PrimS64(value) => Value::Variant {
530                case_idx: 15,
531                case_value: Some(Box::new(value.into_value())),
532            },
533            WitNode::PrimFloat32(value) => Value::Variant {
534                case_idx: 16,
535                case_value: Some(Box::new(value.into_value())),
536            },
537            WitNode::PrimFloat64(value) => Value::Variant {
538                case_idx: 17,
539                case_value: Some(Box::new(value.into_value())),
540            },
541            WitNode::PrimChar(value) => Value::Variant {
542                case_idx: 18,
543                case_value: Some(Box::new(value.into_value())),
544            },
545            WitNode::PrimBool(value) => Value::Variant {
546                case_idx: 19,
547                case_value: Some(Box::new(value.into_value())),
548            },
549            WitNode::PrimString(value) => Value::Variant {
550                case_idx: 20,
551                case_value: Some(Box::new(value.into_value())),
552            },
553            WitNode::Handle((uri, resource_id)) => Value::Variant {
554                case_idx: 21,
555                case_value: Some(Box::new(Value::Tuple(vec![
556                    uri.into_value(),
557                    resource_id.into_value(),
558                ]))),
559            },
560        }
561    }
562
563    fn get_type() -> AnalysedType {
564        use crate::NodeIndex;
565        use analysed_type::{case, variant};
566
567        variant(vec![
568            case("record-value", list(NodeIndex::get_type())),
569            case(
570                "variant-value",
571                tuple(vec![analysed_type::u32(), option(NodeIndex::get_type())]),
572            ),
573            case("enum-value", analysed_type::u32()),
574            case("flags-value", list(analysed_type::bool())),
575            case("tuple-value", list(NodeIndex::get_type())),
576            case("list-value", list(NodeIndex::get_type())),
577            case("option-value", option(NodeIndex::get_type())),
578            case(
579                "result-value",
580                result(option(NodeIndex::get_type()), option(NodeIndex::get_type())),
581            ),
582            case("prim-u8", analysed_type::u8()),
583            case("prim-u16", analysed_type::u16()),
584            case("prim-u32", analysed_type::u32()),
585            case("prim-u64", analysed_type::u64()),
586            case("prim-s8", analysed_type::s8()),
587            case("prim-s16", analysed_type::s16()),
588            case("prim-s32", analysed_type::s32()),
589            case("prim-s64", analysed_type::s64()),
590            case("prim-float32", analysed_type::f32()),
591            case("prim-float64", analysed_type::f64()),
592            case("prim-char", analysed_type::chr()),
593            case("prim-bool", analysed_type::bool()),
594            case("prim-string", analysed_type::str()),
595            case(
596                "handle",
597                tuple(vec![crate::Uri::get_type(), analysed_type::u64()]),
598            ),
599        ])
600    }
601}
602
603#[cfg(feature = "host")]
604impl IntoValue for crate::Uri {
605    fn into_value(self) -> Value {
606        Value::Record(vec![Value::String(self.value)])
607    }
608
609    fn get_type() -> AnalysedType {
610        analysed_type::record(vec![analysed_type::field("value", analysed_type::str())])
611    }
612}
613
614#[cfg(feature = "host")]
615impl IntoValue for WitType {
616    fn into_value(self) -> Value {
617        Value::Record(vec![self.nodes.into_value()])
618    }
619
620    fn get_type() -> AnalysedType {
621        analysed_type::record(vec![analysed_type::field(
622            "nodes",
623            list(NamedWitTypeNode::get_type()),
624        )])
625    }
626}
627
628#[cfg(feature = "host")]
629impl IntoValue for NamedWitTypeNode {
630    fn into_value(self) -> Value {
631        Value::Record(vec![
632            self.name.into_value(),
633            self.owner.into_value(),
634            self.type_.into_value(),
635        ])
636    }
637
638    fn get_type() -> AnalysedType {
639        analysed_type::record(vec![
640            analysed_type::field("name", option(analysed_type::str())),
641            analysed_type::field("owner", option(analysed_type::str())),
642            analysed_type::field("type", WitTypeNode::get_type()),
643        ])
644    }
645}
646
647#[cfg(feature = "host")]
648impl IntoValue for WitTypeNode {
649    fn into_value(self) -> Value {
650        match self {
651            WitTypeNode::RecordType(field_types) => Value::Variant {
652                case_idx: 0,
653                case_value: Some(Box::new(field_types.into_value())),
654            },
655            WitTypeNode::VariantType(case_types) => Value::Variant {
656                case_idx: 1,
657                case_value: Some(Box::new(case_types.into_value())),
658            },
659            WitTypeNode::EnumType(names) => Value::Variant {
660                case_idx: 2,
661                case_value: Some(Box::new(names.into_value())),
662            },
663            WitTypeNode::FlagsType(names) => Value::Variant {
664                case_idx: 3,
665                case_value: Some(Box::new(names.into_value())),
666            },
667            WitTypeNode::TupleType(types) => Value::Variant {
668                case_idx: 4,
669                case_value: Some(Box::new(types.into_value())),
670            },
671            WitTypeNode::ListType(elem) => Value::Variant {
672                case_idx: 5,
673                case_value: Some(Box::new(elem.into_value())),
674            },
675            WitTypeNode::OptionType(elem) => Value::Variant {
676                case_idx: 6,
677                case_value: Some(Box::new(elem.into_value())),
678            },
679            WitTypeNode::ResultType((ok, err)) => Value::Variant {
680                case_idx: 7,
681                case_value: Some(Box::new((ok, err).into_value())),
682            },
683            WitTypeNode::PrimU8Type => Value::Variant {
684                case_idx: 8,
685                case_value: None,
686            },
687            WitTypeNode::PrimU16Type => Value::Variant {
688                case_idx: 9,
689                case_value: None,
690            },
691            WitTypeNode::PrimU32Type => Value::Variant {
692                case_idx: 10,
693                case_value: None,
694            },
695            WitTypeNode::PrimU64Type => Value::Variant {
696                case_idx: 11,
697                case_value: None,
698            },
699            WitTypeNode::PrimS8Type => Value::Variant {
700                case_idx: 12,
701                case_value: None,
702            },
703            WitTypeNode::PrimS16Type => Value::Variant {
704                case_idx: 13,
705                case_value: None,
706            },
707            WitTypeNode::PrimS32Type => Value::Variant {
708                case_idx: 14,
709                case_value: None,
710            },
711            WitTypeNode::PrimS64Type => Value::Variant {
712                case_idx: 15,
713                case_value: None,
714            },
715            WitTypeNode::PrimF32Type => Value::Variant {
716                case_idx: 16,
717                case_value: None,
718            },
719            WitTypeNode::PrimF64Type => Value::Variant {
720                case_idx: 17,
721                case_value: None,
722            },
723            WitTypeNode::PrimCharType => Value::Variant {
724                case_idx: 18,
725                case_value: None,
726            },
727            WitTypeNode::PrimBoolType => Value::Variant {
728                case_idx: 19,
729                case_value: None,
730            },
731            WitTypeNode::PrimStringType => Value::Variant {
732                case_idx: 20,
733                case_value: None,
734            },
735            WitTypeNode::HandleType(handle) => Value::Variant {
736                case_idx: 17,
737                case_value: Some(Box::new(handle.into_value())),
738            },
739        }
740    }
741
742    fn get_type() -> AnalysedType {
743        variant(vec![
744            case(
745                "record-type",
746                list(tuple(vec![str(), NodeIndex::get_type()])),
747            ),
748            case(
749                "variant-type",
750                list(tuple(vec![str(), option(NodeIndex::get_type())])),
751            ),
752            case("enum-type", list(str())),
753            case("flags-type", list(str())),
754            case("tuple-type", list(NodeIndex::get_type())),
755            case("list-type", NodeIndex::get_type()),
756            case("option-type", NodeIndex::get_type()),
757            case(
758                "result-type",
759                tuple(vec![
760                    option(NodeIndex::get_type()),
761                    option(NodeIndex::get_type()),
762                ]),
763            ),
764            unit_case("prim-u8-type"),
765            unit_case("prim-u16-type"),
766            unit_case("prim-u32-type"),
767            unit_case("prim-u64-type"),
768            unit_case("prim-s8-type"),
769            unit_case("prim-s16-type"),
770            unit_case("prim-s32-type"),
771            unit_case("prim-s64-type"),
772            unit_case("prim-f32-type"),
773            unit_case("prim-f64-type"),
774            unit_case("prim-char-type"),
775            unit_case("prim-bool-type"),
776            unit_case("prim-string-type"),
777            case(
778                "handle-type",
779                tuple(vec![analysed_type::u64(), ResourceMode::get_type()]),
780            ),
781        ])
782    }
783}
784
785impl IntoValue for Instant {
786    fn into_value(self) -> Value {
787        Value::U64(self.elapsed().as_nanos() as u64)
788    }
789
790    fn get_type() -> AnalysedType {
791        analysed_type::u64()
792    }
793}
794
795impl IntoValue for Duration {
796    fn into_value(self) -> Value {
797        Value::U64(self.as_nanos() as u64)
798    }
799
800    fn get_type() -> AnalysedType {
801        analysed_type::u64()
802    }
803}
804
805#[cfg(feature = "host")]
806impl IntoValue for crate::ResourceMode {
807    fn into_value(self) -> Value {
808        match self {
809            ResourceMode::Owned => Value::Enum(0),
810            ResourceMode::Borrowed => Value::Enum(1),
811        }
812    }
813
814    fn get_type() -> AnalysedType {
815        analysed_type::r#enum(&["owned", "borrowed"])
816    }
817}
818
819#[cfg(feature = "host")]
820impl IntoValue for crate::RpcError {
821    fn into_value(self) -> Value {
822        match self {
823            RpcError::ProtocolError(value) => Value::Variant {
824                case_idx: 0,
825                case_value: Some(Box::new(Value::String(value))),
826            },
827            RpcError::Denied(value) => Value::Variant {
828                case_idx: 1,
829                case_value: Some(Box::new(Value::String(value))),
830            },
831            RpcError::NotFound(value) => Value::Variant {
832                case_idx: 2,
833                case_value: Some(Box::new(Value::String(value))),
834            },
835            RpcError::RemoteInternalError(value) => Value::Variant {
836                case_idx: 3,
837                case_value: Some(Box::new(Value::String(value))),
838            },
839        }
840    }
841
842    fn get_type() -> AnalysedType {
843        use analysed_type::case;
844
845        variant(vec![
846            case("protocol-error", analysed_type::str()),
847            case("denied", analysed_type::str()),
848            case("not-found", analysed_type::str()),
849            case("remote-internal-error", analysed_type::str()),
850        ])
851    }
852}
853
854#[cfg(feature = "host")]
855impl IntoValue for ValueAndType {
856    fn into_value(self) -> Value {
857        let wit_value: WitValue = self.value.into();
858        let wit_type: WitType = self.typ.into();
859        Value::Record(vec![wit_value.into_value(), wit_type.into_value()])
860    }
861
862    fn get_type() -> AnalysedType {
863        analysed_type::record(vec![
864            analysed_type::field("value", WitValue::get_type()),
865            analysed_type::field("type", WitType::get_type()),
866        ])
867    }
868}
869
870#[cfg(feature = "host")]
871impl IntoValue for Value {
872    fn into_value(self) -> Value {
873        let wit_value: WitValue = self.into();
874        wit_value.into_value()
875    }
876
877    fn get_type() -> AnalysedType {
878        WitValue::get_type()
879    }
880}
881
882#[cfg(feature = "host")]
883impl IntoValue for AnalysedType {
884    fn into_value(self) -> Value {
885        let wit_type: WitType = self.into();
886        wit_type.into_value()
887    }
888
889    fn get_type() -> AnalysedType {
890        WitType::get_type()
891    }
892}
893
894impl From<WitType> for AnalysedType {
895    fn from(value: WitType) -> Self {
896        assert!(!value.nodes.is_empty());
897        build_tree(&value.nodes[0], &value.nodes)
898    }
899}
900
901fn build_tree(node: &NamedWitTypeNode, nodes: &[NamedWitTypeNode]) -> AnalysedType {
902    match &node.type_ {
903        WitTypeNode::RecordType(fields) => {
904            let fields = fields
905                .iter()
906                .map(|(name, idx)| {
907                    let field_type = build_tree(&nodes[*idx as usize], nodes);
908                    analysed_type::field(name, field_type)
909                })
910                .collect();
911            analysed_type::record(fields).with_optional_name(node.name.clone())
912        }
913        WitTypeNode::VariantType(cases) => {
914            let cases = cases
915                .iter()
916                .map(|(name, idx)| match idx {
917                    Some(idx) => {
918                        let case_type = build_tree(&nodes[*idx as usize], nodes);
919                        analysed_type::case(name, case_type)
920                    }
921                    None => analysed_type::unit_case(name),
922                })
923                .collect();
924            variant(cases).with_optional_name(node.name.clone())
925        }
926        WitTypeNode::EnumType(names) => AnalysedType::Enum(TypeEnum {
927            cases: names.clone(),
928            name: node.name.clone(),
929            owner: node.owner.clone(),
930        }),
931        WitTypeNode::FlagsType(names) => AnalysedType::Flags(TypeFlags {
932            names: names.clone(),
933            name: node.name.clone(),
934            owner: node.owner.clone(),
935        }),
936        WitTypeNode::TupleType(types) => {
937            let types = types
938                .iter()
939                .map(|idx| build_tree(&nodes[*idx as usize], nodes))
940                .collect();
941            tuple(types).with_optional_name(node.name.clone())
942        }
943        WitTypeNode::ListType(elem_type) => {
944            let elem_type = build_tree(&nodes[*elem_type as usize], nodes);
945            list(elem_type).with_optional_name(node.name.clone())
946        }
947        WitTypeNode::OptionType(inner_type) => {
948            let inner_type = build_tree(&nodes[*inner_type as usize], nodes);
949            option(inner_type).with_optional_name(node.name.clone())
950        }
951        WitTypeNode::ResultType((ok_type, err_type)) => match (ok_type, err_type) {
952            (Some(ok_type), Some(err_type)) => {
953                let ok_type = build_tree(&nodes[*ok_type as usize], nodes);
954                let err_type = build_tree(&nodes[*err_type as usize], nodes);
955                result(ok_type, err_type).with_optional_name(node.name.clone())
956            }
957            (None, Some(err_type)) => {
958                let err_type = build_tree(&nodes[*err_type as usize], nodes);
959                result_err(err_type).with_optional_name(node.name.clone())
960            }
961            (Some(ok_type), None) => {
962                let ok_type = build_tree(&nodes[*ok_type as usize], nodes);
963                result_ok(ok_type).with_optional_name(node.name.clone())
964            }
965            (None, None) => panic!("ResultType with no ok_type or err_type"),
966        },
967        WitTypeNode::PrimU8Type => analysed_type::u8(),
968        WitTypeNode::PrimU16Type => analysed_type::u16(),
969        WitTypeNode::PrimU32Type => analysed_type::u32(),
970        WitTypeNode::PrimU64Type => analysed_type::u64(),
971        WitTypeNode::PrimS8Type => analysed_type::s8(),
972        WitTypeNode::PrimS16Type => analysed_type::s16(),
973        WitTypeNode::PrimS32Type => analysed_type::s32(),
974        WitTypeNode::PrimS64Type => analysed_type::s64(),
975        WitTypeNode::PrimF32Type => analysed_type::f32(),
976        WitTypeNode::PrimF64Type => analysed_type::f64(),
977        WitTypeNode::PrimCharType => analysed_type::chr(),
978        WitTypeNode::PrimBoolType => analysed_type::bool(),
979        WitTypeNode::PrimStringType => analysed_type::str(),
980        WitTypeNode::HandleType((id, mode)) => analysed_type::handle(
981            AnalysedResourceId(*id),
982            match mode {
983                crate::ResourceMode::Owned => AnalysedResourceMode::Owned,
984                crate::ResourceMode::Borrowed => AnalysedResourceMode::Borrowed,
985            },
986        )
987        .with_optional_name(node.name.clone()),
988    }
989}
990
991impl From<AnalysedType> for WitType {
992    fn from(value: AnalysedType) -> Self {
993        let mut builder = WitTypeBuilder::new();
994        builder.add(value);
995        builder.build()
996    }
997}
998
999struct WitTypeBuilder {
1000    nodes: Vec<NamedWitTypeNode>,
1001    mapping: HashMap<AnalysedType, usize>,
1002}
1003
1004impl WitTypeBuilder {
1005    pub fn new() -> Self {
1006        Self {
1007            nodes: Vec::new(),
1008            mapping: HashMap::new(),
1009        }
1010    }
1011
1012    pub fn add(&mut self, typ: AnalysedType) -> usize {
1013        if let Some(idx) = self.mapping.get(&typ) {
1014            *idx
1015        } else {
1016            let idx = self.nodes.len();
1017            self.nodes.push(NamedWitTypeNode {
1018                name: None,
1019                owner: None,
1020                type_: WitTypeNode::PrimBoolType,
1021            }); // placeholder, to be replaced
1022            let name = typ.name().map(|n| n.to_string());
1023            let owner = typ.owner().map(|o| o.to_string());
1024            let node: WitTypeNode = match typ {
1025                AnalysedType::Variant(variant) => {
1026                    let mut cases = Vec::new();
1027                    for pair in variant.cases {
1028                        let case_idx = pair.typ.map(|case| self.add(case) as i32);
1029                        cases.push((pair.name, case_idx));
1030                    }
1031                    WitTypeNode::VariantType(cases)
1032                }
1033                AnalysedType::Result(result) => {
1034                    let ok_idx = result.ok.map(|ok| self.add(*ok) as i32);
1035                    let err_idx = result.err.map(|err| self.add(*err) as i32);
1036                    WitTypeNode::ResultType((ok_idx, err_idx))
1037                }
1038                AnalysedType::Option(option) => {
1039                    let inner_idx = self.add(*option.inner) as i32;
1040                    WitTypeNode::OptionType(inner_idx)
1041                }
1042                AnalysedType::Enum(enm) => WitTypeNode::EnumType(enm.cases),
1043                AnalysedType::Flags(flags) => WitTypeNode::FlagsType(flags.names),
1044                AnalysedType::Record(record) => {
1045                    let mut fields = Vec::new();
1046                    for field in record.fields {
1047                        fields.push((field.name, self.add(field.typ) as i32));
1048                    }
1049                    WitTypeNode::RecordType(fields)
1050                }
1051                AnalysedType::Tuple(tuple) => {
1052                    let mut indices = Vec::new();
1053                    for item in tuple.items {
1054                        indices.push(self.add(item) as i32);
1055                    }
1056                    WitTypeNode::TupleType(indices)
1057                }
1058                AnalysedType::List(lst) => {
1059                    let elem_idx = self.add(*lst.inner);
1060                    WitTypeNode::ListType(elem_idx as i32)
1061                }
1062                AnalysedType::Str(_) => WitTypeNode::PrimStringType,
1063                AnalysedType::Chr(_) => WitTypeNode::PrimCharType,
1064                AnalysedType::F64(_) => WitTypeNode::PrimF64Type,
1065                AnalysedType::F32(_) => WitTypeNode::PrimF32Type,
1066                AnalysedType::U64(_) => WitTypeNode::PrimU64Type,
1067                AnalysedType::S64(_) => WitTypeNode::PrimS64Type,
1068                AnalysedType::U32(_) => WitTypeNode::PrimU32Type,
1069                AnalysedType::S32(_) => WitTypeNode::PrimS32Type,
1070                AnalysedType::U16(_) => WitTypeNode::PrimU16Type,
1071                AnalysedType::S16(_) => WitTypeNode::PrimS16Type,
1072                AnalysedType::U8(_) => WitTypeNode::PrimU8Type,
1073                AnalysedType::S8(_) => WitTypeNode::PrimS8Type,
1074                AnalysedType::Bool(_) => WitTypeNode::PrimBoolType,
1075                AnalysedType::Handle(handle) => WitTypeNode::HandleType((
1076                    handle.resource_id.0,
1077                    match handle.mode {
1078                        AnalysedResourceMode::Owned => ResourceMode::Owned,
1079                        AnalysedResourceMode::Borrowed => ResourceMode::Borrowed,
1080                    },
1081                )),
1082            };
1083            self.nodes[idx] = NamedWitTypeNode {
1084                name,
1085                owner,
1086                type_: node,
1087            };
1088            idx
1089        }
1090    }
1091
1092    pub fn build(self) -> WitType {
1093        WitType { nodes: self.nodes }
1094    }
1095}
1096
1097impl From<crate::golem_rpc_0_2_x::types::ValueAndType> for ValueAndType {
1098    fn from(value: crate::golem_rpc_0_2_x::types::ValueAndType) -> Self {
1099        Self {
1100            value: value.value.into(),
1101            typ: value.typ.into(),
1102        }
1103    }
1104}
1105
1106impl From<ValueAndType> for crate::golem_rpc_0_2_x::types::ValueAndType {
1107    fn from(value: ValueAndType) -> Self {
1108        Self {
1109            value: value.value.into(),
1110            typ: value.typ.into(),
1111        }
1112    }
1113}
1114
1115#[cfg(feature = "host")]
1116mod extra_bindings {
1117    use crate::analysis::analysed_type::{bool, list, str};
1118    use crate::analysis::{analysed_type, AnalysedType};
1119    use crate::{IntoValue, IntoValueAndType, Value};
1120    use bigdecimal::BigDecimal;
1121    use bit_vec::BitVec;
1122    use chrono::{Datelike, Offset, Timelike};
1123    use url::Url;
1124
1125    impl IntoValue for BigDecimal {
1126        fn into_value(self) -> Value {
1127            self.to_string().into_value()
1128        }
1129
1130        fn get_type() -> AnalysedType {
1131            str()
1132        }
1133    }
1134
1135    impl IntoValue for chrono::NaiveDate {
1136        fn into_value(self) -> Value {
1137            let year = self.year();
1138            let month = self.month() as u8;
1139            let day = self.day() as u8;
1140            Value::Record(vec![Value::S32(year), Value::U8(month), Value::U8(day)])
1141        }
1142
1143        fn get_type() -> AnalysedType {
1144            analysed_type::record(vec![
1145                analysed_type::field("year", analysed_type::s32()),
1146                analysed_type::field("month", analysed_type::u8()),
1147                analysed_type::field("day", analysed_type::u8()),
1148            ])
1149        }
1150    }
1151
1152    impl IntoValue for chrono::NaiveTime {
1153        fn into_value(self) -> Value {
1154            let hour = self.hour() as u8;
1155            let minute = self.minute() as u8;
1156            let second = self.second() as u8;
1157            let nanosecond = self.nanosecond();
1158
1159            Value::Record(vec![
1160                Value::U8(hour),
1161                Value::U8(minute),
1162                Value::U8(second),
1163                Value::U32(nanosecond),
1164            ])
1165        }
1166
1167        fn get_type() -> AnalysedType {
1168            analysed_type::record(vec![
1169                analysed_type::field("hours", analysed_type::u8()),
1170                analysed_type::field("minutes", analysed_type::u8()),
1171                analysed_type::field("seconds", analysed_type::u8()),
1172                analysed_type::field("nanoseconds", analysed_type::u32()),
1173            ])
1174        }
1175    }
1176
1177    impl IntoValue for chrono::NaiveDateTime {
1178        fn into_value(self) -> Value {
1179            let date = self.date().into_value_and_type();
1180            let time = self.time().into_value_and_type();
1181            Value::Record(vec![date.value, time.value])
1182        }
1183
1184        fn get_type() -> AnalysedType {
1185            analysed_type::record(vec![
1186                analysed_type::field("date", chrono::NaiveDate::get_type()),
1187                analysed_type::field("time", chrono::NaiveTime::get_type()),
1188            ])
1189        }
1190    }
1191
1192    impl IntoValue for chrono::DateTime<chrono::Utc> {
1193        fn into_value(self) -> Value {
1194            let timestamp = self.naive_utc().into_value_and_type();
1195            let offset = self.offset().fix().local_minus_utc();
1196            Value::Record(vec![timestamp.value, Value::S32(offset)])
1197        }
1198
1199        fn get_type() -> AnalysedType {
1200            analysed_type::record(vec![
1201                analysed_type::field("timestamp", chrono::NaiveDateTime::get_type()),
1202                analysed_type::field("offset", analysed_type::s32()),
1203            ])
1204        }
1205    }
1206
1207    impl IntoValue for BitVec {
1208        fn into_value(self) -> Value {
1209            self.into_iter().collect::<Vec<_>>().into_value()
1210        }
1211
1212        fn get_type() -> AnalysedType {
1213            list(bool())
1214        }
1215    }
1216
1217    impl IntoValue for Url {
1218        fn into_value(self) -> Value {
1219            Value::String(self.to_string())
1220        }
1221
1222        fn get_type() -> AnalysedType {
1223            str()
1224        }
1225    }
1226}
1227
1228#[cfg(test)]
1229mod tests {
1230    use crate::analysis::AnalysedType;
1231    use crate::{IntoValue, RpcError, WitType, WitValue};
1232    use test_r::test;
1233
1234    #[test]
1235    fn encoding_rpc_error_type() {
1236        let typ1 = RpcError::get_type();
1237        let encoded: WitType = typ1.clone().into();
1238        let typ2: AnalysedType = encoded.into();
1239        assert_eq!(typ1, typ2);
1240    }
1241
1242    #[test]
1243    fn encoding_wit_value_type() {
1244        let typ1 = WitValue::get_type();
1245        let encoded: WitType = typ1.clone().into();
1246        let typ2: AnalysedType = encoded.into();
1247        assert_eq!(typ1, typ2);
1248    }
1249}