wast/core/
export.rs

1use crate::kw;
2use crate::parser::{Cursor, Parse, Parser, Peek, Result};
3use crate::token::{Index, Span};
4
5/// A entry in a WebAssembly module's export section.
6#[derive(Debug)]
7pub struct Export<'a> {
8    /// Where this export was defined.
9    pub span: Span,
10    /// The name of this export from the module.
11    pub name: &'a str,
12    /// The kind of item being exported.
13    pub kind: ExportKind,
14    /// What's being exported from the module.
15    pub item: Index<'a>,
16}
17
18/// Different kinds of elements that can be exported from a WebAssembly module,
19/// contained in an [`Export`].
20#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
21#[allow(missing_docs)]
22pub enum ExportKind {
23    Func,
24    Table,
25    Memory,
26    Global,
27    Tag,
28}
29
30impl<'a> Parse<'a> for Export<'a> {
31    fn parse(parser: Parser<'a>) -> Result<Self> {
32        let span = parser.parse::<kw::export>()?.0;
33        let name = parser.parse()?;
34        let (kind, item) = parser.parens(|p| Ok((p.parse()?, p.parse()?)))?;
35        Ok(Export {
36            span,
37            name,
38            kind,
39            item,
40        })
41    }
42}
43
44impl<'a> Parse<'a> for ExportKind {
45    fn parse(parser: Parser<'a>) -> Result<Self> {
46        let mut l = parser.lookahead1();
47        if l.peek::<kw::func>()? {
48            parser.parse::<kw::func>()?;
49            Ok(ExportKind::Func)
50        } else if l.peek::<kw::table>()? {
51            parser.parse::<kw::table>()?;
52            Ok(ExportKind::Table)
53        } else if l.peek::<kw::memory>()? {
54            parser.parse::<kw::memory>()?;
55            Ok(ExportKind::Memory)
56        } else if l.peek::<kw::global>()? {
57            parser.parse::<kw::global>()?;
58            Ok(ExportKind::Global)
59        } else if l.peek::<kw::tag>()? {
60            parser.parse::<kw::tag>()?;
61            Ok(ExportKind::Tag)
62        } else {
63            Err(l.error())
64        }
65    }
66}
67
68impl Peek for ExportKind {
69    fn peek(cursor: Cursor<'_>) -> Result<bool> {
70        Ok(kw::func::peek(cursor)?
71            || kw::table::peek(cursor)?
72            || kw::memory::peek(cursor)?
73            || kw::global::peek(cursor)?
74            || kw::tag::peek(cursor)?)
75    }
76    fn display() -> &'static str {
77        "export kind"
78    }
79}
80
81macro_rules! kw_conversions {
82    ($($kw:ident => $kind:ident)*) => ($(
83        impl From<kw::$kw> for ExportKind {
84            fn from(_: kw::$kw) -> ExportKind {
85                ExportKind::$kind
86            }
87        }
88
89        impl Default for kw::$kw {
90            fn default() -> kw::$kw {
91                kw::$kw(Span::from_offset(0))
92            }
93        }
94    )*);
95}
96
97kw_conversions! {
98    func => Func
99    table => Table
100    global => Global
101    tag => Tag
102    memory => Memory
103}
104
105/// A listing of inline `(export "foo")` statements on a WebAssembly item in
106/// its textual format.
107#[derive(Debug, Default)]
108pub struct InlineExport<'a> {
109    /// The extra names to export an item as, if any.
110    pub names: Vec<&'a str>,
111}
112
113impl<'a> Parse<'a> for InlineExport<'a> {
114    fn parse(parser: Parser<'a>) -> Result<Self> {
115        let mut names = Vec::new();
116        while parser.peek::<Self>()? {
117            names.push(parser.parens(|p| {
118                p.parse::<kw::export>()?;
119                p.parse::<&str>()
120            })?);
121        }
122        Ok(InlineExport { names })
123    }
124}
125
126impl Peek for InlineExport<'_> {
127    fn peek(cursor: Cursor<'_>) -> Result<bool> {
128        let cursor = match cursor.lparen()? {
129            Some(cursor) => cursor,
130            None => return Ok(false),
131        };
132        let cursor = match cursor.keyword()? {
133            Some(("export", cursor)) => cursor,
134            _ => return Ok(false),
135        };
136        let cursor = match cursor.string()? {
137            Some((_, cursor)) => cursor,
138            None => return Ok(false),
139        };
140        Ok(cursor.rparen()?.is_some())
141    }
142
143    fn display() -> &'static str {
144        "inline export"
145    }
146}