class BGAPIFrame(Structure): head = LengthField(BitField(16, is_event=BitBool(), technology_type=BitNum(4), length=BitNum(11)), get_length=lambda f: f.length, set_length=lambda f, l: setattr(f, 'length', l)) class_id = UBInt8() command_id = UBInt8() payload = Payload(head)
class FieldAccessorMultiple(Structure): # FieldAccessors can be referenced multiple times, # and more than one attribute of a given field may be referenced. # TODO: Figure out how to support LengthField(bits.upper)? bits = BitField(8, upper=BitNum(4), lower=BitNum(4)) upper = bits.upper lower = bits.lower body = DispatchTarget( None, bits.lower, { 0b1010: Structure16, # 0x0A 0b0101: One, # 0x05 })
class ConditionalArrayElement(Structure): options = BitField(8, cond8_present=BitBool(), cond16_present=BitBool(), unused=BitNum(6)) cond8 = ConditionalField(UBInt8(), lambda m: m.options.cond8_present) cond16 = ConditionalField(UBInt16(), lambda m: m.options.cond16_present)
class DNSMessage(Structure): identification = UBInt16() fields = BitField( 16, is_reply=BitBool(), # QR opcode=BitNum(4), truncated=BitBool(), recursion_desired=BitBool(), ra=BitBool(), z=BitBool(), non_authenticated_data_acceptable=BitBool(), cd=BitBool(), rcode=BitNum(4), ) total_questions = UBInt16() total_answers_rrs = UBInt16() total_authority_rrs = UBInt16() total_additional_rrs = UBInt16() data = Payload() # greedy
class TCPFrameHeader(Structure): source_address = UBInt16() destination_address = UBInt16() sequence_number = UBInt32() acknowledgement_number = UBInt32() options = BitField(16, data_offset=BitNum(4), reserved=BitNum(3), NS=BitBool(), CWR=BitBool(), ECE=BitBool(), URG=BitBool(), ACK=BitBool(), PSH=BitBool(), RST=BitBool(), SYN=BitBool(), FIN=BitBool() ) window_size = UBInt16() checksum = UBInt16() urgent_pointer = UBInt16()
def test_packing(self): field_proto = BitField( 16, nib1=BitNum(4), nib2=BitNum(4), nib3=BitNum(4), nib4=BitNum(4), ) field = field_proto.create_instance(None) field.nib1 = 1 field.nib2 = 2 field.nib3 = 3 field.nib4 = 4 field2 = field_proto.create_instance(None) sio = six.BytesIO() field.pack(sio) field2.unpack(sio.getvalue()) self.assertEqual(field2.nib1, 1) self.assertEqual(field2.nib2, 2) self.assertEqual(field2.nib3, 3) self.assertEqual(field2.nib4, 4)
class IPV4Frame(Structure): options = BitField(64, version=BitNum(4), internet_header_length=BitNum(4), differentiated_services_code_point=BitNum(6), explicit_congestion_notification=BitNum(2), total_length=BitNum(16), identification=BitNum(16), flags=BitNum(3), fragment_offset=BitNum(13), ) time_to_live = UBInt8() protocol = DispatchField(UBInt8()) header_checksum = UBInt16() source_ip_address = UBInt32() destination_ip_address = UBInt32()
def test_explicit_field_override(self): field_proto = BitField(16, ULInt16(), b1=BitBool(), b2=BitBool(), remaining=BitNum(14)) inst = field_proto.create_instance(None) inst.b1 = True inst.b2 = False inst.remaining = 0x1EF sio = six.BytesIO() inst.pack(sio) # should be packed in little endian form self.assertEqual(sio.getvalue(), b"\xef\x81") inst2 = field_proto.create_instance(None) inst2.unpack(b"\xef\x81") self.assertEqual(inst.b1, inst2.b1) self.assertEqual(inst.b2, inst2.b2) self.assertEqual(inst.remaining, inst2.remaining)
def test_bad_operations(self): field_proto = BitField(7, num=BitNum(7)) self.assertRaises(SuitcaseProgrammingError, field_proto.create_instance, None)
class SuperMessage(Structure): magic = Magic(b'\xAA\xAA') # bitfield options = BitField(8, b1=BitBool(), b2=BitBool(), rest=BitNum(6)) # unsigned big endian ubint8 = UBInt8() ubint16 = UBInt16() ubint24 = UBInt24() ubint32 = UBInt32() ubint64 = UBInt64() # signed big endian sbint8 = SBInt8() sbint16 = SBInt16() sbint32 = SBInt32() sbint64 = SBInt64() # unsigned little endian ulint8 = ULInt8() ulint16 = ULInt16() ulint32 = ULInt32() ulint64 = ULInt64() # signed little endian slint8 = SLInt8() slint16 = SLInt16() slint32 = SLInt32() slint64 = SLInt64() # optional optional_one = ConditionalField(UBInt8(), lambda m: m.options.b1) optional_two = ConditionalField(UBInt8(), lambda m: m.options.b2) # sequences with variable lengths ubseql = LengthField(UBInt8()) ubseq = UBInt8Sequence(ubseql) sbseql = LengthField(UBInt8()) sbseq = SBInt8Sequence(sbseql) # sequences with fixed lengths ubseqf = UBInt8Sequence(5) sbseqf = SBInt8Sequence(5) # don't change anything... for test coverage ulint16_value = FieldProperty(ulint16) ulint16_byte_string = FieldProperty( ulint16, onget=lambda v: str(v), onset=lambda v: struct.unpack(">H", v)[0]) message_type = DispatchField(UBInt8()) submessage_length = LengthField(UBInt16()) submessage = DispatchTarget(submessage_length, message_type, {0xEF: SuperChild}) # checksum starts after beginning magic, ends before # the checksum crc = CRCField(UBInt16(), crc16_ccitt, 2, -3) eof = Magic(b'~')
class FieldAccessorDispatch(Structure): bits = BitField(8, upper=BitNum(5), lower=BitNum(3)) body = DispatchTarget(None, bits.upper, { 0: Zero, 1: One, })
class StructureWithFieldAccessorAtTopLevel(Structure): bits = BitField(8, top=BitNum(3), bottom=BitNum(5)) top = bits.top