golem_wasm/
extractor.rs

1use crate::{Uri, WitNode, WitValue};
2
3pub trait WitValueExtractor<'a, 'b> {
4    fn u8(&'a self) -> Option<u8>;
5    fn u16(&'a self) -> Option<u16>;
6    fn u32(&'a self) -> Option<u32>;
7    fn u64(&'a self) -> Option<u64>;
8    fn s8(&'a self) -> Option<i8>;
9    fn s16(&'a self) -> Option<i16>;
10    fn s32(&'a self) -> Option<i32>;
11    fn s64(&'a self) -> Option<i64>;
12    fn f32(&'a self) -> Option<f32>;
13    fn f64(&'a self) -> Option<f64>;
14    fn char(&'a self) -> Option<char>;
15    fn bool(&'a self) -> Option<bool>;
16    fn string(&'a self) -> Option<&'b str>;
17    fn field(&'a self, field_idx: usize) -> Option<WitNodePointer<'b>>;
18    fn variant(&'a self) -> Option<(u32, Option<WitNodePointer<'b>>)>;
19    fn enum_value(&'a self) -> Option<u32>;
20    fn flags(&'a self) -> Option<&'b [bool]>;
21    fn tuple_element(&'a self, element_idx: usize) -> Option<WitNodePointer<'b>>;
22    fn list_elements<R>(&'a self, f: impl Fn(WitNodePointer<'b>) -> R) -> Option<Vec<R>>;
23    fn option(&'a self) -> Option<Option<WitNodePointer<'b>>>;
24    fn result(&'a self) -> Option<Result<Option<WitNodePointer<'b>>, Option<WitNodePointer<'b>>>>;
25
26    fn handle(&'a self) -> Option<(Uri, u64)>;
27}
28
29impl<'a: 'b, 'b> WitValueExtractor<'a, 'b> for WitValue {
30    fn u8(&self) -> Option<u8> {
31        WitNodePointer::new(self, 0).u8()
32    }
33
34    fn u16(&self) -> Option<u16> {
35        WitNodePointer::new(self, 0).u16()
36    }
37
38    fn u32(&self) -> Option<u32> {
39        WitNodePointer::new(self, 0).u32()
40    }
41
42    fn u64(&self) -> Option<u64> {
43        WitNodePointer::new(self, 0).u64()
44    }
45
46    fn s8(&self) -> Option<i8> {
47        WitNodePointer::new(self, 0).s8()
48    }
49
50    fn s16(&self) -> Option<i16> {
51        WitNodePointer::new(self, 0).s16()
52    }
53
54    fn s32(&self) -> Option<i32> {
55        WitNodePointer::new(self, 0).s32()
56    }
57
58    fn s64(&self) -> Option<i64> {
59        WitNodePointer::new(self, 0).s64()
60    }
61
62    fn f32(&self) -> Option<f32> {
63        WitNodePointer::new(self, 0).f32()
64    }
65
66    fn f64(&self) -> Option<f64> {
67        WitNodePointer::new(self, 0).f64()
68    }
69
70    fn char(&self) -> Option<char> {
71        WitNodePointer::new(self, 0).char()
72    }
73
74    fn bool(&self) -> Option<bool> {
75        WitNodePointer::new(self, 0).bool()
76    }
77
78    fn string(&'a self) -> Option<&'b str> {
79        let ptr = WitNodePointer::<'a>::new(self, 0);
80        ptr.string()
81    }
82
83    fn field(&'a self, field_idx: usize) -> Option<WitNodePointer<'b>> {
84        WitNodePointer::new(self, 0).field(field_idx)
85    }
86
87    fn variant(&'a self) -> Option<(u32, Option<WitNodePointer<'b>>)> {
88        WitNodePointer::new(self, 0).variant()
89    }
90
91    fn enum_value(&'a self) -> Option<u32> {
92        WitNodePointer::new(self, 0).enum_value()
93    }
94
95    fn flags(&'a self) -> Option<&'b [bool]> {
96        WitNodePointer::new(self, 0).flags()
97    }
98
99    fn tuple_element(&'a self, element_idx: usize) -> Option<WitNodePointer<'b>> {
100        WitNodePointer::new(self, 0).tuple_element(element_idx)
101    }
102
103    fn list_elements<R>(&'a self, f: impl Fn(WitNodePointer<'b>) -> R) -> Option<Vec<R>> {
104        WitNodePointer::new(self, 0).list_elements(f)
105    }
106
107    fn option(&'a self) -> Option<Option<WitNodePointer<'b>>> {
108        WitNodePointer::new(self, 0).option()
109    }
110
111    fn result(&'a self) -> Option<Result<Option<WitNodePointer<'b>>, Option<WitNodePointer<'b>>>> {
112        WitNodePointer::new(self, 0).result()
113    }
114
115    fn handle(&'a self) -> Option<(Uri, u64)> {
116        WitNodePointer::new(self, 0).handle()
117    }
118}
119
120pub struct WitNodePointer<'a> {
121    value: &'a WitValue,
122    idx: usize,
123}
124
125impl<'a> WitNodePointer<'a> {
126    fn new(value: &'a WitValue, idx: usize) -> Self {
127        assert!(idx < value.nodes.len());
128        Self { value, idx }
129    }
130
131    fn node(&self) -> &'a WitNode {
132        &self.value.nodes[self.idx]
133    }
134
135    fn u8(&self) -> Option<u8> {
136        if let WitNode::PrimU8(value) = self.node() {
137            Some(*value)
138        } else {
139            None
140        }
141    }
142
143    fn u16(&self) -> Option<u16> {
144        if let WitNode::PrimU16(value) = self.node() {
145            Some(*value)
146        } else {
147            None
148        }
149    }
150
151    fn u32(&self) -> Option<u32> {
152        if let WitNode::PrimU32(value) = self.node() {
153            Some(*value)
154        } else {
155            None
156        }
157    }
158
159    fn u64(&self) -> Option<u64> {
160        if let WitNode::PrimU64(value) = self.node() {
161            Some(*value)
162        } else {
163            None
164        }
165    }
166
167    fn s8(&self) -> Option<i8> {
168        if let WitNode::PrimS8(value) = self.node() {
169            Some(*value)
170        } else {
171            None
172        }
173    }
174
175    fn s16(&self) -> Option<i16> {
176        if let WitNode::PrimS16(value) = self.node() {
177            Some(*value)
178        } else {
179            None
180        }
181    }
182
183    fn s32(&self) -> Option<i32> {
184        if let WitNode::PrimS32(value) = self.node() {
185            Some(*value)
186        } else {
187            None
188        }
189    }
190
191    fn s64(&self) -> Option<i64> {
192        if let WitNode::PrimS64(value) = self.node() {
193            Some(*value)
194        } else {
195            None
196        }
197    }
198
199    fn f32(&self) -> Option<f32> {
200        if let WitNode::PrimFloat32(value) = self.node() {
201            Some(*value)
202        } else {
203            None
204        }
205    }
206
207    fn f64(&self) -> Option<f64> {
208        if let WitNode::PrimFloat64(value) = self.node() {
209            Some(*value)
210        } else {
211            None
212        }
213    }
214
215    fn char(&self) -> Option<char> {
216        if let WitNode::PrimChar(value) = self.node() {
217            Some(*value)
218        } else {
219            None
220        }
221    }
222
223    fn bool(&self) -> Option<bool> {
224        if let WitNode::PrimBool(value) = self.node() {
225            Some(*value)
226        } else {
227            None
228        }
229    }
230
231    fn string(&self) -> Option<&'a str> {
232        if let WitNode::PrimString(value) = self.node() {
233            Some(value)
234        } else {
235            None
236        }
237    }
238
239    fn field(&self, field_idx: usize) -> Option<WitNodePointer<'a>> {
240        if let WitNode::RecordValue(fields) = self.node() {
241            fields
242                .get(field_idx)
243                .map(|idx| WitNodePointer::new(self.value, *idx as usize))
244        } else {
245            None
246        }
247    }
248
249    fn variant(&self) -> Option<(u32, Option<WitNodePointer<'a>>)> {
250        if let WitNode::VariantValue((case, value)) = self.node() {
251            let value = value.map(|idx| WitNodePointer::new(self.value, idx as usize));
252            Some((*case, value))
253        } else {
254            None
255        }
256    }
257
258    fn enum_value(&self) -> Option<u32> {
259        if let WitNode::EnumValue(value) = self.node() {
260            Some(*value)
261        } else {
262            None
263        }
264    }
265
266    fn flags(&self) -> Option<&'a [bool]> {
267        if let WitNode::FlagsValue(value) = self.node() {
268            Some(value)
269        } else {
270            None
271        }
272    }
273
274    fn tuple_element(&self, element_idx: usize) -> Option<WitNodePointer<'a>> {
275        if let WitNode::TupleValue(elements) = self.node() {
276            elements
277                .get(element_idx)
278                .map(|idx| WitNodePointer::new(self.value, *idx as usize))
279        } else {
280            None
281        }
282    }
283
284    fn list_elements<R>(&self, f: impl Fn(WitNodePointer<'a>) -> R) -> Option<Vec<R>> {
285        if let WitNode::ListValue(elements) = self.node() {
286            Some(
287                elements
288                    .iter()
289                    .map(|idx| f(WitNodePointer::new(self.value, *idx as usize)))
290                    .collect(),
291            )
292        } else {
293            None
294        }
295    }
296
297    fn option(&self) -> Option<Option<WitNodePointer<'a>>> {
298        if let WitNode::OptionValue(value) = self.node() {
299            Some(value.map(|idx| WitNodePointer::new(self.value, idx as usize)))
300        } else {
301            None
302        }
303    }
304
305    fn result(&self) -> Option<Result<Option<WitNodePointer<'a>>, Option<WitNodePointer<'a>>>> {
306        if let WitNode::ResultValue(value) = self.node() {
307            Some(match value {
308                Ok(idx) => Ok(idx.map(|idx| WitNodePointer::new(self.value, idx as usize))),
309                Err(idx) => Err(idx.map(|idx| WitNodePointer::new(self.value, idx as usize))),
310            })
311        } else {
312            None
313        }
314    }
315
316    fn handle(&self) -> Option<(Uri, u64)> {
317        if let WitNode::Handle((uri, idx)) = self.node() {
318            Some((uri.clone(), *idx))
319        } else {
320            None
321        }
322    }
323}
324
325impl<'a, 'b> WitValueExtractor<'a, 'b> for WitNodePointer<'b> {
326    fn u8(&'a self) -> Option<u8> {
327        self.u8()
328    }
329
330    fn u16(&'a self) -> Option<u16> {
331        self.u16()
332    }
333
334    fn u32(&'a self) -> Option<u32> {
335        self.u32()
336    }
337
338    fn u64(&'a self) -> Option<u64> {
339        self.u64()
340    }
341
342    fn s8(&'a self) -> Option<i8> {
343        self.s8()
344    }
345
346    fn s16(&'a self) -> Option<i16> {
347        self.s16()
348    }
349
350    fn s32(&'a self) -> Option<i32> {
351        self.s32()
352    }
353
354    fn s64(&'a self) -> Option<i64> {
355        self.s64()
356    }
357
358    fn f32(&'a self) -> Option<f32> {
359        self.f32()
360    }
361
362    fn f64(&'a self) -> Option<f64> {
363        self.f64()
364    }
365
366    fn char(&'a self) -> Option<char> {
367        self.char()
368    }
369
370    fn bool(&'a self) -> Option<bool> {
371        self.bool()
372    }
373
374    fn string(&'a self) -> Option<&'b str> {
375        self.string()
376    }
377
378    fn field(&'a self, field_idx: usize) -> Option<WitNodePointer<'b>> {
379        self.field(field_idx)
380    }
381
382    fn variant(&'a self) -> Option<(u32, Option<WitNodePointer<'b>>)> {
383        self.variant()
384    }
385
386    fn enum_value(&'a self) -> Option<u32> {
387        self.enum_value()
388    }
389
390    fn flags(&'a self) -> Option<&'b [bool]> {
391        self.flags()
392    }
393
394    fn tuple_element(&'a self, element_idx: usize) -> Option<WitNodePointer<'b>> {
395        self.tuple_element(element_idx)
396    }
397
398    fn list_elements<R>(&'a self, f: impl Fn(WitNodePointer<'b>) -> R) -> Option<Vec<R>> {
399        self.list_elements(f)
400    }
401
402    fn option(&'a self) -> Option<Option<WitNodePointer<'b>>> {
403        self.option()
404    }
405
406    fn result(&'a self) -> Option<Result<Option<WitNodePointer<'b>>, Option<WitNodePointer<'b>>>> {
407        self.result()
408    }
409
410    fn handle(&'a self) -> Option<(Uri, u64)> {
411        self.handle()
412    }
413}
414
415#[cfg(test)]
416mod tests {
417    use test_r::test;
418
419    use crate::*;
420
421    #[test]
422    fn primitive() {
423        let value = WitValue::builder().s32(42);
424        assert_eq!(value.s32(), Some(42));
425    }
426
427    #[test]
428    fn single_record() {
429        let value = WitValue::builder()
430            .record()
431            .item()
432            .u8(1)
433            .item()
434            .enum_value(2)
435            .item()
436            .flags(vec![true, false, true])
437            .finish();
438        assert_eq!(value.field(0).unwrap().u8(), Some(1));
439        assert_eq!(value.field(1).unwrap().enum_value(), Some(2));
440        assert_eq!(
441            value.field(2).unwrap().flags().unwrap(),
442            &[true, false, true]
443        );
444    }
445
446    #[test]
447    fn single_record_generic() {
448        fn u8_field<'a, 'b>(extractor: &'a impl WitValueExtractor<'a, 'b>) -> Option<u8> {
449            extractor.u8()
450        }
451
452        let value = WitValue::builder()
453            .record()
454            .item()
455            .u8(1)
456            .item()
457            .enum_value(2)
458            .item()
459            .flags(vec![true, false, true])
460            .finish();
461        assert_eq!(u8_field(&value.field(0).unwrap()), Some(1));
462        assert_eq!(value.field(1).unwrap().enum_value(), Some(2));
463        assert_eq!(
464            value.field(2).unwrap().flags().unwrap(),
465            &[true, false, true]
466        );
467    }
468
469    #[test]
470    fn deep_record() {
471        let value = WitValue::builder()
472            .record()
473            .item()
474            .record()
475            .item()
476            .s32(10)
477            .item()
478            .string("hello")
479            .finish()
480            .finish();
481
482        let inner = value.field(0).unwrap();
483
484        assert_eq!(inner.field(0).unwrap().s32(), Some(10));
485        assert_eq!(inner.field(1).unwrap().string(), Some("hello"));
486    }
487
488    #[test]
489    fn variant1() {
490        let value = WitValue::builder().variant(2).s32(42).finish();
491        assert_eq!(value.variant().unwrap().0, 2);
492        assert_eq!(value.variant().unwrap().1.unwrap().s32(), Some(42));
493    }
494
495    #[test]
496    fn variant2() {
497        let value = WitValue::builder().variant_unit(0);
498        assert_eq!(value.variant().unwrap().0, 0);
499        assert!(value.variant().unwrap().1.is_none());
500    }
501
502    #[test]
503    fn enum1() {
504        let value = WitValue::builder().enum_value(2);
505        assert_eq!(value.enum_value(), Some(2));
506    }
507
508    #[test]
509    fn flags() {
510        let value = WitValue::builder().flags(vec![true, false, true]);
511        assert_eq!(value.flags().unwrap(), &[true, false, true]);
512    }
513
514    #[test]
515    fn tuple() {
516        let value = WitValue::builder()
517            .tuple()
518            .item()
519            .s32(42)
520            .item()
521            .string("hello")
522            .item()
523            .record()
524            .item()
525            .string("world")
526            .finish()
527            .finish();
528        assert_eq!(value.tuple_element(0).unwrap().s32(), Some(42));
529        assert_eq!(value.tuple_element(1).unwrap().string(), Some("hello"));
530        assert_eq!(
531            value.tuple_element(2).unwrap().field(0).unwrap().string(),
532            Some("world")
533        );
534    }
535
536    #[test]
537    fn list() {
538        let value =
539            WitValue::builder().list_fn(&[1, 2, 3, 4], |n, item_builder| item_builder.s32(*n));
540
541        assert_eq!(
542            value.list_elements(|v| v.s32().unwrap()).unwrap(),
543            vec![1, 2, 3, 4]
544        );
545    }
546
547    #[test]
548    fn option1() {
549        let value = WitValue::builder().option_none();
550        assert!(value.option().unwrap().is_none());
551    }
552
553    #[test]
554    fn option2() {
555        let value = WitValue::builder().option_some().s32(42).finish();
556        assert_eq!(value.option().unwrap().unwrap().s32(), Some(42));
557    }
558
559    #[test]
560    fn result1() {
561        let value = WitValue::builder().result_ok().s32(42).finish();
562        assert_eq!(
563            value.result().unwrap().ok().unwrap().unwrap().s32(),
564            Some(42)
565        );
566    }
567
568    #[test]
569    fn result2() {
570        let value = WitValue::builder().result_err().s32(42).finish();
571        assert_eq!(
572            value.result().unwrap().err().unwrap().unwrap().s32(),
573            Some(42)
574        );
575    }
576
577    #[test]
578    fn result3() {
579        let value = WitValue::builder().result_ok_unit();
580        assert!(value.result().unwrap().ok().unwrap().is_none());
581    }
582
583    #[test]
584    fn result4() {
585        let value = WitValue::builder().result_err_unit();
586        assert!(value.result().unwrap().err().unwrap().is_none());
587    }
588
589    #[test]
590    fn handle() {
591        let value = WitValue::builder().handle(
592            Uri {
593                value: "wit://test".to_string(),
594            },
595            42,
596        );
597        assert_eq!(
598            value.handle().unwrap(),
599            (
600                Uri {
601                    value: "wit://test".to_string()
602                },
603                42
604            )
605        );
606    }
607
608    #[test]
609    fn extraction_is_composable() {
610        // (42, "hello", { "world" })
611        let value = WitValue::builder()
612            .tuple()
613            .item()
614            .s32(42)
615            .item()
616            .string("hello")
617            .item()
618            .record()
619            .item()
620            .string("world")
621            .finish()
622            .finish();
623
624        let world = value
625            .tuple_element(2)
626            .unwrap()
627            .field(0)
628            .unwrap()
629            .string()
630            .unwrap();
631        assert_eq!(world, "world");
632    }
633
634    #[test]
635    fn extraction_is_composable_using_flags() {
636        // (42, "hello", { `101` })
637        let value = WitValue::builder()
638            .tuple()
639            .item()
640            .s32(42)
641            .item()
642            .string("hello")
643            .item()
644            .record()
645            .item()
646            .flags(vec![true, false, true])
647            .finish()
648            .finish();
649
650        let flags = value
651            .tuple_element(2)
652            .map(|record| record.field(0).unwrap().flags().unwrap())
653            .unwrap();
654
655        if flags[0] {
656            println!("Flag 0 is set");
657        }
658
659        assert!(flags[0]);
660        assert!(!flags[1]);
661        assert!(flags[2]);
662    }
663}