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 | |