hydroper_swf/avm2/
read.rs

1use crate::avm2::types::*;
2use crate::error::{Error, Result};
3use crate::extensions::ReadSwfExt;
4use std::io::Read;
5
6pub struct Reader<'a> {
7    input: &'a [u8],
8}
9
10impl<'a> ReadSwfExt<'a> for Reader<'a> {
11    #[inline(always)]
12    fn as_mut_slice(&mut self) -> &mut &'a [u8] {
13        &mut self.input
14    }
15
16    #[inline(always)]
17    fn as_slice(&self) -> &'a [u8] {
18        self.input
19    }
20}
21
22impl<'a> Reader<'a> {
23    pub fn new(input: &'a [u8]) -> Self {
24        Self { input }
25    }
26
27    #[inline]
28    pub fn seek(&mut self, data: &'a [u8], relative_offset: i32) {
29        ReadSwfExt::seek(self, data, relative_offset as isize)
30    }
31
32    #[inline]
33    pub fn seek_absolute(&mut self, data: &'a [u8], pos: usize) {
34        ReadSwfExt::seek_absolute(self, data, pos)
35    }
36
37    pub fn read(&mut self) -> Result<AbcFile> {
38        let minor_version = self.read_u16()?;
39        let major_version = self.read_u16()?;
40        let constant_pool = self.read_constant_pool()?;
41
42        let len = self.read_u30()?;
43        let mut methods = Vec::with_capacity(len as usize);
44        for _ in 0..len {
45            methods.push(self.read_method()?);
46        }
47
48        let len = self.read_u30()?;
49        let metadata = self.read_metadata(len)?;
50
51        let len = self.read_u30()?;
52        let mut instances = Vec::with_capacity(len as usize);
53        for _ in 0..len {
54            instances.push(self.read_instance()?);
55        }
56
57        let mut classes = Vec::with_capacity(len as usize);
58        for _ in 0..len {
59            classes.push(self.read_class()?);
60        }
61
62        let len = self.read_u30()?;
63        let mut scripts = Vec::with_capacity(len as usize);
64        for _ in 0..len {
65            scripts.push(self.read_script()?);
66        }
67
68        let len = self.read_u30()?;
69        let mut method_bodies = Vec::with_capacity(len as usize);
70        for _ in 0..len {
71            method_bodies.push(self.read_method_body()?);
72        }
73
74        Ok(AbcFile {
75            major_version,
76            minor_version,
77
78            constant_pool,
79            methods,
80            metadata,
81            instances,
82            classes,
83            scripts,
84            method_bodies,
85        })
86    }
87
88    fn read_u30(&mut self) -> Result<u32> {
89        self.read_encoded_u32()
90    }
91
92    fn read_i24(&mut self) -> Result<i32> {
93        Ok(i32::from(self.read_u8()?)
94            | (i32::from(self.read_u8()?) << 8)
95            | (i32::from(self.read_u8()? as i8) << 16))
96    }
97
98    fn read_i32(&mut self) -> Result<i32> {
99        Ok(self.read_encoded_u32()? as i32)
100    }
101
102    fn read_string(&mut self) -> Result<Vec<u8>> {
103        let len = self.read_u30()?;
104        // TODO: Avoid allocating a String.
105        let mut s = Vec::with_capacity(len as usize);
106        self.read_slice(len as usize)?.read_to_end(&mut s)?;
107        Ok(s)
108    }
109
110    fn read_index<T>(&mut self) -> Result<Index<T>> {
111        use std::marker::PhantomData;
112        Ok(Index(self.read_u30()?, PhantomData))
113    }
114
115    fn read_namespace(&mut self) -> Result<Namespace> {
116        let kind = self.read_u8()?;
117        let name: Index<String> = self.read_index()?;
118        // TODO: AVM2 specs say that "non-system" namespaces
119        // should have an empty name?
120        Ok(match kind {
121            0x05 => Namespace::Private(name),
122            0x08 => Namespace::Namespace(name),
123            0x16 => Namespace::Package(name),
124            0x17 => Namespace::PackageInternal(name),
125            0x18 => Namespace::Protected(name),
126            0x19 => Namespace::Explicit(name),
127            0x1a => Namespace::StaticProtected(name),
128            _ => return Err(Error::invalid_data("Invalid namespace kind")),
129        })
130    }
131
132    fn read_namespace_set(&mut self) -> Result<NamespaceSet> {
133        let len = self.read_u30()?;
134        let mut namespace_set = Vec::with_capacity(len as usize);
135        for _ in 0..len {
136            namespace_set.push(self.read_index()?);
137        }
138        Ok(namespace_set)
139    }
140
141    fn read_multiname(&mut self) -> Result<Multiname> {
142        let kind = self.read_u8()?;
143        Ok(match kind {
144            0x07 => Multiname::QName {
145                namespace: self.read_index()?,
146                name: self.read_index()?,
147            },
148            0x0d => Multiname::QNameA {
149                namespace: self.read_index()?,
150                name: self.read_index()?,
151            },
152            0x0f => Multiname::RTQName {
153                name: self.read_index()?,
154            },
155            0x10 => Multiname::RTQNameA {
156                name: self.read_index()?,
157            },
158            0x11 => Multiname::RTQNameL,
159            0x12 => Multiname::RTQNameLA,
160            0x09 => Multiname::Multiname {
161                name: self.read_index()?,
162                namespace_set: self.read_index()?,
163            },
164            0x0e => Multiname::MultinameA {
165                name: self.read_index()?,
166                namespace_set: self.read_index()?,
167            },
168            0x1b => Multiname::MultinameL {
169                namespace_set: self.read_index()?,
170            },
171            0x1c => Multiname::MultinameLA {
172                namespace_set: self.read_index()?,
173            },
174            0x1d => {
175                let base_type = self.read_index()?;
176                let count = self.read_u30()?;
177                let mut parameters = Vec::with_capacity(count as usize);
178
179                for _ in 0..count {
180                    parameters.push(self.read_index()?);
181                }
182
183                Multiname::TypeName {
184                    base_type,
185                    parameters,
186                }
187            }
188            _ => return Err(Error::invalid_data("Invalid multiname kind")),
189        })
190    }
191
192    fn read_constant_pool(&mut self) -> Result<ConstantPool> {
193        let len = self.read_u30()?.saturating_sub(1);
194        let mut ints = Vec::with_capacity(len as usize);
195        for _ in 0..len {
196            ints.push(self.read_i32()?);
197        }
198
199        let len = self.read_u30()?.saturating_sub(1);
200        let mut uints = Vec::with_capacity(len as usize);
201        for _ in 0..len {
202            uints.push(self.read_u30()?);
203        }
204
205        let len = self.read_u30()?.saturating_sub(1);
206        let mut doubles = Vec::with_capacity(len as usize);
207        for _ in 0..len {
208            doubles.push(self.read_f64()?);
209        }
210
211        let len = self.read_u30()?.saturating_sub(1);
212        let mut strings = Vec::with_capacity(len as usize);
213        for _ in 0..len {
214            strings.push(self.read_string()?);
215        }
216
217        let len = self.read_u30()?.saturating_sub(1);
218        let mut namespaces = Vec::with_capacity(len as usize);
219        for _ in 0..len {
220            namespaces.push(self.read_namespace()?);
221        }
222
223        let len = self.read_u30()?.saturating_sub(1);
224        let mut namespace_sets = Vec::with_capacity(len as usize);
225        for _ in 0..len {
226            namespace_sets.push(self.read_namespace_set()?);
227        }
228
229        let len = self.read_u30()?.saturating_sub(1);
230        let mut multinames = Vec::with_capacity(len as usize);
231        for _ in 0..len {
232            multinames.push(self.read_multiname()?);
233        }
234
235        Ok(ConstantPool {
236            ints,
237            uints,
238            doubles,
239            strings,
240            namespaces,
241            namespace_sets,
242            multinames,
243        })
244    }
245
246    fn read_method(&mut self) -> Result<Method> {
247        let num_params = self.read_u30()?;
248        let return_type = self.read_index()?;
249        let mut params = Vec::with_capacity(num_params as usize);
250        for _ in 0..num_params {
251            params.push(MethodParam {
252                kind: self.read_index()?,
253                name: None,
254                default_value: None,
255            })
256        }
257        let name = self.read_index()?;
258        let flags = MethodFlags::from_bits_truncate(self.read_u8()?);
259
260        if flags.contains(MethodFlags::HAS_OPTIONAL) {
261            let num_optional_params = self.read_u30()? as usize;
262            if let Some(start) = params.len().checked_sub(num_optional_params) {
263                for param in &mut params[start..] {
264                    param.default_value = Some(self.read_constant_value()?);
265                }
266            } else {
267                return Err(Error::invalid_data("Too many optional parameters"));
268            }
269        }
270
271        if flags.contains(MethodFlags::HAS_PARAM_NAMES) {
272            for param in &mut params {
273                param.name = Some(self.read_index()?);
274            }
275        }
276
277        Ok(Method {
278            name,
279            params,
280            return_type,
281            flags,
282        })
283    }
284
285    fn read_constant_value(&mut self) -> Result<DefaultValue> {
286        let index = self.read_u30()?;
287        Ok(match self.read_u8()? {
288            0x00 => DefaultValue::Undefined,
289            0x01 => DefaultValue::String(Index::new(index)),
290            0x03 => DefaultValue::Int(Index::new(index)),
291            0x04 => DefaultValue::Uint(Index::new(index)),
292            0x05 => DefaultValue::Private(Index::new(index)),
293            0x06 => DefaultValue::Double(Index::new(index)),
294            0x08 => DefaultValue::Namespace(Index::new(index)),
295            0x0a => DefaultValue::False,
296            0x0b => DefaultValue::True,
297            0x0c => DefaultValue::Null,
298            0x16 => DefaultValue::Package(Index::new(index)),
299            0x17 => DefaultValue::PackageInternal(Index::new(index)),
300            0x18 => DefaultValue::Protected(Index::new(index)),
301            0x19 => DefaultValue::Explicit(Index::new(index)),
302            0x1a => DefaultValue::StaticProtected(Index::new(index)),
303            _ => return Err(Error::invalid_data("Invalid default value")),
304        })
305    }
306
307    fn read_optional_value(&mut self) -> Result<Option<DefaultValue>> {
308        let index = self.read_u30()?;
309        if index == 0 {
310            Ok(None)
311        } else {
312            Ok(Some(match self.read_u8()? {
313                0x00 => DefaultValue::Undefined,
314                0x01 => DefaultValue::String(Index::new(index)),
315                0x03 => DefaultValue::Int(Index::new(index)),
316                0x04 => DefaultValue::Uint(Index::new(index)),
317                0x05 => DefaultValue::Private(Index::new(index)),
318                0x06 => DefaultValue::Double(Index::new(index)),
319                0x08 => DefaultValue::Namespace(Index::new(index)),
320                0x0a => DefaultValue::False,
321                0x0b => DefaultValue::True,
322                0x0c => DefaultValue::Null,
323                0x16 => DefaultValue::Package(Index::new(index)),
324                0x17 => DefaultValue::PackageInternal(Index::new(index)),
325                0x18 => DefaultValue::Protected(Index::new(index)),
326                0x19 => DefaultValue::Explicit(Index::new(index)),
327                0x1a => DefaultValue::StaticProtected(Index::new(index)),
328                _ => return Err(Error::invalid_data("Invalid default value")),
329            }))
330        }
331    }
332
333    fn read_metadata(&mut self, len: u32) -> Result<Vec<Metadata>> {
334        let mut metadata = Vec::with_capacity(len as usize);
335        for _ in 0..len {
336            let name = self.read_index()?;
337            let num_items = self.read_u30()?;
338            let mut key_value_data = Vec::with_capacity(num_items as usize * 2);
339
340            // Data includes the keys and values
341            for _ in 0..num_items * 2 {
342                key_value_data.push(self.read_index()?);
343            }
344
345            // Split them up here
346            let mut items = Vec::with_capacity(num_items as usize);
347            for i in 0..num_items {
348                items.push(MetadataItem {
349                    key: key_value_data[i as usize],
350                    value: key_value_data[(num_items + i) as usize],
351                })
352            }
353
354            metadata.push(Metadata { name, items });
355        }
356
357        Ok(metadata)
358    }
359
360    fn read_instance(&mut self) -> Result<Instance> {
361        let name = self.read_index()?;
362        let super_name = self.read_index()?;
363        let flags = self.read_u8()?;
364
365        let protected_namespace = if flags & 0x08 != 0 {
366            Some(self.read_index()?)
367        } else {
368            None
369        };
370
371        let num_interfaces = self.read_u30()?;
372        let mut interfaces = Vec::with_capacity(num_interfaces as usize);
373        for _ in 0..num_interfaces {
374            interfaces.push(self.read_index()?);
375        }
376
377        let init_method = self.read_index()?;
378
379        let num_traits = self.read_u30()?;
380        let mut traits = Vec::with_capacity(num_traits as usize);
381        for _ in 0..num_traits {
382            traits.push(self.read_trait()?);
383        }
384
385        Ok(Instance {
386            name,
387            super_name,
388            protected_namespace,
389            interfaces,
390            traits,
391            init_method,
392            is_sealed: flags & 0x01 != 0,
393            is_final: flags & 0x02 != 0,
394            is_interface: flags & 0x04 != 0,
395        })
396    }
397
398    fn read_class(&mut self) -> Result<Class> {
399        let init_method = self.read_index()?;
400        let num_traits = self.read_u30()?;
401        let mut traits = Vec::with_capacity(num_traits as usize);
402        for _ in 0..num_traits {
403            traits.push(self.read_trait()?);
404        }
405        Ok(Class {
406            init_method,
407            traits,
408        })
409    }
410
411    fn read_script(&mut self) -> Result<Script> {
412        let init_method = self.read_index()?;
413        let num_traits = self.read_u30()?;
414        let mut traits = Vec::with_capacity(num_traits as usize);
415        for _ in 0..num_traits {
416            traits.push(self.read_trait()?);
417        }
418        Ok(Script {
419            init_method,
420            traits,
421        })
422    }
423
424    fn read_trait(&mut self) -> Result<Trait> {
425        let name = self.read_index()?;
426        let flags = self.read_u8()?;
427        let kind = match flags & 0b1111 {
428            0 => TraitKind::Slot {
429                slot_id: self.read_u30()?,
430                type_name: self.read_index()?,
431                value: self.read_optional_value()?,
432            },
433            1 => TraitKind::Method {
434                disp_id: self.read_u30()?,
435                method: self.read_index()?,
436            },
437            2 => TraitKind::Getter {
438                disp_id: self.read_u30()?,
439                method: self.read_index()?,
440            },
441            3 => TraitKind::Setter {
442                disp_id: self.read_u30()?,
443                method: self.read_index()?,
444            },
445            4 => TraitKind::Class {
446                slot_id: self.read_u30()?,
447                class: self.read_index()?,
448            },
449            5 => TraitKind::Function {
450                slot_id: self.read_u30()?,
451                function: self.read_index()?,
452            },
453            6 => TraitKind::Const {
454                slot_id: self.read_u30()?,
455                type_name: self.read_index()?,
456                value: self.read_optional_value()?,
457            },
458            _ => return Err(Error::invalid_data("Invalid trait kind")),
459        };
460
461        let mut metadata = vec![];
462        if flags & 0b0100_0000 != 0 {
463            let num_metadata = self.read_u30()?;
464            metadata.reserve(num_metadata as usize);
465            for _ in 0..num_metadata {
466                metadata.push(self.read_index()?);
467            }
468        }
469
470        Ok(Trait {
471            name,
472            kind,
473            metadata,
474            is_final: flags & 0b0001_0000 != 0,
475            is_override: flags & 0b0010_0000 != 0,
476        })
477    }
478
479    fn read_method_body(&mut self) -> Result<MethodBody> {
480        let method = self.read_index()?;
481        let max_stack = self.read_u30()?;
482        let num_locals = self.read_u30()?;
483        let init_scope_depth = self.read_u30()?;
484        let max_scope_depth = self.read_u30()?;
485
486        // Read the code data.
487        let code_len = self.read_u30()?;
488        // TODO: Avoid allocating a Vec.
489        let code = self.read_slice(code_len as usize)?.to_vec();
490
491        let num_exceptions = self.read_u30()?;
492        let mut exceptions = Vec::with_capacity(num_exceptions as usize);
493        for _ in 0..num_exceptions {
494            exceptions.push(self.read_exception()?);
495        }
496
497        let num_traits = self.read_u30()?;
498        let mut traits = Vec::with_capacity(num_traits as usize);
499        for _ in 0..num_traits {
500            traits.push(self.read_trait()?);
501        }
502
503        Ok(MethodBody {
504            method,
505            max_stack,
506            num_locals,
507            init_scope_depth,
508            max_scope_depth,
509            code,
510            exceptions,
511            traits,
512        })
513    }
514
515    pub fn read_op(&mut self) -> Result<Op> {
516        use crate::avm2::opcode::OpCode;
517        use num_traits::FromPrimitive;
518
519        let byte = self.read_u8()?;
520        let opcode = match OpCode::from_u8(byte) {
521            Some(o) => o,
522            None => return Err(Error::invalid_data(format!("Unknown ABC opcode {byte:#x}"))),
523        };
524
525        let op = match opcode {
526            OpCode::Add => Op::Add,
527            OpCode::AddI => Op::AddI,
528            OpCode::ApplyType => Op::ApplyType {
529                num_types: self.read_u30()?,
530            },
531            OpCode::AsType => Op::AsType {
532                type_name: self.read_index()?,
533            },
534            OpCode::AsTypeLate => Op::AsTypeLate,
535            OpCode::BitAnd => Op::BitAnd,
536            OpCode::BitNot => Op::BitNot,
537            OpCode::BitOr => Op::BitOr,
538            OpCode::BitXor => Op::BitXor,
539            OpCode::Bkpt => Op::Bkpt,
540            OpCode::BkptLine => Op::BkptLine {
541                line_num: self.read_u30()?,
542            },
543            OpCode::Call => Op::Call {
544                num_args: self.read_u30()?,
545            },
546            OpCode::CallMethod => Op::CallMethod {
547                index: self.read_u30()?,
548                num_args: self.read_u30()?,
549            },
550            OpCode::CallProperty => Op::CallProperty {
551                index: self.read_index()?,
552                num_args: self.read_u30()?,
553            },
554            OpCode::CallPropLex => Op::CallPropLex {
555                index: self.read_index()?,
556                num_args: self.read_u30()?,
557            },
558            OpCode::CallPropVoid => Op::CallPropVoid {
559                index: self.read_index()?,
560                num_args: self.read_u30()?,
561            },
562            OpCode::CallStatic => Op::CallStatic {
563                index: self.read_index()?,
564                num_args: self.read_u30()?,
565            },
566            OpCode::CallSuper => Op::CallSuper {
567                index: self.read_index()?,
568                num_args: self.read_u30()?,
569            },
570            OpCode::CallSuperVoid => Op::CallSuperVoid {
571                index: self.read_index()?,
572                num_args: self.read_u30()?,
573            },
574            OpCode::CheckFilter => Op::CheckFilter,
575            OpCode::Coerce => Op::Coerce {
576                index: self.read_index()?,
577            },
578            OpCode::CoerceA => Op::CoerceA,
579            OpCode::CoerceB => Op::CoerceB,
580            OpCode::CoerceD => Op::CoerceD,
581            OpCode::CoerceI => Op::CoerceI,
582            OpCode::CoerceO => Op::CoerceO,
583            OpCode::CoerceS => Op::CoerceS,
584            OpCode::CoerceU => Op::CoerceU,
585            OpCode::Construct => Op::Construct {
586                num_args: self.read_u30()?,
587            },
588            OpCode::ConstructProp => Op::ConstructProp {
589                index: self.read_index()?,
590                num_args: self.read_u30()?,
591            },
592            OpCode::ConstructSuper => Op::ConstructSuper {
593                num_args: self.read_u30()?,
594            },
595            OpCode::ConvertB => Op::ConvertB,
596            OpCode::ConvertD => Op::ConvertD,
597            OpCode::ConvertI => Op::ConvertI,
598            OpCode::ConvertO => Op::ConvertO,
599            OpCode::ConvertS => Op::ConvertS,
600            OpCode::ConvertU => Op::ConvertU,
601            OpCode::Debug => {
602                let op = Op::Debug {
603                    is_local_register: self.read_u8()? != 0,
604                    register_name: self.read_index()?,
605                    register: self.read_u8()?,
606                };
607                self.read_u30()?; // Unused
608                op
609            }
610            OpCode::DebugFile => Op::DebugFile {
611                file_name: self.read_index()?,
612            },
613            OpCode::DebugLine => Op::DebugLine {
614                line_num: self.read_u30()?,
615            },
616            OpCode::DecLocal => Op::DecLocal {
617                index: self.read_u30()?,
618            },
619            OpCode::DecLocalI => Op::DecLocalI {
620                index: self.read_u30()?,
621            },
622            OpCode::Decrement => Op::Decrement,
623            OpCode::DecrementI => Op::DecrementI,
624            OpCode::DeleteProperty => Op::DeleteProperty {
625                index: self.read_index()?,
626            },
627            OpCode::Divide => Op::Divide,
628            OpCode::Dup => Op::Dup,
629            OpCode::Dxns => Op::Dxns {
630                index: self.read_index()?,
631            },
632            OpCode::DxnsLate => Op::DxnsLate,
633            OpCode::Equals => Op::Equals,
634            OpCode::EscXAttr => Op::EscXAttr,
635            OpCode::EscXElem => Op::EscXElem,
636            OpCode::FindDef => Op::FindDef {
637                index: self.read_index()?,
638            },
639            OpCode::FindProperty => Op::FindProperty {
640                index: self.read_index()?,
641            },
642            OpCode::FindPropStrict => Op::FindPropStrict {
643                index: self.read_index()?,
644            },
645            OpCode::GetDescendants => Op::GetDescendants {
646                index: self.read_index()?,
647            },
648            OpCode::GetGlobalScope => Op::GetGlobalScope,
649            OpCode::GetGlobalSlot => Op::GetGlobalSlot {
650                index: self.read_u30()?,
651            },
652            OpCode::GetLex => Op::GetLex {
653                index: self.read_index()?,
654            },
655            OpCode::GetLocal => Op::GetLocal {
656                index: self.read_u30()?,
657            },
658            OpCode::GetLocal0 => Op::GetLocal { index: 0 },
659            OpCode::GetLocal1 => Op::GetLocal { index: 1 },
660            OpCode::GetLocal2 => Op::GetLocal { index: 2 },
661            OpCode::GetLocal3 => Op::GetLocal { index: 3 },
662            OpCode::GetOuterScope => Op::GetOuterScope {
663                index: self.read_u30()?,
664            },
665            OpCode::GetProperty => Op::GetProperty {
666                index: self.read_index()?,
667            },
668            OpCode::GetScopeObject => Op::GetScopeObject {
669                index: self.read_u8()?,
670            },
671            OpCode::GetSlot => Op::GetSlot {
672                index: self.read_u30()?,
673            },
674            OpCode::GetSuper => Op::GetSuper {
675                index: self.read_index()?,
676            },
677            OpCode::GreaterEquals => Op::GreaterEquals,
678            OpCode::GreaterThan => Op::GreaterThan,
679            OpCode::HasNext => Op::HasNext,
680            OpCode::HasNext2 => Op::HasNext2 {
681                object_register: self.read_u30()?,
682                index_register: self.read_u30()?,
683            },
684            OpCode::IfEq => Op::IfEq {
685                offset: self.read_i24()?,
686            },
687            OpCode::IfFalse => Op::IfFalse {
688                offset: self.read_i24()?,
689            },
690            OpCode::IfGe => Op::IfGe {
691                offset: self.read_i24()?,
692            },
693            OpCode::IfGt => Op::IfGt {
694                offset: self.read_i24()?,
695            },
696            OpCode::IfLe => Op::IfLe {
697                offset: self.read_i24()?,
698            },
699            OpCode::IfLt => Op::IfLt {
700                offset: self.read_i24()?,
701            },
702            OpCode::IfNge => Op::IfNge {
703                offset: self.read_i24()?,
704            },
705            OpCode::IfNgt => Op::IfNgt {
706                offset: self.read_i24()?,
707            },
708            OpCode::IfNle => Op::IfNle {
709                offset: self.read_i24()?,
710            },
711            OpCode::IfNlt => Op::IfNlt {
712                offset: self.read_i24()?,
713            },
714            OpCode::IfNe => Op::IfNe {
715                offset: self.read_i24()?,
716            },
717            OpCode::IfStrictEq => Op::IfStrictEq {
718                offset: self.read_i24()?,
719            },
720            OpCode::IfStrictNe => Op::IfStrictNe {
721                offset: self.read_i24()?,
722            },
723            OpCode::IfTrue => Op::IfTrue {
724                offset: self.read_i24()?,
725            },
726            OpCode::In => Op::In,
727            OpCode::IncLocal => Op::IncLocal {
728                index: self.read_u30()?,
729            },
730            OpCode::IncLocalI => Op::IncLocalI {
731                index: self.read_u30()?,
732            },
733            OpCode::Increment => Op::Increment,
734            OpCode::IncrementI => Op::IncrementI,
735            OpCode::InitProperty => Op::InitProperty {
736                index: self.read_index()?,
737            },
738            OpCode::InstanceOf => Op::InstanceOf,
739            OpCode::IsType => Op::IsType {
740                index: self.read_index()?,
741            },
742            OpCode::IsTypeLate => Op::IsTypeLate,
743            OpCode::Jump => Op::Jump {
744                offset: self.read_i24()?,
745            },
746            OpCode::Kill => Op::Kill {
747                index: self.read_u30()?,
748            },
749            OpCode::Label => Op::Label,
750            OpCode::LessEquals => Op::LessEquals,
751            OpCode::LessThan => Op::LessThan,
752            OpCode::Lf32 => Op::Lf32,
753            OpCode::Lf64 => Op::Lf64,
754            OpCode::Li16 => Op::Li16,
755            OpCode::Li32 => Op::Li32,
756            OpCode::Li8 => Op::Li8,
757            OpCode::LookupSwitch => Op::LookupSwitch(Box::new(LookupSwitch {
758                default_offset: self.read_i24()?,
759                case_offsets: {
760                    let num_cases = self.read_u30()? + 1;
761                    let mut case_offsets = Vec::with_capacity(num_cases as usize);
762                    for _ in 0..num_cases {
763                        case_offsets.push(self.read_i24()?);
764                    }
765                    case_offsets.into()
766                },
767            })),
768            OpCode::LShift => Op::LShift,
769            OpCode::Modulo => Op::Modulo,
770            OpCode::Multiply => Op::Multiply,
771            OpCode::MultiplyI => Op::MultiplyI,
772            OpCode::Negate => Op::Negate,
773            OpCode::NegateI => Op::NegateI,
774            OpCode::NewActivation => Op::NewActivation,
775            OpCode::NewArray => Op::NewArray {
776                num_args: self.read_u30()?,
777            },
778            OpCode::NewCatch => Op::NewCatch {
779                index: self.read_index()?,
780            },
781            OpCode::NewClass => Op::NewClass {
782                index: self.read_index()?,
783            },
784            OpCode::NewFunction => Op::NewFunction {
785                index: self.read_index()?,
786            },
787            OpCode::NewObject => Op::NewObject {
788                num_args: self.read_u30()?,
789            },
790            OpCode::NextName => Op::NextName,
791            OpCode::NextValue => Op::NextValue,
792            OpCode::Nop => Op::Nop,
793            OpCode::Not => Op::Not,
794            OpCode::Pop => Op::Pop,
795            OpCode::PopScope => Op::PopScope,
796            OpCode::PushByte => Op::PushByte {
797                value: self.read_u8()?,
798            },
799            OpCode::PushDouble => Op::PushDouble {
800                value: self.read_index()?,
801            },
802            OpCode::PushFalse => Op::PushFalse,
803            OpCode::PushInt => Op::PushInt {
804                value: self.read_index()?,
805            },
806            OpCode::PushNamespace => Op::PushNamespace {
807                value: self.read_index()?,
808            },
809            OpCode::PushNaN => Op::PushNaN,
810            OpCode::PushNull => Op::PushNull,
811            OpCode::PushScope => Op::PushScope,
812            OpCode::PushShort => Op::PushShort {
813                value: self.read_u30()? as i16,
814            },
815            OpCode::PushString => Op::PushString {
816                value: self.read_index()?,
817            },
818            OpCode::PushTrue => Op::PushTrue,
819            OpCode::PushUint => Op::PushUint {
820                value: self.read_index()?,
821            },
822            OpCode::PushUndefined => Op::PushUndefined,
823            OpCode::PushWith => Op::PushWith,
824            OpCode::ReturnValue => Op::ReturnValue,
825            OpCode::ReturnVoid => Op::ReturnVoid,
826            OpCode::RShift => Op::RShift,
827            OpCode::SetLocal => Op::SetLocal {
828                index: self.read_u30()?,
829            },
830            OpCode::SetLocal0 => Op::SetLocal { index: 0 },
831            OpCode::SetLocal1 => Op::SetLocal { index: 1 },
832            OpCode::SetLocal2 => Op::SetLocal { index: 2 },
833            OpCode::SetLocal3 => Op::SetLocal { index: 3 },
834            OpCode::SetGlobalSlot => Op::SetGlobalSlot {
835                index: self.read_u30()?,
836            },
837            OpCode::SetProperty => Op::SetProperty {
838                index: self.read_index()?,
839            },
840            OpCode::SetSlot => Op::SetSlot {
841                index: self.read_u30()?,
842            },
843            OpCode::SetSuper => Op::SetSuper {
844                index: self.read_index()?,
845            },
846            OpCode::Sf32 => Op::Sf32,
847            OpCode::Sf64 => Op::Sf64,
848            OpCode::Si16 => Op::Si16,
849            OpCode::Si32 => Op::Si32,
850            OpCode::Si8 => Op::Si8,
851            OpCode::StrictEquals => Op::StrictEquals,
852            OpCode::Subtract => Op::Subtract,
853            OpCode::SubtractI => Op::SubtractI,
854            OpCode::Swap => Op::Swap,
855            OpCode::Sxi1 => Op::Sxi1,
856            OpCode::Sxi16 => Op::Sxi16,
857            OpCode::Sxi8 => Op::Sxi8,
858            OpCode::Timestamp => Op::Timestamp,
859            OpCode::Throw => Op::Throw,
860            OpCode::TypeOf => Op::TypeOf,
861            OpCode::URShift => Op::URShift,
862        };
863
864        Ok(op)
865    }
866
867    fn read_exception(&mut self) -> Result<Exception> {
868        Ok(Exception {
869            from_offset: self.read_u30()?,
870            to_offset: self.read_u30()?,
871            target_offset: self.read_u30()?,
872            type_name: self.read_index()?,
873            variable_name: self.read_index()?,
874        })
875    }
876}
877
878#[cfg(test)]
879#[allow(clippy::unusual_byte_groupings)]
880pub mod tests {
881    use super::*;
882    use crate::test_data;
883
884    pub fn read_abc_from_file(path: &str) -> Vec<u8> {
885        use crate::types::Tag;
886        let data = std::fs::read(path).unwrap();
887        let swf_buf = crate::decompress_swf(&data[..]).unwrap();
888        let swf = crate::parse_swf(&swf_buf).unwrap();
889        for tag in swf.tags {
890            if let Tag::DoAbc2(do_abc) = tag {
891                return do_abc.data.to_vec();
892            }
893        }
894        panic!("ABC tag not found in {path}");
895    }
896
897    #[test]
898    fn read_abc() {
899        for (_, abc_file, bytes) in test_data::avm2_tests() {
900            let mut reader = Reader::new(&bytes[..]);
901            let parsed = reader.read().unwrap();
902            assert_eq!(
903                parsed, abc_file,
904                "Incorrectly parsed ABC.\nRead:\n{parsed:?}\n\nExpected:\n{abc_file:?}",
905            );
906        }
907    }
908
909    #[test]
910    fn test_round_trip_default_value() {
911        use crate::avm2::write::Writer;
912
913        let orig_bytes = read_abc_from_file("tests/swfs/Avm2DefaultValue.swf");
914        let mut reader = Reader::new(&orig_bytes[..]);
915        let parsed = reader.read().unwrap();
916
917        let mut out = vec![];
918        let mut writer = Writer::new(&mut out);
919        writer.write(parsed).unwrap();
920
921        assert_eq!(
922            orig_bytes, out,
923            "Incorrectly written Avm2DefaultValue class"
924        );
925    }
926
927    #[test]
928    fn read_u30() {
929        let read = |data: &[u8]| Reader::new(data).read_u30().unwrap();
930        assert_eq!(read(&[0]), 0);
931        assert_eq!(read(&[2]), 2);
932        assert_eq!(read(&[0b1_0000001, 0b0_0000001]), 129);
933        assert_eq!(
934            read(&[0b1_0000001, 0b1_0000001, 0b0_1100111]),
935            0b1100111_0000001_0000001
936        );
937        assert_eq!(
938            read(&[
939                0b1_0000000,
940                0b1_0000000,
941                0b1_0000000,
942                0b1_0000000,
943                0b0000_1111
944            ]),
945            0b1111_0000000_0000000_0000000_0000000
946        );
947        assert_eq!(
948            read(&[
949                0b1_0000000,
950                0b1_0000000,
951                0b1_0000000,
952                0b1_0000000,
953                0b1111_1111
954            ]),
955            0b1111_0000000_0000000_0000000_0000000
956        );
957    }
958
959    #[test]
960    fn read_i24() {
961        let read = |data: &[u8]| Reader::new(data).read_i24().unwrap();
962        assert_eq!(read(&[0, 0, 0]), 0);
963        assert_eq!(read(&[2, 0, 0]), 2);
964        assert_eq!(read(&[0b1101_0001, 0b0010_1111, 0b0000_0001]), 77777);
965        assert_eq!(read(&[0b0010_1111, 0b1101_0000, 0b1111_1110]), -77777);
966    }
967
968    #[test]
969    fn read_i32() {
970        let read = |data: &[u8]| Reader::new(data).read_i32().unwrap();
971        assert_eq!(read(&[0]), 0);
972        assert_eq!(read(&[2]), 2);
973        assert_eq!(read(&[0b1_0000001, 0b0_0000001]), 129);
974        assert_eq!(
975            read(&[
976                0b1_0000001,
977                0b1_0000001,
978                0b1_0000001,
979                0b1_0000001,
980                0b0000_0100
981            ]),
982            1075855489
983        );
984
985        // Note that the value is NOT sign-extended, unlike what the AVM2 spec suggests.
986        // Negatives must take up the full 5 bytes.
987        assert_eq!(read(&[0b0_1000000]), 64);
988        assert_eq!(read(&[0b1_0000000, 0b0_1000000]), 8192);
989        assert_eq!(read(&[0b1_0000000, 0b1_0000000, 0b0_1000000]), 1048576);
990        assert_eq!(
991            read(&[0b1_0000000, 0b1_0000000, 0b1_0000000, 0b0_1000000]),
992            134217728
993        );
994        assert_eq!(
995            read(&[
996                0b1_0000000,
997                0b1_0000000,
998                0b1_0000000,
999                0b1_0000000,
1000                0b0000_0100
1001            ]),
1002            1073741824
1003        );
1004        assert_eq!(
1005            read(&[
1006                0b1_1111111,
1007                0b1_1111111,
1008                0b1_1111111,
1009                0b1_1111111,
1010                0b0000_0111
1011            ]),
1012            2147483647
1013        );
1014
1015        assert_eq!(
1016            read(&[
1017                0b1_1000000,
1018                0b1_1111111,
1019                0b1_1111111,
1020                0b1_1111111,
1021                0b0000_1111,
1022            ]),
1023            -64
1024        );
1025        assert_eq!(
1026            read(&[
1027                0b1_0000000,
1028                0b1_1000000,
1029                0b1_1111111,
1030                0b1_1111111,
1031                0b0000_1111
1032            ]),
1033            -8192
1034        );
1035        assert_eq!(
1036            read(&[
1037                0b1_0000000,
1038                0b1_0000000,
1039                0b1_1000000,
1040                0b1_1111111,
1041                0b0000_1111
1042            ]),
1043            -1048576
1044        );
1045        assert_eq!(
1046            read(&[
1047                0b1_0000000,
1048                0b1_0000000,
1049                0b1_0000000,
1050                0b1_1000000,
1051                0b0000_1111
1052            ]),
1053            -134217728
1054        );
1055        assert_eq!(
1056            read(&[
1057                0b1_0000000,
1058                0b1_0000000,
1059                0b1_0000000,
1060                0b1_0000000,
1061                0b0000_1000
1062            ]),
1063            -2147483648
1064        );
1065
1066        assert_eq!(read(&[0b1_0000100, 0b1_0000111, 0b0_0000100,]), 66436);
1067
1068        assert_eq!(
1069            read(&[0b1_0000100, 0b1_0000111, 0b1_0000000, 0b0_1111111,]),
1070            266339204
1071        );
1072
1073        // Final 4 bytes of a 5-byte value are unimportant.
1074        assert_eq!(
1075            read(&[
1076                0b1_0000100,
1077                0b1_0000100,
1078                0b1_0000100,
1079                0b1_0000100,
1080                0b1111_0111
1081            ]),
1082            1887502852
1083        );
1084    }
1085}