use crate::parser::{Parse, Parser, Result}; use crate::token::{self, Span}; use crate::{annotation, kw}; /// A wasm custom section within a module. #[derive(Debug)] pub struct Custom<'a> { /// Where this `@custom` was defined. pub span: Span, /// Name of the custom section. pub name: &'a str, /// Where the custom section is being placed, pub place: CustomPlace, /// Payload of this custom section. pub data: Vec<&'a [u8]>, } /// Possible locations to place a custom section within a module. #[derive(Debug, PartialEq, Copy, Clone)] pub enum CustomPlace { /// This custom section will appear before the first section in the module. BeforeFirst, /// This custom section will be placed just before a known section. Before(CustomPlaceAnchor), /// This custom section will be placed just after a known section. After(CustomPlaceAnchor), /// This custom section will appear after the last section in the module. AfterLast, } /// Known sections that custom sections can be placed relative to. #[derive(Debug, PartialEq, Eq, Copy, Clone)] #[allow(missing_docs)] pub enum CustomPlaceAnchor { Type, Import, Func, Table, Memory, Global, Export, Start, Elem, Code, Data, Tag, } impl<'a> Parse<'a> for Custom<'a> { fn parse(parser: Parser<'a>) -> Result { let span = parser.parse::()?.0; let name = parser.parse()?; let place = if parser.peek::() { parser.parens(|p| p.parse())? } else { CustomPlace::AfterLast }; let mut data = Vec::new(); while !parser.is_empty() { data.push(parser.parse()?); } Ok(Custom { span, name, place, data, }) } } impl<'a> Parse<'a> for CustomPlace { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); let ctor = if l.peek::() { parser.parse::()?; if l.peek::() { parser.parse::()?; return Ok(CustomPlace::BeforeFirst); } CustomPlace::Before as fn(CustomPlaceAnchor) -> _ } else if l.peek::() { parser.parse::()?; if l.peek::() { parser.parse::()?; return Ok(CustomPlace::AfterLast); } CustomPlace::After } else { return Err(l.error()); }; Ok(ctor(parser.parse()?)) } } impl<'a> Parse<'a> for CustomPlaceAnchor { fn parse(parser: Parser<'a>) -> Result { if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Type); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Import); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Func); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Table); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Memory); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Global); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Export); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Start); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Elem); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Code); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Data); } if parser.peek::() { parser.parse::()?; return Ok(CustomPlaceAnchor::Tag); } Err(parser.error("expected a valid section name")) } }