def FixedArray(size_func, subcon): """At parse time parses a fixed sized array, and at build time builds the array with its given size. """ return ListAdapter( IfThenElse(lambda this: this._parsing, FixedSized(size_func, GreedyRange(subcon)), GreedyRange(subcon)))
'midi_list' / FixedSized(_this.flags.len, GreedyRange(Struct( 'delta_time' / If(_this._index > 0, VarInt), # The "running status" technique means multiple commands may be sent under # the same status. This condition occurs when, after parsing the current # commands, we see the next byte is NOT a status byte (MSB is low). # # Below, this is accomplished by storing the most recent status byte # on the global context with the `* remember_last` macro; then using it # on the `else` branch of the `command_byte` selection. '__next' / Peek(Int8ub), 'command_byte' / IfThenElse(_this.__next & 0x80, Byte * remember_last, Computed(lambda ctx: ctx._root._last_command_byte) ), 'command' / If(_this.command_byte, Enum(Computed(_this.command_byte & 0xf0), note_on=COMMAND_NOTE_ON, note_off=COMMAND_NOTE_OFF, aftertouch=COMMAND_AFTERTOUCH, control_mode_change=COMMAND_CONTROL_MODE_CHANGE)), 'channel' / If(_this.command_byte, Computed(_this.command_byte & 0x0f)), 'params' / Switch(_this.command, { 'note_on': Struct( 'key' / MIDINote, 'velocity' / Int8ub, ), 'note_off': Struct( 'key' / MIDINote, 'velocity' / Int8ub, ), 'aftertouch': Struct( 'key' / MIDINote, 'touch' / Int8ub, ), 'control_mode_change': Struct( 'controller' / Int8ub, 'value' / Int8ub, ), }, default=Struct( 'unknown' / GreedyBytes, ))), )),
def SizedUTF16MultiSz(size_func): return ExprAdapter( FixedSized(size_func, GreedyRange(CString("UTF_16_le"))), lambda obj, ctx: list(obj[:-1]), # last element is the null lambda obj, ctx: obj + [''])
stackshot_fault_stats, kcdata_types_enum.KCDATA_BUFFER_BEGIN_STACKSHOT: Struct(predefined_name_substruct), kcdata_types_enum.KCDATA_TYPE_CONTAINER_END: Pass, kcdata_types_enum.KCDATA_TYPE_BUFFER_END: Pass, kcdata_types_enum.STACKSHOT_KCTYPE_STACKSHOT_DURATION: stackshot_duration, } kcdata_item = Struct( 'type' / kcdata_types_enum, 'size' / Int32ul, 'flags' / Int64ul, 'data' / FixedSized( lambda ctx: ctx.size, Switch(lambda ctx: ctx.type, kcdata_types_structures, default=GreedyBytes))) kcdata = GreedyRange(kcdata_item) kd_threadmap = Struct( 'tid' / Int64ul, 'pid' / Int32ul, 'process' / FixedSized(20, CString('utf8')), ) kd_buf = Struct( 'timestamp' / Int64ul, 'args' / RawCopy(Array(4, Int64ul)), 'tid' / Int64ul,
"id" / Array(100, Int32ul), "is_compr" / Array(100, Int32ul), "offset" / Array(100, Int32ul), Padding(4), ), # 2001 "x_view" / Pointer(this.dir.dir_size + this.dir.offset[0], Int32ul), # 2002 "y_view" / Pointer(this.dir.dir_size + this.dir.offset[1], Int32ul), # 2003 "random_state" / Pointer(this.dir.dir_size + this.dir.offset[2], FixedSized(this.dir.uncompr_size[2], GreedyBytes)), # 2004 "bmap_size" / Pointer( this.dir.dir_size + this.dir.offset[3], Struct( "uncompr_size" / Int32ul, "uncompr_size" / Computed(this._.dir.uncompr_size[3]), "compr_size" / Int32ul, "compr_size" / Computed(this._.dir.compr_size[3] - 12), "crc32_offset" / Tell, "crc32" / Int32ul, "data" / FixedSized( this.compr_size, Compressed(Bytes(this.uncompr_size), "blast")), "crc32" / Pointer(this.crc32_offset, Checksum(Int32ul, lambda l: crc32(l), this.data)))), # 2005
def PaddedUTF16StringBestEffort(length): return UTF16EncodedBestEffort( FixedSized(length, NullStripped(GreedyBytes, pad="\x00\x00")))
def SizedUTF16MultiSz(size_func): return ExprAdapter( FixedSized(size_func, GreedyRange(CString("UTF_16_le"))), lambda obj, ctx: list( obj), # last element is already removed by GreedyRange lambda obj, ctx: obj + [''])
def _encode(self, obj, context, path): if obj == u"": return b"" return obj.encode("UTF-16le", "replace") def PaddedUTF16StringBestEffort(length): return UTF16EncodedBestEffort( FixedSized(length, NullStripped(GreedyBytes, pad="\x00\x00"))) FixedNullTerminatedUTF16String = Struct( # I don't use PascalString because it's a null terminated string. "string_size" / Int32ul, "string" / IfThenElse( lambda this: this.string_size, FixedSized( lambda this: this.string_size, NullTerminated(GreedyString("UTF_16_le"), term="\x00".encode("utf-16le"))), Computed(''))) class FiletimeAdapter(Adapter): def _decode(self, obj, context, path): if 0 == obj: return None # 0 is not really a date secs = int(obj // int(1e7)) nanosecs = int(obj - int(secs * int(1e7))) * 100 # I use numpy's datetime64 instead of datetime.datetime because filetime have 100 nanoseconds precision. return datetime64('1601-01-01') + timedelta64(secs, 's') + timedelta64( nanosecs, 'ns') def _encode(self, obj, context, path):
chunk = Struct( "chunk_name" / Bytes(4), "size" / Int32ub, "payload" / Aligned( 4, FixedSized( this.size, Switch( this.chunk_name, { # "Abst" : chunk_abst, b"Atom": Atom, b"AtU8": AtU8, b"Attr": Attr, b"CInf": CInf, b"Code": Code, b"ExpT": ExpT, # "FunT" : chunk_funt, b"ImpT": ImpT, # "Line" : chink_line, b"LitT": LitT, b"LocT": LocT, # "StrT" : chunk_strt, # "Trac" : chunk_trac, }, default=GreedyBytes))), ) __all__ = ["chunk"]
# furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # from construct import this from construct import ( Const, FixedSized, GreedyRange, Int32ub, Struct, ) from pybeam.schema.beam.chunks import chunk beam = Struct("for1" / Const(b'FOR1'), "size" / Int32ub, "beam" / Const(b'BEAM'), "chunks" / FixedSized(this.size - 4, GreedyRange(chunk))) __all__ = ["beam"]