1use crate::{AddMetadata, ComponentNames, ModuleNames, Producers};
2use anyhow::Result;
3use std::mem;
4use wasm_encoder::ComponentSection as _;
5use wasm_encoder::{ComponentSectionId, Encode, Section};
6use wasmparser::{KnownCustom, Parser, Payload::*};
7
8pub(crate) fn rewrite_wasm(
9 metadata: &AddMetadata,
10 add_producers: &Producers,
11 input: &[u8],
12) -> Result<Vec<u8>> {
13 let mut producers_found = false;
14 let mut names_found = false;
15 let mut stack = Vec::new();
16 let mut output = Vec::new();
17 for payload in Parser::new(0).parse_all(&input) {
18 let payload = payload?;
19
20 match payload {
22 Version { encoding, .. } => {
23 output.extend_from_slice(match encoding {
24 wasmparser::Encoding::Component => &wasm_encoder::Component::HEADER,
25 wasmparser::Encoding::Module => &wasm_encoder::Module::HEADER,
26 });
27 }
28 ModuleSection { .. } | ComponentSection { .. } => {
29 stack.push(mem::take(&mut output));
30 continue;
31 }
32 End { .. } => {
33 let mut parent = match stack.pop() {
34 Some(c) => c,
35 None => break,
36 };
37 if output.starts_with(&wasm_encoder::Component::HEADER) {
38 parent.push(ComponentSectionId::Component as u8);
39 output.encode(&mut parent);
40 } else {
41 parent.push(ComponentSectionId::CoreModule as u8);
42 output.encode(&mut parent);
43 }
44 output = parent;
45 }
46 _ => {}
47 }
48
49 if let CustomSection(c) = &payload {
51 if stack.len() == 0 {
52 match c.as_known() {
53 KnownCustom::Producers(_) => {
54 producers_found = true;
55 let mut producers = Producers::from_bytes(c.data(), c.data_offset())?;
56 producers.merge(&add_producers);
58 producers.section().append_to(&mut output);
60 continue;
61 }
62 KnownCustom::Name(_) => {
63 names_found = true;
64 let mut names = ModuleNames::from_bytes(c.data(), c.data_offset())?;
65 names.merge(&ModuleNames::from_name(&metadata.name));
66
67 names.section()?.as_custom().append_to(&mut output);
68 continue;
69 }
70 KnownCustom::ComponentName(_) => {
71 names_found = true;
72 let mut names = ComponentNames::from_bytes(c.data(), c.data_offset())?;
73 names.merge(&ComponentNames::from_name(&metadata.name));
74 names.section()?.as_custom().append_to(&mut output);
75 continue;
76 }
77 #[cfg(feature = "oci")]
78 KnownCustom::Unknown if c.name() == "author" => {
79 if metadata.authors.is_none() {
80 let author = crate::Authors::parse_custom_section(c)?;
81 author.append_to(&mut output);
82 continue;
83 }
84 }
85 #[cfg(feature = "oci")]
86 KnownCustom::Unknown if c.name() == "description" => {
87 if metadata.description.is_none() {
88 let description = crate::Description::parse_custom_section(c)?;
89 description.append_to(&mut output);
90 continue;
91 }
92 }
93 #[cfg(feature = "oci")]
94 KnownCustom::Unknown if c.name() == "licenses" => {
95 if metadata.licenses.is_none() {
96 let licenses = crate::Licenses::parse_custom_section(c)?;
97 licenses.append_to(&mut output);
98 continue;
99 }
100 }
101 #[cfg(feature = "oci")]
102 KnownCustom::Unknown if c.name() == "source" => {
103 if metadata.source.is_none() {
104 let source = crate::Source::parse_custom_section(c)?;
105 source.append_to(&mut output);
106 continue;
107 }
108 }
109 #[cfg(feature = "oci")]
110 KnownCustom::Unknown if c.name() == "homepage" => {
111 if metadata.source.is_none() {
112 let homepage = crate::Homepage::parse_custom_section(c)?;
113 homepage.append_to(&mut output);
114 continue;
115 }
116 }
117 #[cfg(feature = "oci")]
118 KnownCustom::Unknown if c.name() == "revision" => {
119 if metadata.source.is_none() {
120 let revision = crate::Revision::parse_custom_section(c)?;
121 revision.append_to(&mut output);
122 continue;
123 }
124 }
125 #[cfg(feature = "oci")]
126 KnownCustom::Unknown if c.name() == "version" => {
127 if metadata.version.is_none() {
128 let version = crate::Version::parse_custom_section(c)?;
129 version.append_to(&mut output);
130 continue;
131 }
132 }
133 _ => {}
134 }
135 }
136 }
137 if let Some((id, range)) = payload.as_section() {
139 wasm_encoder::RawSection {
140 id,
141 data: &input[range],
142 }
143 .append_to(&mut output);
144 }
145 }
146 if !names_found && metadata.name.is_some() {
147 if output.starts_with(&wasm_encoder::Component::HEADER) {
148 let names = ComponentNames::from_name(&metadata.name);
149 names.section()?.append_to_component(&mut output);
150 } else {
151 let names = ModuleNames::from_name(&metadata.name);
152 names.section()?.append_to(&mut output)
153 }
154 }
155 if !producers_found && !add_producers.is_empty() {
156 let mut producers = Producers::empty();
157 producers.merge(add_producers);
159 producers.section().append_to(&mut output);
161 }
162 #[cfg(feature = "oci")]
163 if let Some(author) = &metadata.authors {
164 author.append_to(&mut output);
165 }
166 #[cfg(feature = "oci")]
167 if let Some(description) = &metadata.description {
168 description.append_to(&mut output);
169 }
170 #[cfg(feature = "oci")]
171 if let Some(licenses) = &metadata.licenses {
172 licenses.append_to(&mut output);
173 }
174 #[cfg(feature = "oci")]
175 if let Some(source) = &metadata.source {
176 source.append_to(&mut output);
177 }
178 #[cfg(feature = "oci")]
179 if let Some(homepage) = &metadata.homepage {
180 homepage.append_to(&mut output);
181 }
182 #[cfg(feature = "oci")]
183 if let Some(revision) = &metadata.revision {
184 revision.append_to(&mut output);
185 }
186 #[cfg(feature = "oci")]
187 if let Some(version) = &metadata.version {
188 version.append_to(&mut output);
189 }
190 Ok(output)
191}