wasm_encoder/core/
producers.rs1use crate::{CustomSection, Encode, Section, SectionId};
2use alloc::borrow::Cow;
3use alloc::vec::Vec;
4
5#[derive(Clone, Debug)]
28pub struct ProducersSection {
29 bytes: Vec<u8>,
30 num_fields: u32,
31}
32
33impl ProducersSection {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn field(&mut self, name: &str, values: &ProducersField) -> &mut Self {
43 name.encode(&mut self.bytes);
44 values.encode(&mut self.bytes);
45 self.num_fields += 1;
46 self
47 }
48}
49
50impl Default for ProducersSection {
51 fn default() -> Self {
52 Self {
53 bytes: Vec::new(),
54 num_fields: 0,
55 }
56 }
57}
58
59impl Encode for ProducersSection {
60 fn encode(&self, sink: &mut Vec<u8>) {
61 let mut data = Vec::new();
62 self.num_fields.encode(&mut data);
63 data.extend(&self.bytes);
64
65 CustomSection {
66 name: "producers".into(),
67 data: Cow::Borrowed(&data),
68 }
69 .encode(sink);
70 }
71}
72
73impl Section for ProducersSection {
74 fn id(&self) -> u8 {
75 SectionId::Custom.into()
76 }
77}
78
79#[derive(Clone, Debug)]
81pub struct ProducersField {
82 bytes: Vec<u8>,
83 num_values: u32,
84}
85
86impl ProducersField {
87 pub fn new() -> Self {
89 ProducersField::default()
90 }
91
92 pub fn value(&mut self, name: &str, version: &str) -> &mut Self {
96 name.encode(&mut self.bytes);
97 version.encode(&mut self.bytes);
98 self.num_values += 1;
99 self
100 }
101}
102
103impl Default for ProducersField {
104 fn default() -> Self {
105 Self {
106 bytes: Vec::new(),
107 num_values: 0,
108 }
109 }
110}
111
112impl Encode for ProducersField {
113 fn encode(&self, sink: &mut Vec<u8>) {
114 self.num_values.encode(sink);
115 sink.extend(&self.bytes);
116 }
117}
118
119#[cfg(test)]
120mod test {
121 #[test]
122 fn roundtrip_example() {
123 use crate::{Module, ProducersField, ProducersSection};
124 use wasmparser::{KnownCustom, Parser, Payload};
125
126 let mut field = ProducersField::new();
128 field.value("clang", "14.0.4");
129 field.value("rustc", "1.66.1");
130 let mut producers = ProducersSection::new();
131 producers.field("processed-by", &field);
132
133 let mut module = Module::new();
135 module.section(&producers);
136 let wasm_bytes = module.finish();
137
138 let mut parser = Parser::new(0).parse_all(&wasm_bytes);
139 let payload = parser
140 .next()
141 .expect("parser is not empty")
142 .expect("element is a payload");
143 match payload {
144 Payload::Version { .. } => {}
145 _ => panic!(""),
146 }
147 let payload = parser
148 .next()
149 .expect("parser is not empty")
150 .expect("element is a payload");
151 match payload {
152 Payload::CustomSection(c) => {
153 assert_eq!(c.name(), "producers");
154 let mut section = match c.as_known() {
155 KnownCustom::Producers(s) => s.into_iter(),
156 _ => panic!("unknown custom section"),
157 };
158 let field = section
159 .next()
160 .expect("section has an element")
161 .expect("element is a producers field");
162 assert_eq!(field.name, "processed-by");
163 let mut values = field.values.into_iter();
164 let value = values
165 .next()
166 .expect("values has an element")
167 .expect("element is a producers field value");
168 assert_eq!(value.name, "clang");
169 assert_eq!(value.version, "14.0.4");
170
171 let value = values
172 .next()
173 .expect("values has another element")
174 .expect("element is a producers field value");
175 assert_eq!(value.name, "rustc");
176 assert_eq!(value.version, "1.66.1");
177 }
178 _ => panic!("unexpected payload"),
179 }
180 }
181}