swf/avm1/
types.rs

1use crate::string::SwfStr;
2use bitflags::bitflags;
3use std::num::NonZeroU8;
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum Action<'a> {
7    Add,
8    Add2,
9    And,
10    AsciiToChar,
11    BitAnd,
12    BitLShift,
13    BitOr,
14    BitRShift,
15    BitURShift,
16    BitXor,
17    Call,
18    CallFunction,
19    CallMethod,
20    CastOp,
21    CharToAscii,
22    CloneSprite,
23    ConstantPool(ConstantPool<'a>),
24    Decrement,
25    DefineFunction(DefineFunction<'a>),
26    DefineFunction2(DefineFunction2<'a>),
27    DefineLocal,
28    DefineLocal2,
29    Delete,
30    Delete2,
31    Divide,
32    End,
33    EndDrag,
34    Enumerate,
35    Enumerate2,
36    Equals,
37    Equals2,
38    Extends,
39    GetMember,
40    GetProperty,
41    GetTime,
42    GetUrl(GetUrl<'a>),
43    GetUrl2(GetUrl2),
44    GetVariable,
45    GotoFrame(GotoFrame),
46    GotoFrame2(GotoFrame2),
47    GotoLabel(GotoLabel<'a>),
48    Greater,
49    If(If),
50    ImplementsOp,
51    Increment,
52    InitArray,
53    InitObject,
54    InstanceOf,
55    Jump(Jump),
56    Less,
57    Less2,
58    MBAsciiToChar,
59    MBCharToAscii,
60    MBStringExtract,
61    MBStringLength,
62    Modulo,
63    Multiply,
64    NewMethod,
65    NewObject,
66    NextFrame,
67    Not,
68    Or,
69    Play,
70    Pop,
71    PreviousFrame,
72    Push(Push<'a>),
73    PushDuplicate,
74    RandomNumber,
75    RemoveSprite,
76    Return,
77    SetMember,
78    SetProperty,
79    SetTarget(SetTarget<'a>),
80    SetTarget2,
81    SetVariable,
82    StackSwap,
83    StartDrag,
84    Stop,
85    StopSounds,
86    StoreRegister(StoreRegister),
87    StrictEquals,
88    StringAdd,
89    StringEquals,
90    StringExtract,
91    StringGreater,
92    StringLength,
93    StringLess,
94    Subtract,
95    TargetPath,
96    Throw,
97    ToInteger,
98    ToNumber,
99    ToString,
100    ToggleQuality,
101    Trace,
102    Try(Try<'a>),
103    TypeOf,
104    WaitForFrame(WaitForFrame),
105    WaitForFrame2(WaitForFrame2),
106    With(With<'a>),
107    Unknown(Unknown<'a>),
108}
109
110#[derive(Clone, Debug, Eq, PartialEq)]
111pub struct ConstantPool<'a> {
112    pub strings: Vec<&'a SwfStr>,
113}
114
115#[derive(Clone, Debug, Eq, PartialEq)]
116pub struct DefineFunction<'a> {
117    pub name: &'a SwfStr,
118    pub params: Vec<&'a SwfStr>,
119    pub actions: &'a [u8],
120}
121
122#[derive(Clone, Debug, Eq, PartialEq)]
123pub struct DefineFunction2<'a> {
124    pub name: &'a SwfStr,
125    pub register_count: u8,
126    pub params: Vec<FunctionParam<'a>>,
127    pub flags: FunctionFlags,
128    pub actions: &'a [u8],
129}
130
131impl<'a> From<DefineFunction<'a>> for DefineFunction2<'a> {
132    #[inline]
133    fn from(function: DefineFunction<'a>) -> Self {
134        let params = function
135            .params
136            .into_iter()
137            .map(|param| FunctionParam {
138                name: param,
139                register_index: None,
140            })
141            .collect();
142        Self {
143            name: function.name,
144            register_count: 0,
145            params,
146            flags: FunctionFlags::empty(),
147            actions: function.actions,
148        }
149    }
150}
151
152#[derive(Clone, Debug, Eq, PartialEq)]
153pub struct FunctionParam<'a> {
154    pub name: &'a SwfStr,
155    pub register_index: Option<NonZeroU8>,
156}
157
158bitflags! {
159    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
160    pub struct FunctionFlags: u16 {
161        const PRELOAD_THIS = 1 << 0;
162        const SUPPRESS_THIS = 1 << 1;
163        const PRELOAD_ARGUMENTS = 1 << 2;
164        const SUPPRESS_ARGUMENTS = 1 << 3;
165        const PRELOAD_SUPER = 1 << 4;
166        const SUPPRESS_SUPER = 1 << 5;
167        const PRELOAD_ROOT = 1 << 6;
168        const PRELOAD_PARENT = 1 << 7;
169        const PRELOAD_GLOBAL = 1 << 8;
170    }
171}
172
173#[derive(Clone, Debug, Eq, PartialEq)]
174pub struct GetUrl<'a> {
175    pub url: &'a SwfStr,
176    pub target: &'a SwfStr,
177}
178
179#[derive(Clone, Debug, Eq, PartialEq)]
180pub struct GetUrl2(pub(crate) GetUrlFlags);
181
182impl GetUrl2 {
183    /// Returns the flags for an AVM1 `loadMovie` call.
184    #[inline]
185    pub fn for_load_movie(method: SendVarsMethod) -> Self {
186        let mut flags = Self(GetUrlFlags::LOAD_TARGET);
187        flags.set_send_vars_method(method);
188        flags
189    }
190
191    /// Returns the flags for an AVM1 `getURL` call.
192    #[inline]
193    pub fn for_get_url(method: SendVarsMethod) -> Self {
194        let mut flags = Self(GetUrlFlags::empty());
195        flags.set_send_vars_method(method);
196        flags
197    }
198
199    /// Returns the flags for an AVM1 `loadVariables` or `LoadVars.load` call.
200    #[inline]
201    pub fn for_load_vars(method: SendVarsMethod) -> Self {
202        let mut flags = Self(GetUrlFlags::LOAD_VARIABLES);
203        flags.set_send_vars_method(method);
204        flags
205    }
206
207    /// The HTTP method used for sending data.
208    #[inline]
209    pub fn send_vars_method(&self) -> SendVarsMethod {
210        match self.0 & GetUrlFlags::METHOD_MASK {
211            GetUrlFlags::METHOD_NONE => SendVarsMethod::None,
212            GetUrlFlags::METHOD_GET => SendVarsMethod::Get,
213            GetUrlFlags::METHOD_POST => SendVarsMethod::Post,
214            _ => unreachable!(),
215        }
216    }
217
218    /// Sets the HTTP method used for sending data.
219    #[inline]
220    pub fn set_send_vars_method(&mut self, method: SendVarsMethod) {
221        self.0 -= GetUrlFlags::METHOD_MASK;
222        self.0 |= GetUrlFlags::from_bits(method as u8).unwrap();
223    }
224
225    /// Whether this action will load a movie or image into a display object.
226    #[inline]
227    pub fn is_target_sprite(&self) -> bool {
228        self.0.contains(GetUrlFlags::LOAD_TARGET)
229    }
230
231    /// Whether this action will load variables into an ActionScript object.
232    #[inline]
233    pub fn is_load_vars(&self) -> bool {
234        self.0.contains(GetUrlFlags::LOAD_VARIABLES)
235    }
236}
237
238bitflags! {
239    // NOTE: The GetURL2 flag layout is listed backwards in the SWF19 specs.
240    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
241    pub(crate) struct GetUrlFlags: u8 {
242        const METHOD_NONE = 0;
243        const METHOD_GET = 1;
244        const METHOD_POST = 2;
245        const METHOD_MASK = 3;
246
247        const LOAD_TARGET = 1 << 6;
248        const LOAD_VARIABLES = 1 << 7;
249    }
250}
251
252#[derive(Clone, Copy, Debug, Eq, PartialEq)]
253#[repr(u8)]
254pub enum SendVarsMethod {
255    None = 0,
256    Get = 1,
257    Post = 2,
258}
259
260#[derive(Clone, Debug, Eq, PartialEq)]
261pub struct GotoFrame {
262    pub frame: u16,
263}
264
265#[derive(Clone, Debug, Eq, PartialEq)]
266pub struct GotoFrame2 {
267    pub set_playing: bool,
268    pub scene_offset: u16,
269}
270
271#[derive(Clone, Debug, Eq, PartialEq)]
272pub struct GotoLabel<'a> {
273    pub label: &'a SwfStr,
274}
275
276#[derive(Clone, Debug, Eq, PartialEq)]
277pub struct If {
278    pub offset: i16,
279}
280
281#[derive(Clone, Debug, Eq, PartialEq)]
282pub struct Jump {
283    pub offset: i16,
284}
285
286#[derive(Clone, Debug, PartialEq)]
287pub struct Push<'a> {
288    pub values: Vec<Value<'a>>,
289}
290
291#[derive(Clone, Debug, PartialEq)]
292pub enum Value<'a> {
293    Undefined,
294    Null,
295    Bool(bool),
296    Int(i32),
297    Float(f32),
298    Double(f64),
299    Str(&'a SwfStr),
300    Register(u8),
301    ConstantPool(u16),
302}
303
304#[derive(Clone, Debug, Eq, PartialEq)]
305pub struct SetTarget<'a> {
306    pub target: &'a SwfStr,
307}
308
309#[derive(Clone, Copy, Debug, Eq, PartialEq)]
310pub struct StoreRegister {
311    pub register: u8,
312}
313
314#[derive(Clone, Debug, Eq, PartialEq)]
315pub struct Try<'a> {
316    pub try_body: &'a [u8],
317    pub catch_body: Option<(CatchVar<'a>, &'a [u8])>,
318    pub finally_body: Option<&'a [u8]>,
319}
320
321#[derive(Clone, Debug, Eq, PartialEq)]
322pub enum CatchVar<'a> {
323    Var(&'a SwfStr),
324    Register(u8),
325}
326
327bitflags! {
328    pub struct TryFlags: u8 {
329        const CATCH_BLOCK = 1 << 0;
330        const FINALLY_BLOCK = 1 << 1;
331        const CATCH_IN_REGISTER = 1 << 2;
332    }
333}
334
335#[derive(Clone, Debug, Eq, PartialEq)]
336pub struct WaitForFrame {
337    pub frame: u16,
338    pub num_actions_to_skip: u8,
339}
340
341#[derive(Clone, Debug, Eq, PartialEq)]
342pub struct WaitForFrame2 {
343    pub num_actions_to_skip: u8,
344}
345
346#[derive(Clone, Debug, Eq, PartialEq)]
347pub struct With<'a> {
348    pub actions: &'a [u8],
349}
350
351#[derive(Clone, Debug, Eq, PartialEq)]
352pub struct Unknown<'a> {
353    pub opcode: u8,
354    pub data: &'a [u8],
355}