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 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 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}