wast/component/
func.rs

1use crate::component::*;
2use crate::kw;
3use crate::parser::{Cursor, Lookahead1, Parse, Parser, Peek, Result};
4use crate::token::{Id, Index, LParen, NameAnnotation, Span};
5
6/// A declared core function.
7///
8/// This is a member of both the core alias and canon sections.
9#[derive(Debug)]
10pub struct CoreFunc<'a> {
11    /// Where this `core func` was defined.
12    pub span: Span,
13    /// An identifier that this function is resolved with (optionally) for name
14    /// resolution.
15    pub id: Option<Id<'a>>,
16    /// An optional name for this function stored in the custom `name` section.
17    pub name: Option<NameAnnotation<'a>>,
18    /// The kind of core function.
19    pub kind: CoreFuncKind<'a>,
20}
21
22impl<'a> Parse<'a> for CoreFunc<'a> {
23    fn parse(parser: Parser<'a>) -> Result<Self> {
24        let span = parser.parse::<kw::core>()?.0;
25        parser.parse::<kw::func>()?;
26        let id = parser.parse()?;
27        let name = parser.parse()?;
28        let kind = parser.parens(|p| p.parse())?;
29
30        Ok(Self {
31            span,
32            id,
33            name,
34            kind,
35        })
36    }
37}
38
39/// Represents the kind of core functions.
40#[derive(Debug)]
41#[allow(missing_docs)]
42pub enum CoreFuncKind<'a> {
43    /// The core function is defined in terms of lowering a component function.
44    ///
45    /// The core function is actually a member of the canon section.
46    Lower(CanonLower<'a>),
47    /// The core function is defined in terms of aliasing a module instance export.
48    ///
49    /// The core function is actually a member of the core alias section.
50    Alias(InlineExportAlias<'a, true>),
51    ResourceNew(CanonResourceNew<'a>),
52    ResourceDrop(CanonResourceDrop<'a>),
53    ResourceRep(CanonResourceRep<'a>),
54    ThreadSpawnRef(CanonThreadSpawnRef<'a>),
55    ThreadSpawnIndirect(CanonThreadSpawnIndirect<'a>),
56    ThreadAvailableParallelism(CanonThreadAvailableParallelism),
57    BackpressureSet,
58    TaskReturn(CanonTaskReturn<'a>),
59    ContextGet(u32),
60    ContextSet(u32),
61    Yield(CanonYield),
62    SubtaskDrop,
63    StreamNew(CanonStreamNew<'a>),
64    StreamRead(CanonStreamRead<'a>),
65    StreamWrite(CanonStreamWrite<'a>),
66    StreamCancelRead(CanonStreamCancelRead<'a>),
67    StreamCancelWrite(CanonStreamCancelWrite<'a>),
68    StreamCloseReadable(CanonStreamCloseReadable<'a>),
69    StreamCloseWritable(CanonStreamCloseWritable<'a>),
70    FutureNew(CanonFutureNew<'a>),
71    FutureRead(CanonFutureRead<'a>),
72    FutureWrite(CanonFutureWrite<'a>),
73    FutureCancelRead(CanonFutureCancelRead<'a>),
74    FutureCancelWrite(CanonFutureCancelWrite<'a>),
75    FutureCloseReadable(CanonFutureCloseReadable<'a>),
76    FutureCloseWritable(CanonFutureCloseWritable<'a>),
77    ErrorContextNew(CanonErrorContextNew<'a>),
78    ErrorContextDebugMessage(CanonErrorContextDebugMessage<'a>),
79    ErrorContextDrop,
80    WaitableSetNew,
81    WaitableSetWait(CanonWaitableSetWait<'a>),
82    WaitableSetPoll(CanonWaitableSetPoll<'a>),
83    WaitableSetDrop,
84    WaitableJoin,
85}
86
87impl<'a> Parse<'a> for CoreFuncKind<'a> {
88    fn parse(parser: Parser<'a>) -> Result<Self> {
89        let mut l = parser.lookahead1();
90        if l.peek::<kw::canon>()? {
91            parser.parse::<kw::canon>()?;
92        } else if l.peek::<kw::alias>()? {
93            return Ok(Self::Alias(parser.parse()?));
94        } else {
95            return Err(l.error());
96        }
97
98        CoreFuncKind::parse_lookahead(parser.lookahead1())
99    }
100}
101
102impl<'a> CoreFuncKind<'a> {
103    fn parse_lookahead(mut l: Lookahead1<'a>) -> Result<CoreFuncKind<'a>> {
104        let parser = l.parser();
105        if l.peek::<kw::lower>()? {
106            Ok(CoreFuncKind::Lower(parser.parse()?))
107        } else if l.peek::<kw::resource_new>()? {
108            Ok(CoreFuncKind::ResourceNew(parser.parse()?))
109        } else if l.peek::<kw::resource_drop>()? {
110            Ok(CoreFuncKind::ResourceDrop(parser.parse()?))
111        } else if l.peek::<kw::resource_rep>()? {
112            Ok(CoreFuncKind::ResourceRep(parser.parse()?))
113        } else if l.peek::<kw::thread_spawn_ref>()? {
114            Ok(CoreFuncKind::ThreadSpawnRef(parser.parse()?))
115        } else if l.peek::<kw::thread_spawn_indirect>()? {
116            Ok(CoreFuncKind::ThreadSpawnIndirect(parser.parse()?))
117        } else if l.peek::<kw::thread_available_parallelism>()? {
118            Ok(CoreFuncKind::ThreadAvailableParallelism(parser.parse()?))
119        } else if l.peek::<kw::backpressure_set>()? {
120            parser.parse::<kw::backpressure_set>()?;
121            Ok(CoreFuncKind::BackpressureSet)
122        } else if l.peek::<kw::task_return>()? {
123            Ok(CoreFuncKind::TaskReturn(parser.parse()?))
124        } else if l.peek::<kw::context_get>()? {
125            parser.parse::<kw::context_get>()?;
126            parser.parse::<kw::i32>()?;
127            Ok(CoreFuncKind::ContextGet(parser.parse()?))
128        } else if l.peek::<kw::context_set>()? {
129            parser.parse::<kw::context_set>()?;
130            parser.parse::<kw::i32>()?;
131            Ok(CoreFuncKind::ContextSet(parser.parse()?))
132        } else if l.peek::<kw::yield_>()? {
133            Ok(CoreFuncKind::Yield(parser.parse()?))
134        } else if l.peek::<kw::subtask_drop>()? {
135            parser.parse::<kw::subtask_drop>()?;
136            Ok(CoreFuncKind::SubtaskDrop)
137        } else if l.peek::<kw::stream_new>()? {
138            Ok(CoreFuncKind::StreamNew(parser.parse()?))
139        } else if l.peek::<kw::stream_read>()? {
140            Ok(CoreFuncKind::StreamRead(parser.parse()?))
141        } else if l.peek::<kw::stream_write>()? {
142            Ok(CoreFuncKind::StreamWrite(parser.parse()?))
143        } else if l.peek::<kw::stream_cancel_read>()? {
144            Ok(CoreFuncKind::StreamCancelRead(parser.parse()?))
145        } else if l.peek::<kw::stream_cancel_write>()? {
146            Ok(CoreFuncKind::StreamCancelWrite(parser.parse()?))
147        } else if l.peek::<kw::stream_close_readable>()? {
148            Ok(CoreFuncKind::StreamCloseReadable(parser.parse()?))
149        } else if l.peek::<kw::stream_close_writable>()? {
150            Ok(CoreFuncKind::StreamCloseWritable(parser.parse()?))
151        } else if l.peek::<kw::future_new>()? {
152            Ok(CoreFuncKind::FutureNew(parser.parse()?))
153        } else if l.peek::<kw::future_read>()? {
154            Ok(CoreFuncKind::FutureRead(parser.parse()?))
155        } else if l.peek::<kw::future_write>()? {
156            Ok(CoreFuncKind::FutureWrite(parser.parse()?))
157        } else if l.peek::<kw::future_cancel_read>()? {
158            Ok(CoreFuncKind::FutureCancelRead(parser.parse()?))
159        } else if l.peek::<kw::future_cancel_write>()? {
160            Ok(CoreFuncKind::FutureCancelWrite(parser.parse()?))
161        } else if l.peek::<kw::future_close_readable>()? {
162            Ok(CoreFuncKind::FutureCloseReadable(parser.parse()?))
163        } else if l.peek::<kw::future_close_writable>()? {
164            Ok(CoreFuncKind::FutureCloseWritable(parser.parse()?))
165        } else if l.peek::<kw::error_context_new>()? {
166            Ok(CoreFuncKind::ErrorContextNew(parser.parse()?))
167        } else if l.peek::<kw::error_context_debug_message>()? {
168            Ok(CoreFuncKind::ErrorContextDebugMessage(parser.parse()?))
169        } else if l.peek::<kw::error_context_drop>()? {
170            parser.parse::<kw::error_context_drop>()?;
171            Ok(CoreFuncKind::ErrorContextDrop)
172        } else if l.peek::<kw::waitable_set_new>()? {
173            parser.parse::<kw::waitable_set_new>()?;
174            Ok(CoreFuncKind::WaitableSetNew)
175        } else if l.peek::<kw::waitable_set_wait>()? {
176            Ok(CoreFuncKind::WaitableSetWait(parser.parse()?))
177        } else if l.peek::<kw::waitable_set_poll>()? {
178            Ok(CoreFuncKind::WaitableSetPoll(parser.parse()?))
179        } else if l.peek::<kw::waitable_set_drop>()? {
180            parser.parse::<kw::waitable_set_drop>()?;
181            Ok(CoreFuncKind::WaitableSetDrop)
182        } else if l.peek::<kw::waitable_join>()? {
183            parser.parse::<kw::waitable_join>()?;
184            Ok(CoreFuncKind::WaitableJoin)
185        } else {
186            Err(l.error())
187        }
188    }
189}
190
191/// A declared component function.
192///
193/// This may be a member of the import, alias, or canon sections.
194#[derive(Debug)]
195pub struct Func<'a> {
196    /// Where this `func` was defined.
197    pub span: Span,
198    /// An identifier that this function is resolved with (optionally) for name
199    /// resolution.
200    pub id: Option<Id<'a>>,
201    /// An optional name for this function stored in the custom `name` section.
202    pub name: Option<NameAnnotation<'a>>,
203    /// If present, inline export annotations which indicate names this
204    /// definition should be exported under.
205    pub exports: InlineExport<'a>,
206    /// The kind of function.
207    pub kind: FuncKind<'a>,
208}
209
210impl<'a> Parse<'a> for Func<'a> {
211    fn parse(parser: Parser<'a>) -> Result<Self> {
212        let span = parser.parse::<kw::func>()?.0;
213        let id = parser.parse()?;
214        let name = parser.parse()?;
215        let exports = parser.parse()?;
216        let kind = parser.parse()?;
217
218        Ok(Self {
219            span,
220            id,
221            name,
222            exports,
223            kind,
224        })
225    }
226}
227
228/// Represents the kind of component functions.
229#[derive(Debug)]
230pub enum FuncKind<'a> {
231    /// A function which is actually defined as an import, such as:
232    ///
233    /// ```text
234    /// (func (import "foo") (param string))
235    /// ```
236    Import {
237        /// The import name of this import.
238        import: InlineImport<'a>,
239        /// The type that this function will have.
240        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
241    },
242    /// The function is defined in terms of lifting a core function.
243    ///
244    /// The function is actually a member of the canon section.
245    Lift {
246        /// The lifted function's type.
247        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
248        /// Information relating to the lifting of the core function.
249        info: CanonLift<'a>,
250    },
251    /// The function is defined in terms of aliasing a component instance export.
252    ///
253    /// The function is actually a member of the alias section.
254    Alias(InlineExportAlias<'a, false>),
255}
256
257impl<'a> Parse<'a> for FuncKind<'a> {
258    fn parse(parser: Parser<'a>) -> Result<Self> {
259        if let Some(import) = parser.parse()? {
260            Ok(Self::Import {
261                import,
262                ty: parser.parse()?,
263            })
264        } else if parser.peek::<LParen>()? && parser.peek2::<kw::alias>()? {
265            parser.parens(|parser| Ok(Self::Alias(parser.parse()?)))
266        } else {
267            Ok(Self::Lift {
268                ty: parser.parse()?,
269                info: parser.parens(|parser| {
270                    parser.parse::<kw::canon>()?;
271                    parser.parse()
272                })?,
273            })
274        }
275    }
276}
277
278/// A WebAssembly canonical function to be inserted into a component.
279///
280/// This is a member of the canonical section.
281#[derive(Debug)]
282pub struct CanonicalFunc<'a> {
283    /// Where this `func` was defined.
284    pub span: Span,
285    /// An identifier that this function is resolved with (optionally) for name
286    /// resolution.
287    pub id: Option<Id<'a>>,
288    /// An optional name for this function stored in the custom `name` section.
289    pub name: Option<NameAnnotation<'a>>,
290    /// What kind of function this is, be it a lowered or lifted function.
291    pub kind: CanonicalFuncKind<'a>,
292}
293
294impl<'a> Parse<'a> for CanonicalFunc<'a> {
295    fn parse(parser: Parser<'a>) -> Result<Self> {
296        let span = parser.parse::<kw::canon>()?.0;
297        let mut l = parser.lookahead1();
298
299        if l.peek::<kw::lift>()? {
300            let info = parser.parse()?;
301            let (id, name, ty) = parser.parens(|parser| {
302                parser.parse::<kw::func>()?;
303                let id = parser.parse()?;
304                let name = parser.parse()?;
305                let ty = parser.parse()?;
306                Ok((id, name, ty))
307            })?;
308
309            Ok(Self {
310                span,
311                id,
312                name,
313                kind: CanonicalFuncKind::Lift { info, ty },
314            })
315        } else {
316            let kind = CoreFuncKind::parse_lookahead(l)?;
317            let (id, name) = parser.parens(|parser| {
318                parser.parse::<kw::core>()?;
319                parser.parse::<kw::func>()?;
320                let id = parser.parse()?;
321                let name = parser.parse()?;
322                Ok((id, name))
323            })?;
324
325            Ok(Self {
326                span,
327                id,
328                name,
329                kind: CanonicalFuncKind::Core(kind),
330            })
331        }
332    }
333}
334
335/// Possible ways to define a canonical function in the text format.
336#[derive(Debug)]
337#[allow(missing_docs)]
338pub enum CanonicalFuncKind<'a> {
339    /// A canonical function that is defined in terms of lifting a core function.
340    Lift {
341        /// The lifted function's type.
342        ty: ComponentTypeUse<'a, ComponentFunctionType<'a>>,
343        /// Information relating to the lifting of the core function.
344        info: CanonLift<'a>,
345    },
346
347    /// A canonical function that defines a core function, whose variants are
348    /// delegated to `CoreFuncKind`.
349    Core(CoreFuncKind<'a>),
350}
351
352/// Information relating to lifting a core function.
353#[derive(Debug)]
354pub struct CanonLift<'a> {
355    /// The core function being lifted.
356    pub func: CoreItemRef<'a, kw::func>,
357    /// The canonical options for the lifting.
358    pub opts: Vec<CanonOpt<'a>>,
359}
360
361impl<'a> Parse<'a> for CanonLift<'a> {
362    fn parse(parser: Parser<'a>) -> Result<Self> {
363        parser.parse::<kw::lift>()?;
364
365        Ok(Self {
366            func: parser.parens(|parser| {
367                parser.parse::<kw::core>()?;
368                parser.parse()
369            })?,
370            opts: parser.parse()?,
371        })
372    }
373}
374
375impl Default for CanonLift<'_> {
376    fn default() -> Self {
377        let span = Span::from_offset(0);
378        Self {
379            func: CoreItemRef {
380                kind: kw::func(span),
381                idx: Index::Num(0, span),
382                export_name: None,
383            },
384            opts: Vec::new(),
385        }
386    }
387}
388
389/// Information relating to lowering a component function.
390#[derive(Debug)]
391pub struct CanonLower<'a> {
392    /// The function being lowered.
393    pub func: ItemRef<'a, kw::func>,
394    /// The canonical options for the lowering.
395    pub opts: Vec<CanonOpt<'a>>,
396}
397
398impl<'a> Parse<'a> for CanonLower<'a> {
399    fn parse(parser: Parser<'a>) -> Result<Self> {
400        parser.parse::<kw::lower>()?;
401
402        Ok(Self {
403            func: parser.parens(|parser| parser.parse())?,
404            opts: parser.parse()?,
405        })
406    }
407}
408
409impl Default for CanonLower<'_> {
410    fn default() -> Self {
411        let span = Span::from_offset(0);
412        Self {
413            func: ItemRef {
414                kind: kw::func(span),
415                idx: Index::Num(0, span),
416                export_names: Vec::new(),
417            },
418            opts: Vec::new(),
419        }
420    }
421}
422
423/// Information relating to the `resource.new` intrinsic.
424#[derive(Debug)]
425pub struct CanonResourceNew<'a> {
426    /// The resource type that this intrinsic creates an owned reference to.
427    pub ty: Index<'a>,
428}
429
430impl<'a> Parse<'a> for CanonResourceNew<'a> {
431    fn parse(parser: Parser<'a>) -> Result<Self> {
432        parser.parse::<kw::resource_new>()?;
433
434        Ok(Self {
435            ty: parser.parse()?,
436        })
437    }
438}
439
440/// Information relating to the `resource.drop` intrinsic.
441#[derive(Debug)]
442pub struct CanonResourceDrop<'a> {
443    /// The resource type that this intrinsic is dropping.
444    pub ty: Index<'a>,
445    /// Whether or not this function is async
446    pub async_: bool,
447}
448
449impl<'a> Parse<'a> for CanonResourceDrop<'a> {
450    fn parse(parser: Parser<'a>) -> Result<Self> {
451        parser.parse::<kw::resource_drop>()?;
452
453        Ok(Self {
454            ty: parser.parse()?,
455            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
456        })
457    }
458}
459
460/// Information relating to the `resource.rep` intrinsic.
461#[derive(Debug)]
462pub struct CanonResourceRep<'a> {
463    /// The resource type that this intrinsic is accessing.
464    pub ty: Index<'a>,
465}
466
467impl<'a> Parse<'a> for CanonResourceRep<'a> {
468    fn parse(parser: Parser<'a>) -> Result<Self> {
469        parser.parse::<kw::resource_rep>()?;
470
471        Ok(Self {
472            ty: parser.parse()?,
473        })
474    }
475}
476
477/// Information relating to the `thread.spawn_ref` intrinsic.
478#[derive(Debug)]
479pub struct CanonThreadSpawnRef<'a> {
480    /// The function type that is being spawned.
481    pub ty: Index<'a>,
482}
483
484impl<'a> Parse<'a> for CanonThreadSpawnRef<'a> {
485    fn parse(parser: Parser<'a>) -> Result<Self> {
486        parser.parse::<kw::thread_spawn_ref>()?;
487
488        Ok(Self {
489            ty: parser.parse()?,
490        })
491    }
492}
493
494/// Information relating to the `thread.spawn_indirect` intrinsic.
495///
496/// This should look quite similar to parsing of `CallIndirect`.
497#[derive(Debug)]
498pub struct CanonThreadSpawnIndirect<'a> {
499    /// The function type that is being spawned.
500    pub ty: Index<'a>,
501    /// The table that this spawn is going to be indexing.
502    pub table: CoreItemRef<'a, kw::table>,
503}
504
505impl<'a> Parse<'a> for CanonThreadSpawnIndirect<'a> {
506    fn parse(parser: Parser<'a>) -> Result<Self> {
507        parser.parse::<kw::thread_spawn_indirect>()?;
508        let ty = parser.parse()?;
509        let table = parser.parens(|p| p.parse())?;
510        Ok(Self { ty, table })
511    }
512}
513
514/// Information relating to the `thread.spawn` intrinsic.
515#[derive(Debug)]
516pub struct CanonThreadAvailableParallelism;
517
518impl<'a> Parse<'a> for CanonThreadAvailableParallelism {
519    fn parse(parser: Parser<'a>) -> Result<Self> {
520        parser.parse::<kw::thread_available_parallelism>()?;
521        Ok(Self)
522    }
523}
524
525/// Information relating to the `task.return` intrinsic.
526#[derive(Debug)]
527pub struct CanonTaskReturn<'a> {
528    /// The type of the result which may be returned with this intrinsic.
529    pub result: Option<ComponentValType<'a>>,
530    /// The canonical options for storing values.
531    pub opts: Vec<CanonOpt<'a>>,
532}
533
534impl<'a> Parse<'a> for CanonTaskReturn<'a> {
535    fn parse(parser: Parser<'a>) -> Result<Self> {
536        parser.parse::<kw::task_return>()?;
537
538        Ok(Self {
539            result: if parser.peek2::<kw::result>()? {
540                Some(parser.parens(|p| {
541                    p.parse::<kw::result>()?.0;
542                    p.parse()
543                })?)
544            } else {
545                None
546            },
547            opts: parser.parse()?,
548        })
549    }
550}
551
552/// Information relating to the `waitable-set.wait` intrinsic.
553#[derive(Debug)]
554pub struct CanonWaitableSetWait<'a> {
555    /// If true, the component instance may be reentered during a call to this
556    /// intrinsic.
557    pub async_: bool,
558    /// The memory to use when returning an event to the caller.
559    pub memory: CoreItemRef<'a, kw::memory>,
560}
561
562impl<'a> Parse<'a> for CanonWaitableSetWait<'a> {
563    fn parse(parser: Parser<'a>) -> Result<Self> {
564        parser.parse::<kw::waitable_set_wait>()?;
565        let async_ = parser.parse::<Option<kw::r#async>>()?.is_some();
566        let memory = parser.parens(|p| p.parse())?;
567
568        Ok(Self { async_, memory })
569    }
570}
571
572/// Information relating to the `waitable-set.poll` intrinsic.
573#[derive(Debug)]
574pub struct CanonWaitableSetPoll<'a> {
575    /// If true, the component instance may be reentered during a call to this
576    /// intrinsic.
577    pub async_: bool,
578    /// The memory to use when returning an event to the caller.
579    pub memory: CoreItemRef<'a, kw::memory>,
580}
581
582impl<'a> Parse<'a> for CanonWaitableSetPoll<'a> {
583    fn parse(parser: Parser<'a>) -> Result<Self> {
584        parser.parse::<kw::waitable_set_poll>()?;
585        let async_ = parser.parse::<Option<kw::r#async>>()?.is_some();
586        let memory = parser.parens(|p| p.parse())?;
587
588        Ok(Self { async_, memory })
589    }
590}
591
592/// Information relating to the `task.yield` intrinsic.
593#[derive(Debug)]
594pub struct CanonYield {
595    /// If true, the component instance may be reentered during a call to this
596    /// intrinsic.
597    pub async_: bool,
598}
599
600impl<'a> Parse<'a> for CanonYield {
601    fn parse(parser: Parser<'a>) -> Result<Self> {
602        parser.parse::<kw::yield_>()?;
603        let async_ = parser.parse::<Option<kw::r#async>>()?.is_some();
604
605        Ok(Self { async_ })
606    }
607}
608
609/// Information relating to the `stream.new` intrinsic.
610#[derive(Debug)]
611pub struct CanonStreamNew<'a> {
612    /// The stream type to instantiate.
613    pub ty: Index<'a>,
614}
615
616impl<'a> Parse<'a> for CanonStreamNew<'a> {
617    fn parse(parser: Parser<'a>) -> Result<Self> {
618        parser.parse::<kw::stream_new>()?;
619
620        Ok(Self {
621            ty: parser.parse()?,
622        })
623    }
624}
625
626/// Information relating to the `stream.read` intrinsic.
627#[derive(Debug)]
628pub struct CanonStreamRead<'a> {
629    /// The stream type to instantiate.
630    pub ty: Index<'a>,
631    /// The canonical options for storing values.
632    pub opts: Vec<CanonOpt<'a>>,
633}
634
635impl<'a> Parse<'a> for CanonStreamRead<'a> {
636    fn parse(parser: Parser<'a>) -> Result<Self> {
637        parser.parse::<kw::stream_read>()?;
638
639        Ok(Self {
640            ty: parser.parse()?,
641            opts: parser.parse()?,
642        })
643    }
644}
645
646/// Information relating to the `stream.write` intrinsic.
647#[derive(Debug)]
648pub struct CanonStreamWrite<'a> {
649    /// The stream type to instantiate.
650    pub ty: Index<'a>,
651    /// The canonical options for loading values.
652    pub opts: Vec<CanonOpt<'a>>,
653}
654
655impl<'a> Parse<'a> for CanonStreamWrite<'a> {
656    fn parse(parser: Parser<'a>) -> Result<Self> {
657        parser.parse::<kw::stream_write>()?;
658
659        Ok(Self {
660            ty: parser.parse()?,
661            opts: parser.parse()?,
662        })
663    }
664}
665
666/// Information relating to the `stream.cancel-read` intrinsic.
667#[derive(Debug)]
668pub struct CanonStreamCancelRead<'a> {
669    /// The stream type to instantiate.
670    pub ty: Index<'a>,
671    /// If false, block until cancel is finished; otherwise return BLOCKED if
672    /// necessary.
673    pub async_: bool,
674}
675
676impl<'a> Parse<'a> for CanonStreamCancelRead<'a> {
677    fn parse(parser: Parser<'a>) -> Result<Self> {
678        parser.parse::<kw::stream_cancel_read>()?;
679
680        Ok(Self {
681            ty: parser.parse()?,
682            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
683        })
684    }
685}
686
687/// Information relating to the `stream.cancel-write` intrinsic.
688#[derive(Debug)]
689pub struct CanonStreamCancelWrite<'a> {
690    /// The stream type to instantiate.
691    pub ty: Index<'a>,
692    /// If false, block until cancel is finished; otherwise return BLOCKED if
693    /// necessary.
694    pub async_: bool,
695}
696
697impl<'a> Parse<'a> for CanonStreamCancelWrite<'a> {
698    fn parse(parser: Parser<'a>) -> Result<Self> {
699        parser.parse::<kw::stream_cancel_write>()?;
700
701        Ok(Self {
702            ty: parser.parse()?,
703            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
704        })
705    }
706}
707
708/// Information relating to the `stream.close-readable` intrinsic.
709#[derive(Debug)]
710pub struct CanonStreamCloseReadable<'a> {
711    /// The stream type to close.
712    pub ty: Index<'a>,
713}
714
715impl<'a> Parse<'a> for CanonStreamCloseReadable<'a> {
716    fn parse(parser: Parser<'a>) -> Result<Self> {
717        parser.parse::<kw::stream_close_readable>()?;
718
719        Ok(Self {
720            ty: parser.parse()?,
721        })
722    }
723}
724
725/// Information relating to the `stream.close-writable` intrinsic.
726#[derive(Debug)]
727pub struct CanonStreamCloseWritable<'a> {
728    /// The stream type to close.
729    pub ty: Index<'a>,
730}
731
732impl<'a> Parse<'a> for CanonStreamCloseWritable<'a> {
733    fn parse(parser: Parser<'a>) -> Result<Self> {
734        parser.parse::<kw::stream_close_writable>()?;
735
736        Ok(Self {
737            ty: parser.parse()?,
738        })
739    }
740}
741
742/// Information relating to the `future.new` intrinsic.
743#[derive(Debug)]
744pub struct CanonFutureNew<'a> {
745    /// The future type to instantiate.
746    pub ty: Index<'a>,
747}
748
749impl<'a> Parse<'a> for CanonFutureNew<'a> {
750    fn parse(parser: Parser<'a>) -> Result<Self> {
751        parser.parse::<kw::future_new>()?;
752
753        Ok(Self {
754            ty: parser.parse()?,
755        })
756    }
757}
758
759/// Information relating to the `future.read` intrinsic.
760#[derive(Debug)]
761pub struct CanonFutureRead<'a> {
762    /// The future type to instantiate.
763    pub ty: Index<'a>,
764    /// The canonical options for storing values.
765    pub opts: Vec<CanonOpt<'a>>,
766}
767
768impl<'a> Parse<'a> for CanonFutureRead<'a> {
769    fn parse(parser: Parser<'a>) -> Result<Self> {
770        parser.parse::<kw::future_read>()?;
771
772        Ok(Self {
773            ty: parser.parse()?,
774            opts: parser.parse()?,
775        })
776    }
777}
778
779/// Information relating to the `future.write` intrinsic.
780#[derive(Debug)]
781pub struct CanonFutureWrite<'a> {
782    /// The future type to instantiate.
783    pub ty: Index<'a>,
784    /// The canonical options for loading values.
785    pub opts: Vec<CanonOpt<'a>>,
786}
787
788impl<'a> Parse<'a> for CanonFutureWrite<'a> {
789    fn parse(parser: Parser<'a>) -> Result<Self> {
790        parser.parse::<kw::future_write>()?;
791
792        Ok(Self {
793            ty: parser.parse()?,
794            opts: parser.parse()?,
795        })
796    }
797}
798
799/// Information relating to the `future.cancel-read` intrinsic.
800#[derive(Debug)]
801pub struct CanonFutureCancelRead<'a> {
802    /// The future type to instantiate.
803    pub ty: Index<'a>,
804    /// If false, block until cancel is finished; otherwise return BLOCKED if
805    /// necessary.
806    pub async_: bool,
807}
808
809impl<'a> Parse<'a> for CanonFutureCancelRead<'a> {
810    fn parse(parser: Parser<'a>) -> Result<Self> {
811        parser.parse::<kw::future_cancel_read>()?;
812
813        Ok(Self {
814            ty: parser.parse()?,
815            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
816        })
817    }
818}
819
820/// Information relating to the `future.cancel-write` intrinsic.
821#[derive(Debug)]
822pub struct CanonFutureCancelWrite<'a> {
823    /// The future type to instantiate.
824    pub ty: Index<'a>,
825    /// If false, block until cancel is finished; otherwise return BLOCKED if
826    /// necessary.
827    pub async_: bool,
828}
829
830impl<'a> Parse<'a> for CanonFutureCancelWrite<'a> {
831    fn parse(parser: Parser<'a>) -> Result<Self> {
832        parser.parse::<kw::future_cancel_write>()?;
833
834        Ok(Self {
835            ty: parser.parse()?,
836            async_: parser.parse::<Option<kw::r#async>>()?.is_some(),
837        })
838    }
839}
840
841/// Information relating to the `future.close-readable` intrinsic.
842#[derive(Debug)]
843pub struct CanonFutureCloseReadable<'a> {
844    /// The future type to close.
845    pub ty: Index<'a>,
846}
847
848impl<'a> Parse<'a> for CanonFutureCloseReadable<'a> {
849    fn parse(parser: Parser<'a>) -> Result<Self> {
850        parser.parse::<kw::future_close_readable>()?;
851
852        Ok(Self {
853            ty: parser.parse()?,
854        })
855    }
856}
857
858/// Information relating to the `future.close-writable` intrinsic.
859#[derive(Debug)]
860pub struct CanonFutureCloseWritable<'a> {
861    /// The future type to close.
862    pub ty: Index<'a>,
863}
864
865impl<'a> Parse<'a> for CanonFutureCloseWritable<'a> {
866    fn parse(parser: Parser<'a>) -> Result<Self> {
867        parser.parse::<kw::future_close_writable>()?;
868
869        Ok(Self {
870            ty: parser.parse()?,
871        })
872    }
873}
874
875/// Information relating to the `error-context.new` intrinsic.
876#[derive(Debug)]
877pub struct CanonErrorContextNew<'a> {
878    /// The canonical options for loading the debug message.
879    pub opts: Vec<CanonOpt<'a>>,
880}
881
882impl<'a> Parse<'a> for CanonErrorContextNew<'a> {
883    fn parse(parser: Parser<'a>) -> Result<Self> {
884        parser.parse::<kw::error_context_new>()?;
885
886        Ok(Self {
887            opts: parser.parse()?,
888        })
889    }
890}
891
892/// Information relating to the `error-context.debug-message` intrinsic.
893#[derive(Debug)]
894pub struct CanonErrorContextDebugMessage<'a> {
895    /// The canonical options for storing the debug message.
896    pub opts: Vec<CanonOpt<'a>>,
897}
898
899impl<'a> Parse<'a> for CanonErrorContextDebugMessage<'a> {
900    fn parse(parser: Parser<'a>) -> Result<Self> {
901        parser.parse::<kw::error_context_debug_message>()?;
902
903        Ok(Self {
904            opts: parser.parse()?,
905        })
906    }
907}
908
909#[derive(Debug)]
910/// Canonical ABI options.
911pub enum CanonOpt<'a> {
912    /// Encode strings as UTF-8.
913    StringUtf8,
914    /// Encode strings as UTF-16.
915    StringUtf16,
916    /// Encode strings as "compact UTF-16".
917    StringLatin1Utf16,
918    /// Use the specified memory for canonical ABI memory access.
919    Memory(CoreItemRef<'a, kw::memory>),
920    /// Use the specified reallocation function for memory allocations.
921    Realloc(CoreItemRef<'a, kw::func>),
922    /// Call the specified function after the lifted function has returned.
923    PostReturn(CoreItemRef<'a, kw::func>),
924    /// Use the async ABI for lifting or lowering.
925    Async,
926    /// Use the specified function to deliver async events to stackless coroutines.
927    Callback(CoreItemRef<'a, kw::func>),
928}
929
930impl<'a> Parse<'a> for CanonOpt<'a> {
931    fn parse(parser: Parser<'a>) -> Result<Self> {
932        let mut l = parser.lookahead1();
933        if l.peek::<kw::string_utf8>()? {
934            parser.parse::<kw::string_utf8>()?;
935            Ok(Self::StringUtf8)
936        } else if l.peek::<kw::string_utf16>()? {
937            parser.parse::<kw::string_utf16>()?;
938            Ok(Self::StringUtf16)
939        } else if l.peek::<kw::string_latin1_utf16>()? {
940            parser.parse::<kw::string_latin1_utf16>()?;
941            Ok(Self::StringLatin1Utf16)
942        } else if l.peek::<kw::r#async>()? {
943            parser.parse::<kw::r#async>()?;
944            Ok(Self::Async)
945        } else if l.peek::<LParen>()? {
946            parser.parens(|parser| {
947                let mut l = parser.lookahead1();
948                if l.peek::<kw::memory>()? {
949                    Ok(CanonOpt::Memory(parser.parse()?))
950                } else if l.peek::<kw::realloc>()? {
951                    parser.parse::<kw::realloc>()?;
952                    Ok(CanonOpt::Realloc(
953                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
954                    ))
955                } else if l.peek::<kw::post_return>()? {
956                    parser.parse::<kw::post_return>()?;
957                    Ok(CanonOpt::PostReturn(
958                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
959                    ))
960                } else if l.peek::<kw::callback>()? {
961                    parser.parse::<kw::callback>()?;
962                    Ok(CanonOpt::Callback(
963                        parser.parse::<IndexOrCoreRef<'_, _>>()?.0,
964                    ))
965                } else {
966                    Err(l.error())
967                }
968            })
969        } else {
970            Err(l.error())
971        }
972    }
973}
974
975impl Peek for CanonOpt<'_> {
976    fn peek(cursor: Cursor<'_>) -> Result<bool> {
977        Ok(kw::string_utf8::peek(cursor)?
978            || kw::string_utf16::peek(cursor)?
979            || kw::string_latin1_utf16::peek(cursor)?
980            || kw::r#async::peek(cursor)?
981            || match cursor.lparen()? {
982                Some(next) => {
983                    kw::memory::peek(next)?
984                        || kw::realloc::peek(next)?
985                        || kw::post_return::peek(next)?
986                        || kw::callback::peek(next)?
987                }
988                None => false,
989            })
990    }
991
992    fn display() -> &'static str {
993        "canonical option"
994    }
995}
996
997impl<'a> Parse<'a> for Vec<CanonOpt<'a>> {
998    fn parse(parser: Parser<'a>) -> Result<Self> {
999        let mut funcs = Vec::new();
1000        while parser.peek::<CanonOpt<'_>>()? {
1001            funcs.push(parser.parse()?);
1002        }
1003        Ok(funcs)
1004    }
1005}