def test_invalid_add(self): m = pycstruct.StructDef() # Invalid type self.assertRaises(Exception, m.add, 'invalid', 'aname') # Invalid length self.assertRaises(Exception, m.add, 'int8', 'aname', 0) # Invalid byteorder in member self.assertRaises(Exception, m.add, 'int8', 'aname', 1, 'invalid') # Duplicaded member m.add('int8', 'name1') self.assertRaises(Exception, m.add, 'uint8', 'name1') # same_level with length > 1 self.assertRaises(Exception, m.add, pycstruct.StructDef(), 'same_level_err1', length=2, same_level=True) # same_level with non StructDef/BitfieldDef self.assertRaises(Exception, m.add, 'int8', 'same_level_err1', same_level=True)
def test_invalid_deserialize(self): m = pycstruct.StructDef() m.add('int8', 'name1') buffer = bytearray(m.size() + 1) self.assertRaises(Exception, m.deserialize, buffer)
def test_embedded_exception(self): unserializable = UnserializableDef() s = pycstruct.StructDef() s.add(unserializable, 'unserializable') self.assertRaises(Exception, s.deserialize, bytes([0])) self.assertRaises(Exception, s.serialize, {'unserializable': 'hello'})
def test_embedded_same_level(self): substruct = pycstruct.StructDef() substruct.add('uint8', 'ss1') substruct.add('int16', 'ss2') substruct.add('uint32', 'ss3') bitfield = pycstruct.BitfieldDef() bitfield.add('bf1', 3) bitfield.add('bf2', 1) bitfield.add('bf3', 4) parentstruct = pycstruct.StructDef() parentstruct.add('uint16', 'ps1') parentstruct.add('uint32', 'ps2') parentstruct.add(substruct, 'ps3', same_level=True) parentstruct.add(bitfield, 'ps4', same_level=True) parentstruct.add('int8', 'ps5') mydict = { 'ss1': 1, 'ss2': -1234, 'ss3': 123456, 'bf1': 5, 'bf2': 0, 'bf3': 11, 'ps1': 789, 'ps2': 91011, 'ps3': 1213, # Should be ignored 'ps5': -100 } databin = parentstruct.serialize(mydict) mydict2 = parentstruct.deserialize(databin) # Check for key, value in mydict.items(): if key != 'ps3': self.assertEqual(value, mydict2[key], msg='Key {0}'.format(key))
def test_invalid_serialize(self): m = pycstruct.StructDef() m.add('utf-8', 'astring', length=5) data = {} data['astring'] = 5 # no valid string self.assertRaises(Exception, m.serialize, data) data['astring'] = 'too long string' self.assertRaises(Exception, m.serialize, data) m.add('int32', 'alist', length=5) data['astring'] = 'valid' data['alist'] = 3 # no valid list self.assertRaises(Exception, m.serialize, data) data['alist'] = [1, 2, 3, 4, 5, 6, 7] # to long self.assertRaises(Exception, m.serialize, data)
def create_struct(self, byteorder, alignment): m = pycstruct.StructDef(byteorder, alignment) m.add('int8', 'int8_low') m.add('int8', 'int8_high') m.add('uint8', 'uint8_low') m.add('uint8', 'uint8_high') m.add('bool8', 'bool8_false') m.add('bool8', 'bool8_true') m.add('int16', 'int16_low') m.add('int16', 'int16_high') m.add('uint16', 'uint16_low') m.add('uint16', 'uint16_high') m.add('bool16', 'bool16_false') m.add('bool16', 'bool16_true') m.add('int32', 'int32_low') m.add('int32', 'int32_high') m.add('uint32', 'uint32_low') m.add('uint32', 'uint32_high') m.add('bool32', 'bool32_false') m.add('bool32', 'bool32_true') m.add('float32', 'float32_low') m.add('float32', 'float32_high') m.add('int64', 'int64_low') m.add('int64', 'int64_high') m.add('uint64', 'uint64_low') m.add('uint64', 'uint64_high') m.add('bool64', 'bool64_false') m.add('bool64', 'bool64_true') m.add('float64', 'float64_low') m.add('float64', 'float64_high') m.add('int32', 'int32_array', length=5) m.add('utf-8', 'utf8_ascii', 100) m.add('utf-8', 'utf8_nonascii', 80) m.add('utf-8', 'utf8_no_term', 4) return m
def test_struct_remove_to(self): m = pycstruct.StructDef() m.add('int8', 'e1') m.add('int8', 'e2') m.add('int16', 'e3') m.add('int16', 'e4') m.add('int32', 'e5') m.add('int32', 'e6') self.assertEqual(m.size(), 14) self.assertRaises(Exception, m.remove_to, 'invalid') m.remove_to('e4') self.assertEqual(m.size(), 8) d = m.create_empty_data() self.assertFalse('e1' in d) self.assertFalse('e4' in d) self.assertTrue('e5' in d) self.assertTrue('e6' in d)
def test_union_no_pad(self): u = pycstruct.StructDef(union=True, default_byteorder='big') self.assertEqual(u._type_name(), 'union') u.add('uint8', 'small') self.assertEqual(u.size(), 1) u.add('uint16', 'large') self.assertEqual(u.size(), 2) u.add('uint32', 'larger') self.assertEqual(u.size(), 4) u.add('uint64', 'largest') self.assertEqual(u.size(), 8) input = {} input['largest'] = 0x1122334455667788 buf = u.serialize(input) self.assertEqual(len(buf), 8) output = u.deserialize(buf) self.assertEqual(output['small'], 0x11) self.assertEqual(output['large'], 0x1122) self.assertEqual(output['larger'], 0x11223344) self.assertEqual(output['largest'], 0x1122334455667788) buf2 = u.serialize(output) output2 = u.deserialize(buf2) self.assertEqual(output2['largest'], 0x1122334455667788) del output2['largest'] del output2['larger'] buf3 = u.serialize(output2) output3 = u.deserialize(buf3) self.assertEqual(output3['largest'], 0x1122000000000000) self.assertEqual(output3['larger'], 0x11220000)
def _to_instance(self, name): ''' Create a pycstruct instance of type with name. Will recursively create instances of referenced types. Returns the instance. ''' if name in self._instances: return self._instances[name] # Parsed before meta = self._type_meta[name] if meta['supported'] == False: return None # Not supported instance = None # Structs or union if meta['type'] == 'struct' or meta['type'] == 'union': is_union = meta['type'] == 'union' instance = pycstruct.StructDef(self._byteorder, meta['align'], union=is_union) for member in meta['members']: if 'reference' in member: other_instance = self._to_instance(member['reference']) if other_instance == None: raise Exception( 'Member {} is of type {} {} that is not supported'. format(member['name'], member['type'], member['reference'])) same_level = False if ('same_level' in member) and (member['same_level'] == True): same_level = True instance.add(other_instance, member['name'], member['length'], same_level=same_level) else: instance.add(member['type'], member['name'], member['length']) # Enum elif meta['type'] == 'enum': instance = pycstruct.EnumDef(self._byteorder, meta['size'], meta['signed']) for member in meta['members']: instance.add(member['name'], member['value']) # Bitfield elif meta['type'] == 'bitfield': instance = pycstruct.BitfieldDef(self._byteorder, meta['size']) for member in meta['members']: instance.add(member['name'], member['bits'], member['signed']) # Not supported else: logger.warning( 'Unable to create instance for {} (type {}). Not supported.'. format(meta['name'], meta['type'])) meta['supported'] = False return None # Sanity check size: if meta['size'] != instance.size(): logger.warning( '{0} size, {1}, does match indicated size {2}'.format( meta['name'], instance.size(), meta['size'])) self._instances[name] = instance return instance
def embedded_struct(self, filename, alignment=1): car_type = pycstruct.EnumDef(size=4) car_type.add('Sedan', 0) car_type.add('Station_Wagon', 5) car_type.add('Bus', 7) car_type.add('Pickup', 12) sedan_properties = pycstruct.StructDef(alignment=alignment) sedan_properties.add('uint16', 'sedan_code') station_wagon_properties = pycstruct.StructDef(alignment=alignment) station_wagon_properties.add('int32', 'trunk_volume') bus_properties = pycstruct.StructDef(alignment=alignment) bus_properties.add('int32', 'number_of_passangers') bus_properties.add('uint16', 'number_of_entries') bus_properties.add('bool8', 'is_accordion_bus') pickup_properties = pycstruct.StructDef(alignment=alignment) pickup_properties.add('int32', 'truck_bed_volume') type_specific_properties = pycstruct.StructDef(alignment=alignment, union=True) type_specific_properties.add(sedan_properties, 'sedan') type_specific_properties.add(station_wagon_properties, 'station_wagon') type_specific_properties.add(bus_properties, 'bus') type_specific_properties.add(pickup_properties, 'pickup') # gcc is setting the size of car_properties_s to # 4 bytes when no packing is added of some strange # reason. size = 1 if alignment > 1: size = 4 car_properties = pycstruct.BitfieldDef(size=size) car_properties.add('env_class', 3) car_properties.add('registered', 1) car_properties.add('over_3500_kg', 1) car = pycstruct.StructDef(alignment=alignment) car.add('uint16', 'year') car.add('utf-8', 'model', length=50) car.add('utf-8', 'registration_number', length=10) car.add(car_properties, 'properties') car.add(car_type, 'type') car.add(type_specific_properties, 'type_properties') garage = pycstruct.StructDef(alignment=alignment) garage.add(car, 'cars', length=20) garage.add('uint8', 'nbr_registered_parkings') house = pycstruct.StructDef(alignment=alignment) house.add('uint8', 'nbr_of_levels') house.add(garage, 'garage') ############################################# # Test to string method stringrep = str(car) self.assertTrue('model' in stringrep) stringrep = str(garage) self.assertTrue('nbr_registered_parkings' in stringrep) stringrep = str(house) self.assertTrue('nbr_of_levels' in stringrep) ############################################# # Load pre-stored binary data and deserialize and check check_embedded_struct(self, house, filename)
import pycstruct person = pycstruct.StructDef() person.add('utf-8', 'name', length=50) person.add('uint32', 'age') person.add('float32', 'height') person.add('bool8', 'is_male') person.add('uint32', 'nbr_of_children') person.add('uint32', 'child_ages', length=10) f = open('simple_example.dat', 'rb') inbytes = f.read() result = person.deserialize(inbytes) f.close() print(str(result))