1use parity_wasm::elements::{Module, Section};
2
3use super::{ChiselModule, ModuleError, ModuleKind, ModuleTranslator};
4
5pub enum DropSection {
7 NamesSection,
8 CustomSectionByName(String),
10 CustomSectionByIndex(usize),
12 UnknownSectionByIndex(usize),
14}
15
16impl<'a> ChiselModule<'a> for DropSection {
17 type ObjectReference = &'a dyn ModuleTranslator;
18
19 fn id(&'a self) -> String {
20 "dropsection".to_string()
21 }
22
23 fn kind(&'a self) -> ModuleKind {
24 ModuleKind::Translator
25 }
26
27 fn as_abstract(&'a self) -> Self::ObjectReference {
28 self as Self::ObjectReference
29 }
30}
31
32fn custom_section_index_for(module: &Module, name: &str) -> Option<usize> {
34 module.sections().iter().position(|e| match e {
35 Section::Custom(_section) => _section.name() == name,
36 Section::Name(_) => name == "name", _ => false,
38 })
39}
40
41impl DropSection {
42 fn find_index(&self, module: &Module) -> Option<usize> {
43 match &self {
44 DropSection::NamesSection => custom_section_index_for(module, "name"),
45 DropSection::CustomSectionByName(name) => custom_section_index_for(module, &name),
46 DropSection::CustomSectionByIndex(index) => Some(*index),
47 DropSection::UnknownSectionByIndex(index) => Some(*index),
48 }
49 }
50
51 fn drop_section(&self, module: &mut Module) -> Result<bool, ModuleError> {
52 if let Some(index) = self.find_index(&module) {
53 let sections = module.sections_mut();
54 if index < sections.len() {
55 sections.remove(index);
56 return Ok(true);
57 }
58 }
59
60 Ok(false)
61 }
62}
63
64impl<'a> ModuleTranslator for DropSection {
65 fn translate_inplace(&self, module: &mut Module) -> Result<bool, ModuleError> {
66 Ok(self.drop_section(module)?)
67 }
68
69 fn translate(&self, module: &Module) -> Result<Option<Module>, ModuleError> {
70 let mut ret = module.clone();
71 if self.drop_section(&mut ret)? {
72 Ok(Some(ret))
73 } else {
74 Ok(None)
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use parity_wasm::builder;
82 use parity_wasm::elements::CustomSection;
83 use rustc_hex::FromHex;
84
85 use super::*;
86
87 #[test]
88 fn keep_intact() {
89 let mut module = builder::module().build();
90 let name = "empty".to_string();
91 let dropper = DropSection::CustomSectionByName(name);
92 let did_change = dropper.translate_inplace(&mut module).unwrap();
93 assert_eq!(did_change, false);
94 }
95
96 #[test]
97 fn keep_intact_custom_section() {
98 let mut module = builder::module()
99 .with_section(Section::Custom(CustomSection::new(
100 "test".to_string(),
101 vec![],
102 )))
103 .build();
104 let name = "empty".to_string();
105 let dropper = DropSection::CustomSectionByName(name);
106 let did_change = dropper.translate_inplace(&mut module).unwrap();
107 assert_eq!(did_change, false);
108 }
109
110 #[test]
111 fn remove_custom_section() {
112 let mut module = builder::module()
113 .with_section(Section::Custom(CustomSection::new(
114 "test".to_string(),
115 vec![],
116 )))
117 .build();
118 let name = "test".to_string();
119 let dropper = DropSection::CustomSectionByName(name);
120 let did_change = dropper.translate_inplace(&mut module).unwrap();
121 assert_eq!(did_change, true);
122 }
123
124 #[test]
125 fn remove_custom_section_by_index() {
126 let mut module = builder::module()
127 .with_section(Section::Custom(CustomSection::new(
128 "test".to_string(),
129 vec![],
130 )))
131 .build();
132 let dropper = DropSection::CustomSectionByIndex(0);
133 let did_change = dropper.translate_inplace(&mut module).unwrap();
134 assert_eq!(did_change, true);
135 }
136
137 #[test]
138 fn remove_oob_custom_section_by_index() {
139 let mut module = builder::module()
140 .with_section(Section::Custom(CustomSection::new(
141 "test".to_string(),
142 vec![],
143 )))
144 .build();
145 let dropper = DropSection::CustomSectionByIndex(1);
146 let did_change = dropper.translate_inplace(&mut module).unwrap();
147 assert_eq!(did_change, false);
148 }
149
150 #[test]
151 fn remove_custom_unknown_by_index() {
152 let mut module = builder::module()
153 .with_section(Section::Custom(CustomSection::new(
154 "test".to_string(),
155 vec![],
156 )))
157 .build();
158 let dropper = DropSection::UnknownSectionByIndex(0);
159 let did_change = dropper.translate_inplace(&mut module).unwrap();
160 assert_eq!(did_change, true);
161 }
162
163 #[test]
164 fn remove_oob_unknown_section_by_index() {
165 let mut module = builder::module()
166 .with_section(Section::Custom(CustomSection::new(
167 "test".to_string(),
168 vec![],
169 )))
170 .build();
171 let dropper = DropSection::UnknownSectionByIndex(1);
172 let did_change = dropper.translate_inplace(&mut module).unwrap();
173 assert_eq!(did_change, false);
174 }
175
176 #[test]
177 fn names_section_index() {
178 let input = FromHex::from_hex(
179 "0061736d010000000104016000000303020000070801046d61696e00010a
180 0a020300010b040010000b0014046e616d65010d0200047465737401046d
181 61696e",
182 )
183 .unwrap();
184
185 let mut module = Module::from_bytes(&input).unwrap();
186 assert!(custom_section_index_for(&module, "name").is_some());
187 module = module.parse_names().expect("Should not fail");
188 assert!(custom_section_index_for(&module, "name").is_some());
189 }
190
191 #[test]
192 fn missing_name_section_index() {
193 let input = FromHex::from_hex(
194 "0061736d010000000104016000000303020000070801046d61696e00010a
195 0a020300010b040010000b",
196 )
197 .unwrap();
198
199 let module = Module::from_bytes(&input).unwrap();
200 assert!(custom_section_index_for(&module, "name").is_none());
201 }
202
203 #[test]
204 fn dropped_name_section_parsed() {
205 let input = FromHex::from_hex(
206 "0061736d010000000104016000000303020000070801046d61696e00010a
207 0a020300010b040010000b0014046e616d65010d0200047465737401046d
208 61696e",
209 )
210 .unwrap();
211
212 let mut module = Module::from_bytes(&input)
213 .unwrap()
214 .parse_names()
215 .expect("Should not fail");
216 let mut module1 = module.clone();
217
218 assert!(custom_section_index_for(&module, "name").is_some());
219
220 let dropper = DropSection::CustomSectionByName("name".to_string());
221 let dropper1 = DropSection::NamesSection;
222
223 assert!(dropper
224 .translate_inplace(&mut module)
225 .expect("Should not fail"));
226 assert!(dropper1
227 .translate_inplace(&mut module1)
228 .expect("Should not fail"));
229
230 assert!(custom_section_index_for(&module, "name").is_none());
231 assert!(custom_section_index_for(&module1, "name").is_none());
232 }
233
234 #[test]
235 fn dropped_name_section_index_unparsed() {
236 let input = FromHex::from_hex(
237 "0061736d010000000104016000000303020000070801046d61696e00010a
238 0a020300010b040010000b0014046e616d65010d0200047465737401046d
239 61696e",
240 )
241 .unwrap();
242
243 let mut module = Module::from_bytes(&input).unwrap();
244 let mut module1 = module.clone();
245
246 assert!(custom_section_index_for(&module, "name").is_some());
247
248 let dropper = DropSection::CustomSectionByName("name".to_string());
249 let dropper1 = DropSection::NamesSection;
250
251 assert!(dropper
252 .translate_inplace(&mut module)
253 .expect("Should not fail"));
254 assert!(dropper1
255 .translate_inplace(&mut module1)
256 .expect("Should not fail"));
257
258 assert!(custom_section_index_for(&module, "name").is_none());
259 assert!(custom_section_index_for(&module1, "name").is_none());
260 }
261}