class StructWithComputedSizeArray(binobj.Struct): half_size = fields.UInt8() size = fields.UInt8() stuff = fields.Array(fields.UInt8(), count=size) @size.computes def compute_size(self, all_fields): return all_fields["half_size"] * 2
class FieldsUnionContainer(binobj.Struct): data_type = fields.UInt8() item = fields.Union( fields.StringZ(), fields.UInt16(endian="little"), load_decider=fields_load_decider, dump_decider=fields_dump_decider, )
class UnionContainer(binobj.Struct): data_type = fields.UInt8() item = fields.Union( UnionItemA, UnionItemB, load_decider=struct_load_decider, dump_decider=struct_dump_decider, )
class FAT12BootSector(binobj.Struct): jump = fields.Bytes(const=b"\xeb\x3c\x90") oem_name = fields.String(size=8, default="mkdosfs", pad_byte=b" ", encoding="ascii") bytes_per_sector = fields.UInt16(default=512) sectors_per_cluster = fields.UInt8() reserved_sectors = fields.UInt16(default=1) num_fats = fields.UInt8(default=2) max_root_entries = fields.UInt16(default=240) total_logical_sectors_16 = fields.UInt16() media_descriptor = fields.UInt8() sectors_per_fat = fields.UInt16() sectors_per_track = fields.UInt16() num_heads = fields.UInt16() num_hidden_sectors = fields.UInt32(default=0) total_logical_sectors_32 = fields.UInt32() drive_number = fields.UInt8() _reserved = fields.Bytes(const=b"\0", discard=True) _ex_boot_signature = fields.Bytes(const=b"\x29", discard=True) volume_id = fields.UInt32(default=lambda: random.randrange(2**32)) volume_label = fields.String(size=11) fs_type = fields.String(size=8, default="FAT12", pad_byte=b" ", encoding="ascii") boot_code = fields.Bytes(size=448, default=b"\xcc" * 448) boot_signature = fields.Bytes(const=b"\x55\xaa") @property def total_logical_sectors(self): return self.total_logical_sectors_16 or self.total_logical_sectors_32 @total_logical_sectors.setter def total_logical_sectors(self, total_sectors): if total_sectors < 1 or total_sectors >= 2**32: raise ValueError("Total sectors must be in [1, 2^32). Got: %d" % total_sectors) if total_sectors < 65535: self.total_logical_sectors_16 = total_sectors self.total_logical_sectors_32 = 0 else: self.total_logical_sectors_16 = 0 self.total_logical_sectors_32 = total_sectors
def test_string__dump_basic(): """Basic test of dumping a String""" field = stringlike.String(size=13, encoding="utf-8") assert field.to_bytes( r"¯\_(ツ)_/¯") == b"\xc2\xaf\\_(\xe3\x83\x84)_/\xc2\xaf" def test_string__dump_no_size(): """Try dumping a string without its size set.""" field = stringlike.String() with pytest.raises(errors.UndefinedSizeError): field.to_bytes("asdf") @pytest.mark.parametrize("size_field", (fields.UInt8(name="size"), "size")) def test_string__dump_variable_size(size_field): """Dumping a field with variable size should work.""" field = stringlike.String(size=size_field) assert field.to_bytes("asdf", all_fields={"size": 4}) == b"asdf" def test_string__dump_too_long_before_encoding(): """Basic test of dumping a string that's too long into a String.""" field = stringlike.String(size=5, encoding="utf-8") with pytest.raises(errors.ValueSizeError): assert field.to_bytes("abcdefg") def test_string__dump_too_long_after_encoding(): """Test dumping a string that's too long only after encoding to bytes."""
def test_array__sized__read(): """Verify the behavior of a fixed-size array on loading.""" sequence = fields.Array(fields.UInt8(), count=3) result = sequence.from_bytes(b"\xde\xad\xbe") assert result == [0xDE, 0xAD, 0xBE]
def test_array__basic(): """Test deserializing a list of stuff.""" sequence = fields.Array(fields.UInt8()) result = sequence.from_bytes(b"\xde\xad\xbe\xef") assert result == [0xDE, 0xAD, 0xBE, 0xEF]
class UnionItemB(binobj.Struct): _id = fields.UInt8(const=0x7F) other = fields.UInt16(endian="little")
class UnionItemA(binobj.Struct): _id = fields.UInt8(const=0xFF) value = fields.StringZ()
def test_array__bogus_count(count): with pytest.raises(TypeError): fields.Array(fields.UInt8(), count=count)
class _Crash(binobj.Struct): n_numbers = fields.UInt8() numbers = fields.Array(fields.UInt8(), count="eof") eof = fields.String(const="ABC")
class BasicStructWithArraySizeFieldAsName(binobj.Struct): n_numbers = fields.UInt8() numbers = fields.Array(fields.UInt8(), count="n_numbers") eof = fields.String(const="ABC")
class BasicStructWithSentinelArray(binobj.Struct): numbers = fields.Array(fields.UInt8(), halt_check=bswsa_should_halt) eof = fields.String(const="ABC")