1use crate::kw;
2use crate::parser::{Cursor, Parse, Parser, Peek, Result};
3use crate::token::{Index, Span};
4
5#[derive(Debug)]
7pub struct Export<'a> {
8 pub span: Span,
10 pub name: &'a str,
12 pub kind: ExportKind,
14 pub item: Index<'a>,
16}
17
18#[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#[derive(Debug, Default)]
108pub struct InlineExport<'a> {
109 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}