use serde::{Deserialize, Serialize};
pub use self::value::Value;
pub mod actions;
pub mod cfg_actions;
pub mod cfg_blocks;
mod float_is;
mod helpers;
mod value;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "action", rename_all = "kebab-case")]
pub enum Action {
Unknown(actions::UnknownAction),
Add,
And,
CastOp,
CloneSprite,
Divide,
Equals,
EndDrag,
FsCommand2,
GetProperty,
GetVariable,
ImplementsOp,
Less,
MbStringLength,
Multiply,
NextFrame,
Not,
Or,
PrevFrame,
Play,
Pop,
RandomNumber,
RemoveSprite,
SetProperty,
SetTarget2,
SetVariable,
StartDrag,
Stop,
StopSounds,
StringAdd,
StringEquals,
StringExtract,
StringLength,
StringLess,
Subtract,
Throw,
ToInteger,
ToggleQuality,
Trace,
CharToAscii,
AsciiToChar,
GetTime,
MbStringExtract,
MbCharToAscii,
MbAsciiToChar,
Delete,
Delete2,
DefineLocal,
CallFunction,
Return,
Modulo,
NewObject,
DefineLocal2,
InitArray,
InitObject,
TypeOf,
TargetPath,
Enumerate,
Add2,
Less2,
Equals2,
ToNumber,
ToString,
PushDuplicate,
StackSwap,
GetMember,
SetMember,
Increment,
Decrement,
CallMethod,
NewMethod,
InstanceOf,
Enumerate2,
BitAnd,
BitOr,
BitXor,
BitLShift,
BitRShift,
BitURShift,
StrictEquals,
Greater,
StringGreater,
Extends,
GotoFrame(actions::GotoFrame),
GetUrl(actions::GetUrl),
StoreRegister(actions::StoreRegister),
ConstantPool(actions::ConstantPool),
WaitForFrame(actions::WaitForFrame),
SetTarget(actions::SetTarget),
GotoLabel(actions::GoToLabel),
WaitForFrame2(actions::WaitForFrame2),
DefineFunction2(actions::DefineFunction2),
Try(actions::Try),
With(actions::With),
Push(actions::Push),
Jump(actions::Jump),
GetUrl2(actions::GetUrl2),
DefineFunction(actions::DefineFunction),
If(actions::If),
Call,
GotoFrame2(actions::GotoFrame2),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct Cfg {
pub blocks: Vec<CfgBlock>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct CfgLabel(pub String);
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum CfgBlock {
Error(cfg_blocks::CfgErrorBlock),
If(cfg_blocks::CfgIfBlock),
Return(cfg_blocks::CfgReturnBlock),
Simple(cfg_blocks::CfgSimpleBlock),
Throw(cfg_blocks::CfgThrowBlock),
Try(cfg_blocks::CfgTryBlock),
WaitForFrame(cfg_blocks::CfgWaitForFrameBlock),
WaitForFrame2(cfg_blocks::CfgWaitForFrame2Block),
With(cfg_blocks::CfgWithBlock),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "action", rename_all = "kebab-case")]
pub enum CfgAction {
Unknown(actions::UnknownAction),
Add,
And,
CastOp,
CloneSprite,
Divide,
Equals,
EndDrag,
FsCommand2,
GetProperty,
GetVariable,
ImplementsOp,
Less,
MbStringLength,
Multiply,
NextFrame,
Not,
Or,
PrevFrame,
Play,
Pop,
RandomNumber,
RemoveSprite,
SetProperty,
SetTarget2,
SetVariable,
StartDrag,
Stop,
StopSounds,
StringAdd,
StringEquals,
StringExtract,
StringLength,
StringLess,
Subtract,
ToInteger,
ToggleQuality,
Trace,
CharToAscii,
AsciiToChar,
GetTime,
MbStringExtract,
MbCharToAscii,
MbAsciiToChar,
Delete,
Delete2,
DefineLocal,
CallFunction,
Modulo,
NewObject,
DefineLocal2,
InitArray,
InitObject,
TypeOf,
TargetPath,
Enumerate,
Add2,
Less2,
Equals2,
ToNumber,
ToString,
PushDuplicate,
StackSwap,
GetMember,
SetMember,
Increment,
Decrement,
CallMethod,
NewMethod,
InstanceOf,
Enumerate2,
BitAnd,
BitOr,
BitXor,
BitLShift,
BitRShift,
BitURShift,
StrictEquals,
Greater,
StringGreater,
Extends,
GotoFrame(actions::GotoFrame),
GetUrl(actions::GetUrl),
StoreRegister(actions::StoreRegister),
ConstantPool(actions::ConstantPool),
SetTarget(actions::SetTarget),
GotoLabel(actions::GoToLabel),
StrictMode(actions::StrictMode),
DefineFunction2(cfg_actions::CfgDefineFunction2),
Push(actions::Push),
GetUrl2(actions::GetUrl2),
DefineFunction(cfg_actions::CfgDefineFunction),
Call,
GotoFrame2(actions::GotoFrame2),
}
#[cfg(test)]
mod tests {
use crate::Cfg;
use ::test_generator::test_resources;
use std::path::Path;
#[test_resources("../tests/avm1/[!.]*/*/")]
fn test_cfg(path: &str) {
let path: &Path = Path::new(path);
let name = path
.components()
.last()
.unwrap()
.as_os_str()
.to_str()
.expect("Failed to retrieve sample name");
if name == "corrupted-push" || name == "try-jump-to-catch-throw-finally" {
return;
}
let cfg_path = path.join("cfg.json");
let value_json = ::std::fs::read_to_string(cfg_path).expect("Failed to read CFG file");
let value: Cfg = serde_json_v8::from_str(&value_json).expect("Failed to read CFG");
let output_json = serde_json_v8::to_string_pretty(&value).expect("Failed to write CFG");
let output_json = format!("{}\n", output_json);
assert_eq!(output_json, value_json)
}
}
#[cfg(test)]
mod e2e_raw_tests {
use super::*;
use ::test_generator::test_resources;
#[test_resources("../tests/raw/*.json")]
fn test_parse_action(path: &str) {
let file = ::std::fs::File::open(path).unwrap();
let reader = ::std::io::BufReader::new(file);
serde_json::from_reader::<_, Action>(reader).unwrap();
}
}