1use serde::{Deserialize, Serialize};
2
3pub use self::value::Value;
4
5pub mod actions;
6pub mod cfg_actions;
7pub mod cfg_blocks;
8mod float_is;
9mod helpers;
10mod value;
11
12#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
13#[serde(tag = "action", rename_all = "kebab-case")]
14pub enum Action {
15 Unknown(actions::UnknownAction),
16 Add,
17 And,
18 CastOp,
19 CloneSprite,
20 Divide,
21 Equals,
22 EndDrag,
23 FsCommand2,
24 GetProperty,
25 GetVariable,
26 ImplementsOp,
27 Less,
28 MbStringLength,
29 Multiply,
30 NextFrame,
31 Not,
32 Or,
33 PrevFrame,
34 Play,
35 Pop,
36 RandomNumber,
37 RemoveSprite,
38 SetProperty,
39 SetTarget2,
40 SetVariable,
41 StartDrag,
42 Stop,
43 StopSounds,
44 StringAdd,
45 StringEquals,
46 StringExtract,
47 StringLength,
48 StringLess,
49 Subtract,
50 Throw,
51 ToInteger,
52 ToggleQuality,
53 Trace,
54 CharToAscii,
56 AsciiToChar,
58 GetTime,
60 MbStringExtract,
62 MbCharToAscii,
64 MbAsciiToChar,
66 Delete,
68 Delete2,
70 DefineLocal,
72 CallFunction,
74 Return,
76 Modulo,
78 NewObject,
80 DefineLocal2,
82 InitArray,
84 InitObject,
86 TypeOf,
88 TargetPath,
90 Enumerate,
92 Add2,
94 Less2,
96 Equals2,
98 ToNumber,
100 ToString,
102 PushDuplicate,
104 StackSwap,
106 GetMember,
108 SetMember,
110 Increment,
112 Decrement,
114 CallMethod,
116 NewMethod,
118 InstanceOf,
120 Enumerate2,
122 BitAnd,
124 BitOr,
126 BitXor,
128 BitLShift,
130 BitRShift,
132 BitURShift,
134 StrictEquals,
136 Greater,
138 StringGreater,
140 Extends,
142 GotoFrame(actions::GotoFrame),
144 GetUrl(actions::GetUrl),
146 StoreRegister(actions::StoreRegister),
148 ConstantPool(actions::ConstantPool),
150 WaitForFrame(actions::WaitForFrame),
152 SetTarget(actions::SetTarget),
154 GotoLabel(actions::GoToLabel),
156 WaitForFrame2(actions::WaitForFrame2),
158 DefineFunction2(actions::DefineFunction2),
160 Try(actions::Try),
162 With(actions::With),
164 Push(actions::Push),
166 Jump(actions::Jump),
168 GetUrl2(actions::GetUrl2),
170 DefineFunction(actions::DefineFunction),
172 If(actions::If),
174 Call,
176 GotoFrame2(actions::GotoFrame2),
178 }
180
181#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
182#[serde(rename_all = "snake_case")]
183pub struct Cfg {
184 pub blocks: Vec<CfgBlock>,
185}
186
187#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
188#[serde(rename_all = "snake_case")]
189pub struct CfgLabel(pub String);
190
191#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
192#[serde(tag = "type", rename_all = "kebab-case")]
193pub enum CfgBlock {
194 Error(cfg_blocks::CfgErrorBlock),
195 If(cfg_blocks::CfgIfBlock),
196 Return(cfg_blocks::CfgReturnBlock),
197 Simple(cfg_blocks::CfgSimpleBlock),
198 Throw(cfg_blocks::CfgThrowBlock),
199 Try(cfg_blocks::CfgTryBlock),
200 WaitForFrame(cfg_blocks::CfgWaitForFrameBlock),
201 WaitForFrame2(cfg_blocks::CfgWaitForFrame2Block),
202 With(cfg_blocks::CfgWithBlock),
203}
204
205#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
209#[serde(tag = "action", rename_all = "kebab-case")]
210pub enum CfgAction {
211 Unknown(actions::UnknownAction),
212 Add,
213 And,
214 CastOp,
215 CloneSprite,
216 Divide,
217 Equals,
218 EndDrag,
219 FsCommand2,
220 GetProperty,
221 GetVariable,
222 ImplementsOp,
223 Less,
224 MbStringLength,
225 Multiply,
226 NextFrame,
227 Not,
228 Or,
229 PrevFrame,
230 Play,
231 Pop,
232 RandomNumber,
233 RemoveSprite,
234 SetProperty,
235 SetTarget2,
236 SetVariable,
237 StartDrag,
238 Stop,
239 StopSounds,
240 StringAdd,
241 StringEquals,
242 StringExtract,
243 StringLength,
244 StringLess,
245 Subtract,
246 ToInteger,
247 ToggleQuality,
248 Trace,
249 CharToAscii,
250 AsciiToChar,
251 GetTime,
252 MbStringExtract,
253 MbCharToAscii,
254 MbAsciiToChar,
255 Delete,
256 Delete2,
257 DefineLocal,
258 CallFunction,
259 Modulo,
260 NewObject,
261 DefineLocal2,
262 InitArray,
263 InitObject,
264 TypeOf,
265 TargetPath,
266 Enumerate,
267 Add2,
268 Less2,
269 Equals2,
270 ToNumber,
271 ToString,
272 PushDuplicate,
273 StackSwap,
274 GetMember,
275 SetMember,
276 Increment,
277 Decrement,
278 CallMethod,
279 NewMethod,
280 InstanceOf,
281 Enumerate2,
282 BitAnd,
283 BitOr,
284 BitXor,
285 BitLShift,
286 BitRShift,
287 BitURShift,
288 StrictEquals,
289 Greater,
290 StringGreater,
291 Extends,
292 GotoFrame(actions::GotoFrame),
293 GetUrl(actions::GetUrl),
294 StoreRegister(actions::StoreRegister),
295 ConstantPool(actions::ConstantPool),
296 SetTarget(actions::SetTarget),
297 GotoLabel(actions::GoToLabel),
298 StrictMode(actions::StrictMode),
299 DefineFunction2(cfg_actions::CfgDefineFunction2),
300 Push(actions::Push),
301 GetUrl2(actions::GetUrl2),
302 DefineFunction(cfg_actions::CfgDefineFunction),
303 Call,
304 GotoFrame2(actions::GotoFrame2),
305}
306
307#[cfg(test)]
308mod tests {
309 use crate::Cfg;
310 use ::test_generator::test_resources;
311 use std::path::Path;
312
313 #[test_resources("../tests/avm1/[!.]*/*/")]
314 fn test_cfg(path: &str) {
315 let path: &Path = Path::new(path);
316 let name = path
317 .components()
318 .last()
319 .unwrap()
320 .as_os_str()
321 .to_str()
322 .expect("Failed to retrieve sample name");
323
324 if name == "corrupted-push" || name == "try-jump-to-catch-throw-finally" {
325 return;
326 }
327
328 let cfg_path = path.join("cfg.json");
329
330 let value_json = ::std::fs::read_to_string(cfg_path).expect("Failed to read CFG file");
331
332 let value: Cfg = serde_json_v8::from_str(&value_json).expect("Failed to read CFG");
333
334 let output_json = serde_json_v8::to_string_pretty(&value).expect("Failed to write CFG");
335 let output_json = format!("{}\n", output_json);
336
337 assert_eq!(output_json, value_json)
338 }
339}
340
341#[cfg(test)]
342mod e2e_raw_tests {
343 use super::*;
344 use ::test_generator::test_resources;
345
346 #[test_resources("../tests/raw/*.json")]
347 fn test_parse_action(path: &str) {
348 let file = ::std::fs::File::open(path).unwrap();
349 let reader = ::std::io::BufReader::new(file);
350 serde_json::from_reader::<_, Action>(reader).unwrap();
352 }
353}