| 1 | /* Copyright 2019 Mozilla Foundation |
| 2 | * |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | |
| 16 | use crate::{BinaryReader, FromReader, Result, SectionLimited}; |
| 17 | |
| 18 | /// A reader for the producers custom section of a WebAssembly module. |
| 19 | /// |
| 20 | /// # Examples |
| 21 | /// |
| 22 | /// ``` |
| 23 | /// # let data: &[u8] = &[0x01, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, |
| 24 | /// # 0x02, 0x03, 0x77, 0x61, 0x74, 0x01, 0x31, 0x01, 0x43, 0x03, 0x39, 0x2e, 0x30]; |
| 25 | /// # use wasmparser::{ProducersSectionReader, ProducersFieldValue, Result, BinaryReader}; |
| 26 | /// let reader = BinaryReader::new(data, 0); |
| 27 | /// let reader = ProducersSectionReader::new(reader).expect("producers reader" ); |
| 28 | /// let field = reader.into_iter().next().unwrap().expect("producers field" ); |
| 29 | /// assert!(field.name == "language" ); |
| 30 | /// let value = field.values.into_iter().collect::<Result<Vec<_>>>().expect("values" ); |
| 31 | /// assert!(value.len() == 2); |
| 32 | /// assert!(value[0].name == "wat" && value[0].version == "1" ); |
| 33 | /// assert!(value[1].name == "C" && value[1].version == "9.0" ); |
| 34 | /// ``` |
| 35 | pub type ProducersSectionReader<'a> = SectionLimited<'a, ProducersField<'a>>; |
| 36 | |
| 37 | /// A field from the producers custom section. |
| 38 | #[derive (Debug, Clone)] |
| 39 | pub struct ProducersField<'a> { |
| 40 | /// The name of the field. |
| 41 | pub name: &'a str, |
| 42 | /// The values specified for this field |
| 43 | pub values: SectionLimited<'a, ProducersFieldValue<'a>>, |
| 44 | } |
| 45 | |
| 46 | impl<'a> FromReader<'a> for ProducersField<'a> { |
| 47 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { |
| 48 | let offset: usize = reader.original_position(); |
| 49 | let name: &'a str = reader.read_string()?; |
| 50 | match name { |
| 51 | "language" | "sdk" | "processed-by" => {} |
| 52 | _ => bail!(offset, "invalid producers field name: ` {name}`" ), |
| 53 | } |
| 54 | let values: BinaryReader<'a> = reader.skip(|reader: &mut BinaryReader<'a>| { |
| 55 | // FIXME(#188) ideally shouldn't need to skip here |
| 56 | for _ in 0..reader.read_var_u32()? { |
| 57 | reader.skip_string()?; |
| 58 | reader.skip_string()?; |
| 59 | } |
| 60 | Ok(()) |
| 61 | })?; |
| 62 | Ok(ProducersField { |
| 63 | name, |
| 64 | values: SectionLimited::new(reader:values)?, |
| 65 | }) |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | /// Represents a field value in the producers custom section. |
| 70 | #[derive (Debug, Copy, Clone)] |
| 71 | pub struct ProducersFieldValue<'a> { |
| 72 | /// The field name. |
| 73 | pub name: &'a str, |
| 74 | /// The field version. |
| 75 | pub version: &'a str, |
| 76 | } |
| 77 | |
| 78 | impl<'a> FromReader<'a> for ProducersFieldValue<'a> { |
| 79 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { |
| 80 | let name: &'a str = reader.read_string()?; |
| 81 | let version: &'a str = reader.read_string()?; |
| 82 | Ok(ProducersFieldValue { name, version }) |
| 83 | } |
| 84 | } |
| 85 | |