1pub use parity_wasm::elements::Module;
2
3use std::{error, fmt};
4
5pub mod imports;
6
7#[cfg(feature = "binaryen")]
8pub mod binaryenopt;
9pub mod checkfloat;
10pub mod checkstartfunc;
11pub mod deployer;
12pub mod dropsection;
13pub mod remapimports;
14pub mod remapstart;
15pub mod repack;
16pub mod snip;
17pub mod trimexports;
18pub mod trimstartfunc;
19pub mod verifyexports;
20pub mod verifyimports;
21
22mod depgraph;
23
24#[derive(Eq, PartialEq, Debug)]
25pub enum ModuleKind {
26 Creator,
27 Translator,
28 Validator,
29}
30
31#[derive(Eq, PartialEq, Debug, Clone)]
32pub enum ModuleError {
33 NotSupported,
34 NotFound,
35 Custom(String),
36}
37
38pub trait ChiselModule<'a> {
40 type ObjectReference: ?Sized;
41 fn id(&'a self) -> String;
43
44 fn kind(&'a self) -> ModuleKind;
45
46 fn as_abstract(&'a self) -> Self::ObjectReference;
48}
49
50pub trait ModuleCreator {
51 fn create(&self) -> Result<Module, ModuleError>;
53}
54
55pub trait ModuleTranslator {
56 fn translate(&self, module: &Module) -> Result<Option<Module>, ModuleError>;
58
59 fn translate_inplace(&self, module: &mut Module) -> Result<bool, ModuleError>;
61}
62
63pub trait ModuleValidator {
64 fn validate(&self, module: &Module) -> Result<bool, ModuleError>;
66}
67
68pub trait ModulePreset {
69 fn with_preset(preset: &str) -> Result<Self, ModuleError>
70 where
71 Self: std::marker::Sized;
72}
73
74impl From<String> for ModuleError {
75 fn from(error: String) -> Self {
76 ModuleError::Custom(error)
77 }
78}
79
80impl From<std::io::Error> for ModuleError {
81 fn from(error: std::io::Error) -> Self {
82 use std::error::Error;
83 ModuleError::Custom(error.description().to_string())
84 }
85}
86
87impl From<parity_wasm::elements::Error> for ModuleError {
89 fn from(a: parity_wasm::elements::Error) -> Self {
90 use std::error::Error;
91 ModuleError::Custom(a.description().to_string())
92 }
93}
94
95impl fmt::Display for ModuleError {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 write!(
98 f,
99 "{}",
100 match self {
101 ModuleError::NotSupported => "Method unsupported",
102 ModuleError::NotFound => "Not found",
103 ModuleError::Custom(msg) => msg,
104 }
105 )
106 }
107}
108
109impl error::Error for ModuleError {
110 fn description(&self) -> &str {
111 match self {
112 ModuleError::NotSupported => "Method unsupported",
113 ModuleError::NotFound => "Not found",
114 ModuleError::Custom(msg) => msg,
115 }
116 }
117
118 fn cause(&self) -> Option<&dyn error::Error> {
119 None
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use std::error::Error;
126
127 use super::*;
128
129 struct SampleModule {}
130
131 impl ModuleCreator for SampleModule {
132 fn create(&self) -> Result<Module, ModuleError> {
133 Ok(Module::default())
134 }
135 }
136
137 impl ModuleTranslator for SampleModule {
138 fn translate(&self, _module: &Module) -> Result<Option<Module>, ModuleError> {
139 Ok(Some(Module::default()))
140 }
141 fn translate_inplace(&self, _module: &mut Module) -> Result<bool, ModuleError> {
142 Ok(true)
143 }
144 }
145
146 impl ModuleValidator for SampleModule {
147 fn validate(&self, _module: &Module) -> Result<bool, ModuleError> {
148 Ok(true)
149 }
150 }
151
152 impl<'a> ChiselModule<'a> for SampleModule {
153 type ObjectReference = &'a dyn ModuleValidator;
156
157 fn id(&'a self) -> String {
158 "Sample".to_string()
159 }
160
161 fn kind(&'a self) -> ModuleKind {
162 ModuleKind::Validator
163 }
164
165 fn as_abstract(&'a self) -> Self::ObjectReference {
166 self as Self::ObjectReference
167 }
168 }
169
170 #[test]
171 fn creator_succeeds() {
172 let creator = SampleModule {};
173 let result = creator.create();
174 assert!(result.is_ok());
175 }
176
177 #[test]
178 fn translator_succeeds() {
179 let translator = SampleModule {};
180 let result = translator.translate(&Module::default());
181 assert!(result.is_ok());
182 }
183
184 #[test]
185 fn translator_inplace_succeeds() {
186 let translator = SampleModule {};
187 let result = translator.translate_inplace(&mut Module::default());
188 assert!(result.is_ok());
189 }
190
191 #[test]
192 fn validator_succeeds() {
193 let validator = SampleModule {};
194 let result = validator.validate(&Module::default());
195 assert!(result.is_ok());
196 }
197
198 #[test]
199 fn from_error() {
200 let err: ModuleError = "custom message".to_string().into();
201 assert_eq!(err, ModuleError::Custom("custom message".to_string()));
202 }
203
204 #[test]
205 fn fmt_good() {
206 let fmt_result_unsupported = format!("{}", ModuleError::NotSupported);
208 assert_eq!("Method unsupported", fmt_result_unsupported);
209
210 let fmt_result_custom = format!("{}", ModuleError::Custom("foo".to_string()));
211 assert_eq!("foo", fmt_result_custom);
212 }
213
214 #[test]
215 fn error_good() {
216 let err_unsupported = ModuleError::NotSupported;
218 let err_description_unsupported = err_unsupported.description();
219 assert_eq!("Method unsupported", err_description_unsupported);
220
221 let err_custom = ModuleError::Custom("bar".to_string());
222 let err_description_custom = err_custom.description();
223 assert_eq!("bar", err_description_custom);
224 }
225
226 #[test]
227 fn opaque_module() {
228 let validator = SampleModule {};
229 assert_eq!(validator.id(), "Sample");
230
231 let opaque: &dyn ChiselModule<ObjectReference = &dyn ModuleValidator> =
232 &validator as &dyn ChiselModule<ObjectReference = &dyn ModuleValidator>;
233
234 assert_eq!(opaque.kind(), ModuleKind::Validator);
235
236 let as_trait: &dyn ModuleValidator = opaque.as_abstract();
237
238 let result = as_trait.validate(&Module::default());
239 assert!(result.is_ok());
240 }
241}