/// <summary> /// Read in a trait, which are like object properties. /// </summary> /// <returns>A trait.</returns> private Trait ReadTrait() { Trait t = null; Multiname traitName = this.code.GetMultiname((int)this.abcdtr.ReadU30()); int traitCode = this.abcdtr.ReadUI8(); TraitKind kind = (TraitKind)(traitCode & 0xF); switch (kind) { case TraitKind.Slot: case TraitKind.Const: SlotTrait st = new SlotTrait(); st.Name = traitName; st.Kind = kind; st.SlotID = this.abcdtr.ReadU30(); st.TypeName = this.code.GetMultiname((int)this.abcdtr.ReadU30()); uint vindex = this.abcdtr.ReadU30(); if (vindex != 0) { st.ValKind = (ConstantKind)this.abcdtr.ReadUI8(); switch (st.ValKind) { case ConstantKind.ConInt: st.Val = this.code.IntConsts[vindex]; break; case ConstantKind.ConUInt: st.Val = this.code.UIntConsts[vindex]; break; case ConstantKind.ConDouble: st.Val = this.code.DoubleConsts[vindex]; break; case ConstantKind.ConUtf8: st.Val = this.code.StringConsts[vindex]; break; case ConstantKind.ConTrue: case ConstantKind.ConFalse: case ConstantKind.ConNull: case ConstantKind.ConUndefined: break; case ConstantKind.ConNamespace: case ConstantKind.ConPackageNamespace: case ConstantKind.ConPackageInternalNs: case ConstantKind.ConProtectedNamespace: case ConstantKind.ConExplicitNamespace: case ConstantKind.ConStaticProtectedNs: case ConstantKind.ConPrivateNs: st.Val = this.code.GetNamespace((int)vindex); break; default: throw new SWFModellerException( SWFModellerError.Internal, "Unsupported constant kind: " + st.ValKind.ToString()); } } t = st; break; case TraitKind.Class: ClassTrait ct = new ClassTrait(); ct.Name = traitName; ct.Kind = kind; ct.SlotID = this.abcdtr.ReadU30(); this.LateResolutions.Add(ct, (int)this.abcdtr.ReadU30()); /* We'll resolve the class ref later. */ t = ct; break; case TraitKind.Function: FunctionTrait ft = new FunctionTrait(); ft.Name = traitName; ft.Kind = kind; ft.SlotID = this.abcdtr.ReadU30(); ft.Fn = this.code.GetMethod((int)this.abcdtr.ReadU30()); t = ft; break; case TraitKind.Method: case TraitKind.Getter: case TraitKind.Setter: default: MethodTrait mt = new MethodTrait(); mt.Name = traitName; mt.Kind = kind; uint dispID = this.abcdtr.ReadU30(); if (dispID != 0) { mt.OverriddenMethod = this.code.GetMethod((int)dispID); } mt.Fn = this.code.GetMethod((int)this.abcdtr.ReadU30()); t = mt; break; } return(t); }
public ASTrait(ABCFile abc, FlashReader reader) : this(abc) { TypeIndex = reader.Read7BitEncodedInt(); byte trueKind = reader.ReadByte(); var traitType = (TraitType)(trueKind & 0xF); Attributes = (TraitAttributes)(trueKind >> 4); #region Trait Reading switch (traitType) { case TraitType.Slot: case TraitType.Constant: { Data = new SlotConstantTrait(abc, reader, traitType) { ObjName = Type.ObjName }; break; } case TraitType.Method: case TraitType.Getter: case TraitType.Setter: { Data = new MethodGetterSetterTrait(abc, reader, traitType) { ObjName = Type.ObjName }; ((MethodGetterSetterTrait)Data).Method.ObjName = ObjName; break; } case TraitType.Class: { Data = new ClassTrait(abc, reader) { ObjName = Type.ObjName }; break; } case TraitType.Function: { Data = new FunctionTrait(abc, reader) { ObjName = Type.ObjName }; break; } default: throw new Exception($"Invalid {nameof(ASTrait)} type: " + traitType); } #endregion if ((Attributes & TraitAttributes.Metadata) != 0) { MetadataIndices.Capacity = reader.Read7BitEncodedInt(); } for (int i = 0; i < MetadataIndices.Capacity; i++) { MetadataIndices.Add(reader.Read7BitEncodedInt()); } }
private void WriteTraitInfo(ABCDataTypeWriter writer, Trait t) { writer.WriteU30Packed((uint)this.MultinameID(t.Name)); writer.WriteUI8((uint)t.Kind); switch (t.Kind) { case TraitKind.Slot: case TraitKind.Const: SlotTrait st = (SlotTrait)t; writer.WriteU30Packed(st.SlotID); writer.WriteU30Packed((uint)this.MultinameID(st.TypeName)); if (st.Val == null) { writer.WriteU30Packed(0); } else { switch (st.ValKind) { case ConstantKind.ConInt: writer.WriteU30Packed((uint)this.intMarshal.GetIDFor((int)st.Val)); break; case ConstantKind.ConUInt: writer.WriteU30Packed((uint)this.uintMarshal.GetIDFor((uint)st.Val)); break; case ConstantKind.ConDouble: writer.WriteU30Packed((uint)this.doubleMarshal.GetIDFor((ulong)st.Val)); break; case ConstantKind.ConUtf8: writer.WriteU30Packed((uint)this.stringMarshal.GetIDFor((string)st.Val)); break; case ConstantKind.ConTrue: /* Through observation, this always gets set to 11, I do not know why. It * seems though that it should be any non-zero number. */ writer.WriteU30Packed(11); break; case ConstantKind.ConFalse: /* Through observation, this always gets set to 11, I do not know why. It * seems though that it should be any non-zero number. */ writer.WriteU30Packed(10); break; case ConstantKind.ConNull: /* Through observation, this always gets set to 11, I do not know why. It * seems though that it should be any non-zero number. */ writer.WriteU30Packed(12); break; case ConstantKind.ConUndefined: /* Through observation, true, false and null all seem to have ignored but * specific values. I haven't seen one for undefined, but I'm guessing it's * 13. Really want to know what these number are. The don't seem to relate * the string or multiname tables. */ writer.WriteU30Packed(13); break; case ConstantKind.ConNamespace: case ConstantKind.ConPackageNamespace: case ConstantKind.ConPackageInternalNs: case ConstantKind.ConProtectedNamespace: case ConstantKind.ConExplicitNamespace: case ConstantKind.ConStaticProtectedNs: case ConstantKind.ConPrivateNs: writer.WriteU30Packed((uint)this.NamespaceID((Namespace)st.Val)); break; default: throw new SWFModellerException( SWFModellerError.Internal, "Unsupported constant type: " + st.ValKind.ToString()); } writer.WriteUI8((uint)st.ValKind); } break; case TraitKind.Method: case TraitKind.Getter: case TraitKind.Setter: MethodTrait mt = (MethodTrait)t; if (mt.OverriddenMethod != null) { writer.WriteU30Packed((uint)this.methodMarshal.GetIDFor(mt.OverriddenMethod)); } else { writer.WriteU30Packed(0); } writer.WriteU30Packed((uint)this.methodMarshal.GetIDFor(mt.Fn)); break; case TraitKind.Class: ClassTrait ct = (ClassTrait)t; writer.WriteU30Packed((uint)ct.SlotID); writer.WriteU30Packed((uint)this.classMarshal.GetIDFor(ct.As3class)); break; case TraitKind.Function: FunctionTrait ft = (FunctionTrait)t; writer.WriteU30Packed((uint)ft.SlotID); writer.WriteU30Packed((uint)this.methodMarshal.GetIDFor(ft.Fn)); break; default: /* ISSUE 73 */ throw new SWFModellerException( SWFModellerError.UnimplementedFeature, "Unsupported trait kind: " + t.Kind.ToString()); } }