1use wast::parser::{Parse, Parser, Result};
2
3use crate::{
4 AsAtoms, Atom, Expr, Expression, ExpressionParser, FuncType, GlobalType,
5 ImportDesc, Index, InlineExport, MemType, SExpr, TypeUse,
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum Section {
11 Type(TypeSection),
12 Import(ImportSection),
13 Function(FunctionSection),
14 Memory(MemorySection),
15 Global(GlobalSection),
16 Data(DataSection),
17}
18
19impl Section {
20 pub(crate) fn exprs(&self) -> Vec<Expr> {
21 match self {
22 Self::Type(s) => s.exprs(),
23 Self::Import(s) => s.exprs(),
24 Self::Function(s) => s.exprs(),
25 Self::Memory(s) => s.exprs(),
26 Self::Global(s) => s.exprs(),
27 Self::Data(s) => s.exprs(),
28 }
29 }
30}
31
32impl Parse<'_> for Section {
33 fn parse(parser: Parser<'_>) -> Result<Self> {
34 while !parser.is_empty() {
35 if parser.peek2::<wast::kw::r#type>() {
36 return Ok(Self::Type(parser.parse()?));
37 } else if parser.peek2::<wast::kw::import>() {
38 return Ok(Self::Import(parser.parse()?));
39 } else if parser.peek2::<wast::kw::func>() {
40 return Ok(Self::Function(parser.parse()?));
41 } else if parser.peek2::<wast::kw::memory>() {
42 return Ok(Self::Memory(parser.parse()?));
43 } else if parser.peek2::<wast::kw::global>() {
44 return Ok(Self::Global(parser.parse()?));
45 } else if parser.peek2::<wast::kw::data>() {
46 return Ok(Self::Data(parser.parse()?));
47 } else {
48 return Err(parser.error("unexpected section"));
49 }
50 }
51
52 Err(parser.error("empty section"))
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct TypeSection {
58 entries: Vec<TypeSectionEntry>,
59}
60
61impl TypeSection {
62 pub fn with_entries(entries: Vec<TypeSectionEntry>) -> Self {
63 Self { entries }
64 }
65
66 pub(crate) fn exprs(&self) -> Vec<Expr> {
67 self.entries
68 .iter()
69 .map(|e| Expr::SExpr(Box::new(e.clone())))
70 .collect()
71 }
72}
73
74impl Parse<'_> for TypeSection {
75 fn parse(parser: Parser<'_>) -> Result<Self> {
76 let mut entries = Vec::new();
77
78 while !parser.is_empty() {
79 entries.push(parser.parens(|p| p.parse::<TypeSectionEntry>())?);
80
81 if !parser.peek2::<wast::kw::r#type>() {
82 break;
83 }
84 }
85
86 Ok(Self { entries })
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub struct TypeSectionEntry {
92 idx: Option<Index>,
93 func_type: FuncType,
94}
95
96impl TypeSectionEntry {
97 pub fn new(idx: Option<Index>, func_type: FuncType) -> Self {
98 Self { idx, func_type }
99 }
100}
101
102impl SExpr for TypeSectionEntry {
103 fn car(&self) -> String {
104 "type".to_owned()
105 }
106
107 fn cdr(&self) -> Vec<Expr> {
108 let mut v = Vec::new();
109
110 if let Some(ref idx) = self.idx {
111 v.push(Expr::Atom(Atom::new(idx.to_string())));
112 }
113
114 v.push(Expr::SExpr(Box::new(self.func_type.clone())));
115
116 v
117 }
118}
119
120impl Parse<'_> for TypeSectionEntry {
121 fn parse(parser: Parser<'_>) -> Result<Self> {
122 parser.parse::<wast::kw::r#type>()?;
123
124 let idx = parser.parse::<Option<Index>>()?;
125 let func_type = parser.parens(|p| p.parse::<FuncType>())?;
126
127 Ok(Self { idx, func_type })
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub struct ImportSection {
133 entries: Vec<ImportSectionEntry>,
134}
135
136impl ImportSection {
137 pub fn with_entries(entries: Vec<ImportSectionEntry>) -> Self {
138 Self { entries }
139 }
140
141 pub(crate) fn exprs(&self) -> Vec<Expr> {
142 self.entries
143 .iter()
144 .map(|e| Expr::SExpr(Box::new(e.clone())))
145 .collect()
146 }
147}
148
149impl Parse<'_> for ImportSection {
150 fn parse(parser: Parser<'_>) -> Result<Self> {
151 let mut entries = Vec::new();
152
153 while !parser.is_empty() {
154 entries.push(parser.parens(ImportSectionEntry::parse)?);
155
156 if !parser.peek2::<wast::kw::import>() {
157 break;
158 }
159 }
160
161 Ok(Self { entries })
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct ImportSectionEntry {
167 module: String,
168 name: String,
169 desc: ImportDesc,
170}
171
172impl ImportSectionEntry {
173 pub fn new(module: String, name: String, desc: ImportDesc) -> Self {
174 Self { module, name, desc }
175 }
176}
177
178impl SExpr for ImportSectionEntry {
179 fn car(&self) -> String {
180 "import".to_owned()
181 }
182
183 fn cdr(&self) -> Vec<Expr> {
184 let mut v = Vec::with_capacity(3);
185
186 v.append(
187 &mut self
188 .module
189 .as_atoms()
190 .iter()
191 .map(|a| Expr::Atom(a.clone()))
192 .collect(),
193 );
194 v.append(
195 &mut self
196 .name
197 .as_atoms()
198 .iter()
199 .map(|a| Expr::Atom(a.clone()))
200 .collect(),
201 );
202 v.push(Expr::SExpr(Box::new(self.desc.clone())));
203
204 v
205 }
206}
207
208impl Parse<'_> for ImportSectionEntry {
209 fn parse(parser: Parser<'_>) -> Result<Self> {
210 parser.parse::<wast::kw::import>()?;
211
212 let module = parser.parse::<String>()?;
213 let name = parser.parse::<String>()?;
214 let desc = parser.parens(ImportDesc::parse)?;
215
216 Ok(Self { module, name, desc })
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq)]
221pub struct FunctionSection {
222 entries: Vec<FunctionSectionEntry>,
223}
224
225impl FunctionSection {
226 pub fn with_entries(entries: Vec<FunctionSectionEntry>) -> Self {
227 Self { entries }
228 }
229
230 pub(crate) fn exprs(&self) -> Vec<Expr> {
231 self.entries
232 .iter()
233 .map(|e| Expr::SExpr(Box::new(e.clone())))
234 .collect()
235 }
236}
237
238impl Parse<'_> for FunctionSection {
239 fn parse(parser: Parser<'_>) -> Result<Self> {
240 let mut entries = Vec::new();
241
242 while !parser.is_empty() {
243 entries.push(parser.parens(|p| p.parse::<FunctionSectionEntry>())?);
244
245 if !parser.peek2::<wast::kw::func>() {
246 break;
247 }
248 }
249
250 Ok(Self { entries })
251 }
252}
253
254#[derive(Debug, Clone, PartialEq, Eq)]
255pub struct FunctionSectionEntry {
256 idx: Option<Index>,
257 inline_export: Option<InlineExport>,
258 type_use: TypeUse,
259 exprs: Vec<Expression>,
260}
261
262impl FunctionSectionEntry {
263 pub fn new(
264 idx: Option<Index>,
265 inline_export: Option<InlineExport>,
266 type_use: TypeUse,
267 exprs: Vec<Expression>,
268 ) -> Self {
269 Self {
270 idx,
271 inline_export,
272 type_use,
273 exprs,
274 }
275 }
276}
277
278impl SExpr for FunctionSectionEntry {
279 fn car(&self) -> String {
280 "func".to_owned()
281 }
282
283 fn cdr(&self) -> Vec<Expr> {
284 let mut v = Vec::new();
285
286 if let Some(ref idx) = self.idx {
287 v.push(Expr::Atom(Atom::new(idx.to_string())));
288 }
289
290 if let Some(ref inline_export) = self.inline_export {
291 v.push(Expr::SExpr(Box::new(inline_export.clone())));
292 }
293
294 v.append(&mut self.type_use.exprs());
295 v.append(&mut self.exprs.iter().map(|e| e.expr()).collect());
296
297 v
298 }
299}
300
301impl Parse<'_> for FunctionSectionEntry {
302 fn parse(parser: Parser<'_>) -> Result<Self> {
303 parser.parse::<wast::kw::func>()?;
304
305 let idx = parser.parse::<Option<Index>>()?;
306 let mut inline_export = None;
307
308 if parser.peek2::<wast::kw::export>() {
309 inline_export = Some(parser.parens(InlineExport::parse)?);
310 }
311
312 let type_use = parser.parse::<TypeUse>()?;
313 let expressions_parser = ExpressionParser::default();
314 let exprs = expressions_parser.parse(parser)?;
315
316 Ok(Self {
317 idx,
318 inline_export,
319 type_use,
320 exprs,
321 })
322 }
323}
324
325#[derive(Debug, Clone, PartialEq, Eq)]
326pub struct MemorySection {
327 entries: Vec<MemorySectionEntry>,
328}
329
330impl MemorySection {
331 pub fn with_entries(entries: Vec<MemorySectionEntry>) -> Self {
332 Self { entries }
333 }
334
335 pub(crate) fn exprs(&self) -> Vec<Expr> {
336 self.entries
337 .iter()
338 .map(|e| Expr::SExpr(Box::new(e.clone())))
339 .collect()
340 }
341}
342
343impl Parse<'_> for MemorySection {
344 fn parse(parser: Parser<'_>) -> Result<Self> {
345 let mut entries = Vec::new();
346
347 while !parser.is_empty() {
348 entries.push(parser.parens(|p| p.parse::<MemorySectionEntry>())?);
349
350 if !parser.peek2::<wast::kw::memory>() {
351 break;
352 }
353 }
354
355 Ok(Self { entries })
356 }
357}
358
359#[derive(Debug, Clone, PartialEq, Eq)]
360pub struct MemorySectionEntry {
361 idx: Option<Index>,
362 inline_export: Option<InlineExport>,
363 mem_type: MemType,
364}
365
366impl MemorySectionEntry {
367 pub fn new(
368 idx: Option<Index>,
369 inline_export: Option<InlineExport>,
370 mem_type: MemType,
371 ) -> Self {
372 Self {
373 idx,
374 inline_export,
375 mem_type,
376 }
377 }
378}
379
380impl SExpr for MemorySectionEntry {
381 fn car(&self) -> String {
382 "memory".to_owned()
383 }
384
385 fn cdr(&self) -> Vec<Expr> {
386 let mut v = Vec::new();
387
388 if let Some(ref idx) = self.idx {
389 v.push(Expr::Atom(Atom::new(idx.to_string())));
390 }
391
392 if let Some(ref inline_export) = self.inline_export {
393 v.push(Expr::SExpr(Box::new(inline_export.clone())));
394 }
395
396 v.append(&mut self.mem_type.exprs());
397
398 v
399 }
400}
401
402impl Parse<'_> for MemorySectionEntry {
403 fn parse(parser: Parser<'_>) -> Result<Self> {
404 parser.parse::<wast::kw::memory>()?;
405
406 let idx = parser.parse::<Option<Index>>()?;
407 let mut inline_export = None;
408
409 if parser.peek2::<wast::kw::export>() {
410 inline_export = Some(parser.parens(InlineExport::parse)?);
411 }
412
413 let mem_type = parser.parse::<MemType>()?;
414
415 Ok(Self {
416 idx,
417 inline_export,
418 mem_type,
419 })
420 }
421}
422
423#[derive(Debug, Clone, PartialEq, Eq)]
424pub struct GlobalSection {
425 entries: Vec<GlobalSectionEntry>,
426}
427
428impl GlobalSection {
429 pub fn with_entries(entries: Vec<GlobalSectionEntry>) -> Self {
430 Self { entries }
431 }
432
433 pub(crate) fn exprs(&self) -> Vec<Expr> {
434 self.entries
435 .iter()
436 .map(|e| Expr::SExpr(Box::new(e.clone())))
437 .collect()
438 }
439}
440
441impl Parse<'_> for GlobalSection {
442 fn parse(parser: Parser<'_>) -> Result<Self> {
443 let mut entries = Vec::new();
444
445 while !parser.is_empty() {
446 entries.push(parser.parens(|p| p.parse::<GlobalSectionEntry>())?);
447
448 if !parser.peek2::<wast::kw::global>() {
449 break;
450 }
451 }
452
453 Ok(Self { entries })
454 }
455}
456
457#[derive(Debug, Clone, PartialEq, Eq)]
458pub struct GlobalSectionEntry {
459 idx: Option<Index>,
460 inline_export: Option<InlineExport>,
461 global_type: GlobalType,
462
463 expr: Option<Expression>,
465}
466
467impl GlobalSectionEntry {
468 pub fn new(
469 idx: Option<Index>,
470 inline_export: Option<InlineExport>,
471 global_type: GlobalType,
472 expr: Option<Expression>,
473 ) -> Self {
474 Self {
475 idx,
476 inline_export,
477 global_type,
478 expr,
479 }
480 }
481}
482
483impl SExpr for GlobalSectionEntry {
484 fn car(&self) -> String {
485 "global".to_owned()
486 }
487
488 fn cdr(&self) -> Vec<Expr> {
489 let mut v = Vec::new();
490
491 if let Some(ref idx) = self.idx {
492 v.push(Expr::Atom(Atom::new(idx.to_string())));
493 }
494
495 if let Some(ref inline_export) = self.inline_export {
496 v.push(Expr::SExpr(Box::new(inline_export.clone())));
497 }
498
499 v.push(self.global_type.expr());
500
501 if let Some(ref expr) = self.expr {
502 v.push(expr.expr());
503 }
504
505 v
506 }
507}
508
509impl Parse<'_> for GlobalSectionEntry {
510 fn parse(parser: Parser<'_>) -> Result<Self> {
511 parser.parse::<wast::kw::global>()?;
512
513 let idx = parser.parse::<Option<Index>>()?;
514 let mut inline_export = None;
515
516 if parser.peek2::<wast::kw::export>() {
517 inline_export = Some(parser.parens(InlineExport::parse)?);
518 }
519
520 let global_type = parser.parse::<GlobalType>()?;
521 let mut exprs = ExpressionParser::default().parse(parser)?;
522 let expr;
523
524 if exprs.len() == 0 {
525 expr = None;
526 } else {
527 if exprs.len() != 1 {
528 return Err(parser.error("only one expr is expected"));
529 }
530
531 expr = Some(exprs.pop().unwrap());
532 }
533
534 Ok(Self {
535 idx,
536 inline_export,
537 global_type,
538 expr,
539 })
540 }
541}
542
543#[derive(Debug, Clone, PartialEq, Eq)]
544pub struct DataSection {
545 entries: Vec<DataSectionEntry>,
546}
547
548impl DataSection {
549 pub fn with_entries(entries: Vec<DataSectionEntry>) -> Self {
550 Self { entries }
551 }
552
553 pub(crate) fn exprs(&self) -> Vec<Expr> {
554 self.entries
555 .iter()
556 .map(|e| Expr::SExpr(Box::new(e.clone())))
557 .collect()
558 }
559}
560
561impl Parse<'_> for DataSection {
562 fn parse(parser: Parser<'_>) -> Result<Self> {
563 let mut entries = Vec::new();
564
565 while !parser.is_empty() {
566 entries.push(parser.parens(DataSectionEntry::parse)?);
567
568 if !parser.peek2::<wast::kw::data>() {
569 break;
570 }
571 }
572
573 Ok(Self { entries })
574 }
575}
576
577#[derive(Debug, Clone, PartialEq, Eq)]
578pub struct Offset(Expression);
579
580impl Offset {
581 pub fn new(expression: Expression) -> Self {
582 Self(expression)
583 }
584
585 pub(crate) fn expr(&self) -> Expr {
586 self.0.expr()
587 }
588}
589
590impl Parse<'_> for Offset {
591 fn parse(parser: Parser<'_>) -> Result<Self> {
592 let mut exprs = ExpressionParser::default().parse(parser)?;
593
594 if exprs.len() == 0 {
595 return Err(parser.error("init_expr is empty"));
596 }
597
598 if exprs.len() > 1 {
599 return Err(parser.error("only one init_expr operator is expected"));
600 }
601
602 Ok(Self(exprs.pop().unwrap()))
603 }
604}
605
606#[derive(Debug, Clone, PartialEq, Eq)]
607pub struct DataString {
608 strings: Vec<String>,
609}
610
611impl DataString {
612 pub fn with_strings(strings: Vec<String>) -> Self {
613 Self { strings }
614 }
615
616 pub(crate) fn exprs(&self) -> Vec<Expr> {
617 self.strings
618 .iter()
619 .map(|s| Expr::Atom(Atom::new(format!(r#""{}""#, s))))
620 .collect()
621 }
622}
623
624impl Parse<'_> for DataString {
625 fn parse(parser: Parser<'_>) -> Result<Self> {
626 let mut strings = Vec::new();
627
628 while !parser.is_empty() {
629 strings.push(parser.parse::<String>()?);
630 }
631
632 Ok(Self { strings })
633 }
634}
635
636#[derive(Debug, Clone, PartialEq, Eq)]
638pub struct DataSectionEntry {
639 idx: Option<Index>,
640 offset: Offset,
641 data_string: DataString,
642}
643
644impl DataSectionEntry {
645 pub fn new(
646 idx: Option<Index>,
647 offset: Offset,
648 data_string: DataString,
649 ) -> Self {
650 Self {
651 idx,
652 offset,
653 data_string,
654 }
655 }
656}
657
658impl SExpr for DataSectionEntry {
659 fn car(&self) -> String {
660 "data".to_owned()
661 }
662
663 fn cdr(&self) -> Vec<Expr> {
664 let mut v = Vec::new();
665
666 if let Some(idx) = self.idx.clone() {
667 v.push(Expr::Atom(Atom::new(idx.to_string())));
668 }
669
670 v.push(self.offset.expr());
671 v.append(&mut self.data_string.exprs());
672
673 v
674 }
675}
676
677impl Parse<'_> for DataSectionEntry {
678 fn parse(parser: Parser<'_>) -> Result<Self> {
679 parser.parse::<wast::kw::data>()?;
680
681 let idx = parser.parse::<Option<Index>>()?;
682 let offset = parser.parse::<Offset>()?;
683 let data_string = parser.parse::<DataString>()?;
684
685 Ok(Self {
686 idx,
687 offset,
688 data_string,
689 })
690 }
691}