1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use wast::parser::{self, Parse, Parser};

use crate::{Integer, Param, Result};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueType {
    I32,
    I64,
    F32,
    F64,
}

impl Parse<'_> for ValueType {
    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
        let mut l = parser.lookahead1();

        if l.peek::<wast::kw::i32>() {
            parser.parse::<wast::kw::i32>()?;
            Ok(Self::I32)
        } else if l.peek::<wast::kw::i64>() {
            parser.parse::<wast::kw::i64>()?;
            Ok(Self::I64)
        } else if l.peek::<wast::kw::f32>() {
            parser.parse::<wast::kw::f32>()?;
            Ok(Self::F32)
        } else if l.peek::<wast::kw::f64>() {
            parser.parse::<wast::kw::f64>()?;
            Ok(Self::F64)
        } else {
            Err(l.error())
        }
    }
}

/// https://webassembly.github.io/spec/core/text/types.html#function-types
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FuncType {
    pub params: Vec<Param>,
    pub results: Vec<Result>,
}

impl Parse<'_> for FuncType {
    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
        parser.parse::<wast::kw::func>()?;

        let mut params = Vec::new();
        let mut results = Vec::new();

        while !parser.is_empty() {
            if parser.peek2::<wast::kw::param>() {
                params.push(parser.parens(Param::parse)?)
            } else {
                break;
            }
        }

        while !parser.is_empty() {
            if parser.peek2::<wast::kw::result>() {
                results.push(parser.parens(Result::parse)?)
            } else {
                break;
            }
        }

        Ok(Self { params, results })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Limits<'a> {
    pub min: Integer<'a>,
    pub max: Option<Integer<'a>>,
}

impl<'a> Parse<'a> for Limits<'a> {
    fn parse(parser: Parser<'a>) -> parser::Result<Self> {
        let min = parser.parse::<Integer>()?;
        let max = parser.parse::<Option<Integer>>()?;

        Ok(Self { min, max })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MemType<'a> {
    pub lim: Limits<'a>,
}

impl<'a> Parse<'a> for MemType<'a> {
    fn parse(parser: Parser<'a>) -> parser::Result<Self> {
        let lim = parser.parse::<Limits>()?;

        Ok(Self { lim })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GlobalType {
    pub is_mut: bool,
    pub val_type: ValueType,
}

impl Parse<'_> for GlobalType {
    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
        let mut is_mut = false;
        let val_type;

        if parser.peek::<wast::LParen>() {
            val_type = parser.parens(|p| {
                p.parse::<wast::kw::r#mut>()?;

                is_mut = true;

                Ok(p.parse::<ValueType>()?)
            })?;
        } else {
            val_type = parser.parse::<ValueType>()?;
        }

        Ok(Self { is_mut, val_type })
    }
}