def ClassImpl(id): return C.FocusedSeq( "classes", "_class" / C.Computed(lambda this: this._root.defs[evaluate(id, this)]), "classes" / C.FocusedSeq( "entries", "_index" / C.Index, "_member" / C.Computed(lambda this: this._._class.members[this._index]), "entries" / C.Sequence(C.Computed(this._._member.name), DataEntry(lambda this: this._._._member.type)))[C.len_( this._class.members)])
def Backwards(subcon): r""" Adapter used to parse a given subconstruct backwards in the stream. This ia a macro for seeking backwards before parsing the construct. (This will not work for subcons that don't have a valid sizeof) The stream will be left off at the start of the parsed result by design. Therefore, doing something like Int32ul >> Backwards(Int32ul) >> Int32ul will parse the same data 3 times. e.g. >>> (Bytes(14) >> Backwards(Int32ul) >> Tell).parse(b'junk stuff\x01\x02\x00\x00') ['junk stuff\x01\x02\x00\x00', 513, 10L] >>> spec = Struct(Seek(0, os.SEEK_END), 'name' / Backwards(String(9)), 'number' / Backwards(Int32ul)) >>> spec.parse(b'A BUNCH OF JUNK DATA\x01\x00\x00\x00joe shmoe') Container(name='joe shmoe')(number=1) WARNING: This will break if the subcon doesn't have a valid sizeof. >>> spec = Struct(Seek(0, os.SEEK_END), 'name' / Backwards(CString()), 'number' / Backwards(Int32ul)) >>> spec.parse(b'A BUNCH OF JUNK DATA\x01\x00\x00\x00joe shmoe\x00') Traceback (most recent call last): ... SizeofError: cannot calculate size parsing -> name """ return construct.FocusedSeq( 1, construct.Seek(lambda ctx: subcon.sizeof(ctx) * -1, os.SEEK_CUR), construct.Peek(subcon))
def PrefixedOffset(sizetype, type, offs=0): return C.FocusedSeq( "content", "_data" / C.Rebuild( C.Struct("size" / C.Rebuild(sizetype, C.len_(this.data) - offs), "data" / C.Bytes(this.size + offs)), lambda obj: {"data": type.build(obj.content, **{ **obj._params, **obj })}), "content" / C.RestreamData(this._data.data, type))
def DataEntry(type): return C.FocusedSeq( "values", "_count" / C.Rebuild(Int32ul, C.len_(this.values)), "values" / C.Switch( type, { 0: Pass, 1: ClassEntry(), 2: ClassEntry(), 3: Byte, #boolean 4: Int8ul, 5: Int16ul, 6: Int32ul, 7: Int64ul, 8: Int8sl, 9: Int16sl, 10: Int32sl, 11: Int64sl, 12: Float32l, 13: Float64l, 14: CString("utf8"), 15: RGBA(), 16: Int64ul, #pointer #17: Int32ul #size, potentially not a uint but that's probably the best option of it 20: Vector3(), 21: Vector4(), 22: Quat4(), 32: CString( 'utf8' ), #specifically a CString, while 14 is probably something like std::string 46: Capsule(), 64: Vector2() }, default=C.StopFieldError)[this._count], )
def OptionalValue(subcon): return construct.FocusedSeq( "value", present=Rebuild(Flag, construct.this.value != None), value=If(construct.this.present, subcon), )
KeyValue = c.Struct( "key" / c.Prefixed(CompactUint, c.Struct( "type" / c.Byte, "data" / c.GreedyBytes, )), "value" / c.Prefixed(CompactUint, c.GreedyBytes), "ofs" / c.Tell, ) Sequence = c.FocusedSeq("content", "content" / c.GreedyRange( c.FocusedSeq( "keyvalue", "terminator" / c.Peek(c.Byte), c.StopIf(c.this.terminator == 0), "keyvalue" / KeyValue, ) ), c.Const(b'\0'), ) PSBT = c.Struct( "magic" / c.Const(b'psbt'), "sep" / c.Const(b'\xff'), "general" / Sequence, "transaction" / c.RestreamData(c.this.general[0].value, Transaction), "inputs" / c.Array(c.len_(c.this.transaction.inputs), Sequence), "outputs" / c.Array(c.len_(c.this.transaction.outputs), Sequence), c.Terminated, )
PermalinkBinary = construct.FocusedSeq( "fields", schema_version=construct.Const(_CURRENT_SCHEMA_VERSION, construct.Byte), fields=construct.RawCopy( construct.Aligned( 3, construct.Struct( header=construct.BitStruct( has_seed_hash=construct.Rebuild( construct.Flag, construct.this._.seed_hash != None), bytes_rotation=construct.Rebuild( construct.BitsInteger(7), lambda ctx: single_byte_hash(ctx._.generator_params) >> 1, )), seed_hash=construct.If(construct.this.header.has_seed_hash, construct.Bytes(5)), randovania_version=construct.Bytes(4), # short git hash generator_params=construct.ExprAdapter( construct.Prefixed(construct.VarInt, construct.GreedyBytes), # parsing decoder=create_rotator(inverse=True), # building encoder=create_rotator(inverse=False), ), ))), permalink_checksum=construct.Checksum( construct.Bytes(2), lambda data: hashlib.blake2b(data, digest_size=2).digest(), construct.this.fields.data, ), end=construct.Terminated, )
c.Struct( "type" / CompactUint, "data" / Optional(c.GreedyBytes), )), "value" / c.Prefixed(CompactUint, c.GreedyBytes), ) PsbtProprietaryKey = c.Struct( "prefix" / c.CString("utf-8"), "subtype" / CompactUint, "data" / Optional(c.GreedyBytes), ) PsbtSequence = c.FocusedSeq( "content", "content" / c.GreedyRange(PsbtKeyValue), c.Const(b"\0"), ) PsbtEnvelope = c.FocusedSeq( "sequences", "magic" / c.Const(b"psbt\xff"), "sequences" / c.GreedyRange(PsbtSequence), c.Terminated, ) Bip32Field = c.Struct( "fingerprint" / c.Bytes(4), "address_n" / c.GreedyRange(c.Int32ul), ) # fmt: on
"size" / Byte, "_unknData" / C.Default(Byte[69], [0 for _ in range(69)]), ) ClassDefinition = DataPointer( Int64ul, Struct("hash" / Int64ul, "members" / C.PrefixedArray(Int64ul, ClassMemberDefinition)), "definitionData") ClassDefinitionList = C.FocusedSeq( "definitions", "_count" / C.Rebuild(Int32ul, C.len_(this.definitions)), "definitions" / C.Prefixed( Int32ul, C.Aligned( 8, C.FocusedSeq( "definitions", "definitions" / ClassDefinition[this._._count], DataEntries("definitionData"), DataEntries("names"), )))) # Hierarchy handling varcount = 0 def varHandling(this): global varcount ret = varcount varcount += 1 return ret