用于构造结构化二进制数据包的模块。
Hydras的Python项目详细描述
九头蛇
'hydras'是一个python库,允许开发人员根据简单的规则创建结构化的二进制数据, 有点类似于C对结构的处理。
示例
classHeader(Struct):Opcode=UInt8(4)# The `opcode`'s default value will now be `4`DataLength=UInt32()classDataPacket(Struct):# A nested structure. "DataLength = 128" sets the default DataLength value for `Header`s inside `DataPacket`sHeader=NestedStruct(Header(DataLength=128))# Creates an array of bytes with a length of 128 bytes.Payload=Array(length=128)# To override the constructor it must be able to override the default ctor (1 argument)def__init__(self,opcode=0):# Must call the base ctorsuper(DataPacket,self).__init__()self.Header.Opcode=opcodeif__name__=='__main__':packet=DataPacket()# After you create the object, you can ignore the formatting rules, and assign the data directly to the properties.packet.Header.Opcode=DATAPACKET_OPCODE# You can transform the object into a byte string using the `serialize` method.data_to_send=packet.serialize()# => b'\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...'some_socket.send(data_to_send)packet.Payload='\xFF'*128data_to_send=packet.serialize()# => b'\x04\x80\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF...'# . . .# You can parse raw byte strings into an object using the deserialize class method.received_data=some_socket.recv(len(packet))parsed_packet=DataPacket.deserialize(received_data)
您可以在examples目录中找到更多示例。
它是如何工作的?
在库的核心,有两种类型的对象:TypeFormatter
和Struct
。
TypeFormatter
是一个格式化对象,可以解析和格式化指定类型的值。
Struct
是一个结构对象,它允许您定义对象序列化的规则。
因此,开发人员可以使用以下符号声明类:
class<StructName>(Struct):<member_name>=<TypeClass>(<default_value>)
或
classMessage(Struct):TimeOfDay=UInt64()# This creates a UInt64 formatter.DataLength=UInt8(128)# A default value is optionalMessage().serialize()#=> b'\x00\x00\x00\x00\x00\x00\x00\x00\x80'
声明的数据成员实际上(由于python的语法)是静态的。
创建类对象时,构造函数(deep)将每个格式化程序default_value
复制到同名的实例变量中,
因此,通过“诱使”用户认为不涉及格式化程序,可以实现一些透明度:
Class members:
TimeOfDay: UInt64 (default_value = 0)
DataLength: UInt8 (default_value = 128)
Object members:
TimeOfDay: 0
DataLength: 128
序列化对象时,对象的数据与类的格式化程序交叉引用。
所有整数都是使用python的struct.pack
函数在内部转换的。
验证器
可以将验证器对象分配给结构数据成员以定义验证规则。 当从二进制数据反序列化对象时,框架将验证这些值 使用用户定义的验证规则。
如果遇到无效值,将引发valueerror。
classMeIsValidated(Struct):member=Int8(0,validator=RangeValidator(-15,15))...MeIsValidated.deserialize('\x10')# => ValueError: The deserialized data is invalid.
为以下规则定义了一些内置验证器:
- 范围验证器:范围检查
- ExactValueValidator:精确值检查
- BitSizeValidator:位长度检查
- customvalidator:lambda验证(接收用户函数)
- TrueValidator&FalseValidator:虚拟验证器(始终为真/始终为假)
可以通过子类化validator类来定义更多的验证器。
lambda验证器
用户可以使用lambda表达式(或任何函数)而不是验证程序对象作为验证规则。
classMeIsLambda(Struct):member=Int8(0,validator=lambdavalue:value%3==0)
挂钩
派生类可以实现钩子。
序列化前
此方法将在序列化即将发生之前调用。
note:如果HydraSettings.dry_run
为真,则不会调用此方法,
或者用dry_run=True
serialize
序列化后
序列化发生后将调用此方法。
note:如果HydraSettings.dry_run
为真,则不会调用此方法,
或者用dry_run=True
serialize
验证
在反序列化完成后调用。
如果返回False
y值,deserialize
将引发错误。
如果在自定义结构类中没有被用户重写,则方法 将使用类型格式化程序的验证程序进行验证。
当然,用户可以重写方法以添加自定义验证, 然后调用原始的validate方法。
note:如果将HydraSettings.validate
设置为False
,则不会引发错误。