1use crate::analysis::{AnalysedFunctionParameter, AnalysedType};
16use crate::Value;
17
18include!(concat!(env!("OUT_DIR"), "/wasm.rpc.rs"));
19
20impl From<super::WitValue> for WitValue {
23 fn from(value: super::WitValue) -> Self {
24 WitValue {
25 nodes: value.nodes.into_iter().map(|node| node.into()).collect(),
26 }
27 }
28}
29
30impl From<super::WitNode> for WitNode {
31 fn from(value: super::WitNode) -> Self {
32 match value {
33 super::WitNode::RecordValue(fields) => WitNode {
34 value: Some(wit_node::Value::Record(WitRecordNode { fields })),
35 },
36 super::WitNode::VariantValue((case_index, case_value)) => WitNode {
37 value: Some(wit_node::Value::Variant(WitVariantNode {
38 case_index,
39 case_value,
40 })),
41 },
42 super::WitNode::EnumValue(value) => WitNode {
43 value: Some(wit_node::Value::Enum(WitEnumNode { value })),
44 },
45 super::WitNode::FlagsValue(flags) => WitNode {
46 value: Some(wit_node::Value::Flags(WitFlagsNode { flags })),
47 },
48 super::WitNode::TupleValue(values) => WitNode {
49 value: Some(wit_node::Value::Tuple(WitTupleNode { values })),
50 },
51 super::WitNode::ListValue(values) => WitNode {
52 value: Some(wit_node::Value::List(WitListNode { values })),
53 },
54 super::WitNode::OptionValue(value) => WitNode {
55 value: Some(wit_node::Value::Option(WitOptionNode { value })),
56 },
57 super::WitNode::ResultValue(type_idx) => WitNode {
58 value: Some(wit_node::Value::Result(WitResultNode {
59 discriminant: if type_idx.is_ok() { 0 } else { 1 },
60 value: type_idx.unwrap_or_else(|index| index),
61 })),
62 },
63 super::WitNode::PrimU8(value) => WitNode {
64 value: Some(wit_node::Value::U8(WitPrimU8Node {
65 value: value as u32,
66 })),
67 },
68 super::WitNode::PrimU16(value) => WitNode {
69 value: Some(wit_node::Value::U16(WitPrimU16Node {
70 value: value as u32,
71 })),
72 },
73 super::WitNode::PrimU32(value) => WitNode {
74 value: Some(wit_node::Value::U32(WitPrimU32Node { value })),
75 },
76 super::WitNode::PrimU64(value) => WitNode {
77 value: Some(wit_node::Value::U64(WitPrimU64Node { value })),
78 },
79 super::WitNode::PrimS8(value) => WitNode {
80 value: Some(wit_node::Value::I8(WitPrimI8Node {
81 value: value as i32,
82 })),
83 },
84 super::WitNode::PrimS16(value) => WitNode {
85 value: Some(wit_node::Value::I16(WitPrimI16Node {
86 value: value as i32,
87 })),
88 },
89 super::WitNode::PrimS32(value) => WitNode {
90 value: Some(wit_node::Value::I32(WitPrimI32Node { value })),
91 },
92 super::WitNode::PrimS64(value) => WitNode {
93 value: Some(wit_node::Value::I64(WitPrimI64Node { value })),
94 },
95 super::WitNode::PrimFloat32(value) => WitNode {
96 value: Some(wit_node::Value::F32(WitPrimF32Node { value })),
97 },
98 super::WitNode::PrimFloat64(value) => WitNode {
99 value: Some(wit_node::Value::F64(WitPrimF64Node { value })),
100 },
101 super::WitNode::PrimChar(value) => WitNode {
102 value: Some(wit_node::Value::Char(WitPrimCharNode {
103 value: value as u32,
104 })),
105 },
106 super::WitNode::PrimBool(value) => WitNode {
107 value: Some(wit_node::Value::Bool(WitPrimBoolNode { value })),
108 },
109 super::WitNode::PrimString(value) => WitNode {
110 value: Some(wit_node::Value::String(WitPrimStringNode { value })),
111 },
112 super::WitNode::Handle((uri, value)) => WitNode {
113 value: Some(wit_node::Value::Handle(WitHandleNode {
114 uri: uri.value,
115 value,
116 })),
117 },
118 }
119 }
120}
121
122impl TryFrom<WitValue> for super::WitValue {
124 type Error = String;
125
126 fn try_from(value: WitValue) -> Result<Self, Self::Error> {
127 Ok(super::WitValue {
128 nodes: value
129 .nodes
130 .into_iter()
131 .map(|node| node.try_into())
132 .collect::<Result<Vec<_>, _>>()?,
133 })
134 }
135}
136
137impl TryFrom<WitNode> for super::WitNode {
138 type Error = String;
139
140 fn try_from(value: WitNode) -> Result<Self, Self::Error> {
141 match value.value {
142 None => Err("Protobuf WitNode has no value".to_string()),
143 Some(wit_node::Value::Record(WitRecordNode { fields })) => {
144 Ok(super::WitNode::RecordValue(fields))
145 }
146 Some(wit_node::Value::Variant(WitVariantNode {
147 case_index,
148 case_value,
149 })) => Ok(super::WitNode::VariantValue((case_index, case_value))),
150 Some(wit_node::Value::Enum(WitEnumNode { value })) => {
151 Ok(super::WitNode::EnumValue(value))
152 }
153 Some(wit_node::Value::Flags(WitFlagsNode { flags })) => {
154 Ok(super::WitNode::FlagsValue(flags))
155 }
156 Some(wit_node::Value::Tuple(WitTupleNode { values })) => {
157 Ok(super::WitNode::TupleValue(values))
158 }
159 Some(wit_node::Value::List(WitListNode { values })) => {
160 Ok(super::WitNode::ListValue(values))
161 }
162 Some(wit_node::Value::Option(WitOptionNode { value })) => {
163 Ok(super::WitNode::OptionValue(value))
164 }
165 Some(wit_node::Value::Result(WitResultNode {
166 discriminant,
167 value,
168 })) => match discriminant {
169 0 => Ok(super::WitNode::ResultValue(Ok(value))),
170 1 => Ok(super::WitNode::ResultValue(Err(value))),
171 _ => Err("Protobuf WitResultNode has invalid discriminant".to_string()),
172 },
173 Some(wit_node::Value::U8(WitPrimU8Node { value })) => {
174 Ok(super::WitNode::PrimU8(value as u8))
175 }
176 Some(wit_node::Value::U16(WitPrimU16Node { value })) => {
177 Ok(super::WitNode::PrimU16(value as u16))
178 }
179 Some(wit_node::Value::U32(WitPrimU32Node { value })) => {
180 Ok(super::WitNode::PrimU32(value))
181 }
182 Some(wit_node::Value::U64(WitPrimU64Node { value })) => {
183 Ok(super::WitNode::PrimU64(value))
184 }
185 Some(wit_node::Value::I8(WitPrimI8Node { value })) => {
186 Ok(super::WitNode::PrimS8(value as i8))
187 }
188 Some(wit_node::Value::I16(WitPrimI16Node { value })) => {
189 Ok(super::WitNode::PrimS16(value as i16))
190 }
191 Some(wit_node::Value::I32(WitPrimI32Node { value })) => {
192 Ok(super::WitNode::PrimS32(value))
193 }
194 Some(wit_node::Value::I64(WitPrimI64Node { value })) => {
195 Ok(super::WitNode::PrimS64(value))
196 }
197 Some(wit_node::Value::F32(WitPrimF32Node { value })) => {
198 Ok(super::WitNode::PrimFloat32(value))
199 }
200 Some(wit_node::Value::F64(WitPrimF64Node { value })) => {
201 Ok(super::WitNode::PrimFloat64(value))
202 }
203 Some(wit_node::Value::Char(WitPrimCharNode { value })) => Ok(super::WitNode::PrimChar(
204 char::from_u32(value)
205 .ok_or("Protobuf WitPrimCharNode has invalid value".to_string())?,
206 )),
207 Some(wit_node::Value::Bool(WitPrimBoolNode { value })) => {
208 Ok(super::WitNode::PrimBool(value))
209 }
210 Some(wit_node::Value::String(WitPrimStringNode { value })) => {
211 Ok(super::WitNode::PrimString(value))
212 }
213 Some(wit_node::Value::Handle(WitHandleNode { uri, value })) => {
214 Ok(super::WitNode::Handle((super::Uri { value: uri }, value)))
215 }
216 }
217 }
218}
219
220impl From<super::WitValue> for Val {
222 fn from(value: super::WitValue) -> Self {
223 let value: Value = value.into();
224 value.into()
225 }
226}
227
228impl TryFrom<&ValueAndType> for Type {
229 type Error = String;
230
231 fn try_from(value: &ValueAndType) -> Result<Self, Self::Error> {
232 Ok(value
233 .typ
234 .as_ref()
235 .ok_or_else(|| "Missing typ field".to_string())?
236 .clone())
237 }
238}
239
240impl TryFrom<&ValueAndType> for AnalysedType {
241 type Error = String;
242 fn try_from(value: &ValueAndType) -> Result<Self, Self::Error> {
243 let typ = Type::try_from(value)?;
244 AnalysedType::try_from(&typ)
245 }
246}
247
248impl TryFrom<ValueAndType> for super::WitValue {
249 type Error = String;
250
251 fn try_from(value: ValueAndType) -> Result<Self, Self::Error> {
252 let value: Value = value.try_into()?;
253 Ok(super::WitValue::from(value))
254 }
255}
256
257impl TryFrom<ValueAndType> for Value {
258 type Error = String;
259
260 fn try_from(value: ValueAndType) -> Result<Self, Self::Error> {
261 value
262 .value
263 .ok_or_else(|| "Missing value field".to_string())?
264 .try_into()
265 }
266}
267
268impl From<Value> for Val {
269 fn from(value: Value) -> Self {
270 match value {
271 Value::Bool(value) => Val {
272 val: Some(val::Val::Bool(value)),
273 },
274 Value::U8(value) => Val {
275 val: Some(val::Val::U8(value as i32)),
276 },
277 Value::U16(value) => Val {
278 val: Some(val::Val::U16(value as i32)),
279 },
280 Value::U32(value) => Val {
281 val: Some(val::Val::U32(value as i64)),
282 },
283 Value::U64(value) => Val {
284 val: Some(val::Val::U64(value as i64)),
285 },
286 Value::S8(value) => Val {
287 val: Some(val::Val::S8(value as i32)),
288 },
289 Value::S16(value) => Val {
290 val: Some(val::Val::S16(value as i32)),
291 },
292 Value::S32(value) => Val {
293 val: Some(val::Val::S32(value)),
294 },
295 Value::S64(value) => Val {
296 val: Some(val::Val::S64(value)),
297 },
298 Value::F32(value) => Val {
299 val: Some(val::Val::F32(value)),
300 },
301 Value::F64(value) => Val {
302 val: Some(val::Val::F64(value)),
303 },
304 Value::Char(value) => Val {
305 val: Some(val::Val::Char(value as i32)),
306 },
307 Value::String(value) => Val {
308 val: Some(val::Val::String(value)),
309 },
310 Value::List(items) => Val {
311 val: Some(val::Val::List(ValList {
312 values: items.into_iter().map(|item| item.into()).collect(),
313 })),
314 },
315 Value::Tuple(items) => Val {
316 val: Some(val::Val::Tuple(ValTuple {
317 values: items.into_iter().map(|item| item.into()).collect(),
318 })),
319 },
320 Value::Record(fields) => Val {
321 val: Some(val::Val::Record(ValRecord {
322 values: fields.into_iter().map(|value| value.into()).collect(),
323 })),
324 },
325 Value::Variant {
326 case_idx,
327 case_value,
328 } => Val {
329 val: Some(val::Val::Variant(Box::new(ValVariant {
330 discriminant: case_idx as i32,
331 value: case_value.map(|case_value| Box::new((*case_value).into())),
332 }))),
333 },
334 Value::Enum(value) => Val {
335 val: Some(val::Val::Enum(ValEnum {
336 discriminant: value as i32,
337 })),
338 },
339 Value::Flags(values) => {
340 let mut indexes = Vec::with_capacity(values.len());
341 for (i, value) in values.iter().enumerate() {
342 if *value {
343 indexes.push(i as i32);
344 }
345 }
346 Val {
347 val: Some(val::Val::Flags(ValFlags {
348 count: values.len() as i32,
349 value: indexes,
350 })),
351 }
352 }
353 Value::Option(Some(value)) => Val {
354 val: Some(val::Val::Option(Box::new(ValOption {
355 discriminant: 1,
356 value: Some(Box::new((*value).into())),
357 }))),
358 },
359 Value::Option(None) => Val {
360 val: Some(val::Val::Option(Box::new(ValOption {
361 discriminant: 0,
362 value: None,
363 }))),
364 },
365 Value::Result(Ok(value)) => Val {
366 val: Some(val::Val::Result(Box::new(ValResult {
367 discriminant: 0,
368 value: value.map(|value| Box::new((*value).into())),
369 }))),
370 },
371 Value::Result(Err(value)) => Val {
372 val: Some(val::Val::Result(Box::new(ValResult {
373 discriminant: 1,
374 value: value.map(|value| Box::new((*value).into())),
375 }))),
376 },
377 Value::Handle { uri, resource_id } => Val {
378 val: Some(val::Val::Handle(ValHandle {
379 uri,
380 value: resource_id,
381 })),
382 },
383 }
384 }
385}
386
387impl TryFrom<Val> for super::WitValue {
389 type Error = String;
390
391 fn try_from(value: Val) -> Result<Self, Self::Error> {
392 let value: Value = value.try_into()?;
393 Ok(value.into())
394 }
395}
396
397impl TryFrom<Val> for Value {
398 type Error = String;
399
400 fn try_from(value: Val) -> Result<Self, Self::Error> {
401 match value.val {
402 None => Err("Protobuf Val has no value".to_string()),
403 Some(val::Val::Bool(value)) => Ok(Value::Bool(value)),
404 Some(val::Val::U8(value)) => Ok(Value::U8(value as u8)),
405 Some(val::Val::U16(value)) => Ok(Value::U16(value as u16)),
406 Some(val::Val::U32(value)) => Ok(Value::U32(value as u32)),
407 Some(val::Val::U64(value)) => Ok(Value::U64(value as u64)),
408 Some(val::Val::S8(value)) => Ok(Value::S8(value as i8)),
409 Some(val::Val::S16(value)) => Ok(Value::S16(value as i16)),
410 Some(val::Val::S32(value)) => Ok(Value::S32(value)),
411 Some(val::Val::S64(value)) => Ok(Value::S64(value)),
412 Some(val::Val::F32(value)) => Ok(Value::F32(value)),
413 Some(val::Val::F64(value)) => Ok(Value::F64(value)),
414 Some(val::Val::Char(value)) => Ok(Value::Char(
415 char::from_u32(value as u32)
416 .ok_or("Protobuf WitPrimCharNode has invalid value".to_string())?,
417 )),
418 Some(val::Val::String(value)) => Ok(Value::String(value)),
419 Some(val::Val::List(ValList { values })) => Ok(Value::List(
420 values
421 .into_iter()
422 .map(|value| value.try_into())
423 .collect::<Result<Vec<_>, _>>()?,
424 )),
425 Some(val::Val::Tuple(ValTuple { values })) => Ok(Value::Tuple(
426 values
427 .into_iter()
428 .map(|value| value.try_into())
429 .collect::<Result<Vec<_>, _>>()?,
430 )),
431 Some(val::Val::Record(ValRecord { values })) => Ok(Value::Record(
432 values
433 .into_iter()
434 .map(|value| value.try_into())
435 .collect::<Result<Vec<_>, _>>()?,
436 )),
437 Some(val::Val::Variant(variant)) => {
438 let discriminant = variant.discriminant as u32;
439 match variant.value {
440 Some(value) => Ok(Value::Variant {
441 case_idx: discriminant,
442 case_value: Some(Box::new((*value).try_into()?)),
443 }),
444 None => Ok(Value::Variant {
445 case_idx: discriminant,
446 case_value: None,
447 }),
448 }
449 }
450 Some(val::Val::Enum(ValEnum { discriminant })) => Ok(Value::Enum(discriminant as u32)),
451 Some(val::Val::Flags(ValFlags { count, value })) => {
452 let mut flags = vec![false; count as usize];
453 for i in value {
454 flags[i as usize] = true;
455 }
456 Ok(Value::Flags(flags))
457 }
458 Some(val::Val::Option(inner)) => {
459 let ValOption {
460 discriminant,
461 value,
462 } = *inner;
463 match (discriminant, value) {
464 (0, None) => Ok(Value::Option(None)),
465 (1, Some(value)) => Ok(Value::Option(Some(Box::new((*value).try_into()?)))),
466 _ => Err("Protobuf ValOption has invalid discriminant or value".to_string()),
467 }
468 }
469 Some(val::Val::Result(inner)) => {
470 let ValResult {
471 discriminant,
472 value,
473 } = *inner;
474 match (discriminant, value) {
475 (0, Some(value)) => Ok(Value::Result(Ok(Some(Box::new((*value).try_into()?))))),
476 (0, None) => Ok(Value::Result(Ok(None))),
477 (1, Some(value)) => {
478 Ok(Value::Result(Err(Some(Box::new((*value).try_into()?)))))
479 }
480 (1, None) => Ok(Value::Result(Err(None))),
481 _ => Err("Protobuf ValResult has invalid discriminant or value".to_string()),
482 }
483 }
484 Some(val::Val::Handle(ValHandle { uri, value })) => Ok(Value::Handle {
485 uri,
486 resource_id: value,
487 }),
488 }
489 }
490}
491
492impl From<crate::ValueAndType> for ValueAndType {
493 fn from(value: crate::ValueAndType) -> Self {
494 ValueAndType {
495 value: Some(value.value.into()),
496 typ: Some((&value.typ).into()),
497 }
498 }
499}
500
501impl TryFrom<ValueAndType> for crate::ValueAndType {
502 type Error = String;
503
504 fn try_from(value: ValueAndType) -> Result<Self, Self::Error> {
505 let v: Value = value
506 .value
507 .ok_or_else(|| "Missing value field".to_string())?
508 .try_into()?;
509 let t: AnalysedType =
510 (&value.typ.ok_or_else(|| "Missing typ field".to_string())?).try_into()?;
511 Ok(crate::ValueAndType { value: v, typ: t })
512 }
513}
514
515pub fn function_parameters(
516 parameters: &[Val],
517 expected_parameters: Vec<AnalysedFunctionParameter>,
518) -> Result<(), Vec<String>> {
519 if parameters.len() == expected_parameters.len() {
520 Ok(())
521 } else {
522 Err(vec![format!(
523 "Unexpected number of parameters (got {}, expected: {})",
524 parameters.len(),
525 expected_parameters.len()
526 )])
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use test_r::test;
533
534 use super::{Val, WitValue};
535 use crate::Value;
536 use proptest::prelude::*;
537 use proptest_arbitrary_interop::arb_sized;
538
539 const CASES: u32 = 10000;
540 const SIZE: usize = 4096;
541
542 proptest! {
543
544 #![proptest_config(ProptestConfig {
545 cases: CASES, .. ProptestConfig::default()
546 })]
547 #[test]
548 fn round_trip_wit_value(value in arb_sized::<Value>(SIZE).prop_filter("Value must be equal to itself", |v| v.eq(v))) {
549 let wit_value: crate::WitValue = value.clone().into();
550 let protobuf_wit_value: WitValue = wit_value.into();
551 let round_trip_wit_value: crate::WitValue = protobuf_wit_value.try_into().unwrap();
552 let round_trip_value: Value = round_trip_wit_value.into();
553 prop_assert_eq!(value, round_trip_value);
554 }
555
556 #[test]
557 fn round_trip_val(value in arb_sized::<Value>(SIZE).prop_filter("Value must be equal to itself", |v| v.eq(v))) {
558 let wit_value: crate::WitValue = value.clone().into();
559
560 let protobuf_val: Val = wit_value.into();
561 let round_trip_wit_value: crate::WitValue = protobuf_val.try_into().unwrap();
562 let round_trip_value: Value = round_trip_wit_value.into();
563 prop_assert_eq!(value, round_trip_value);
564 }
565 }
566}