Package: binpi
binpibinpi aims to provide a simple interface for serializing and deserializing binary file formats.Usage:importbinpiclassData:...classFileHeader:prop1=binpi.Int()prop2=binpi.Short()prop3=binpi.Byte()is_compressed=binpi.Boolean()float_prop=binpi.Float()some_data=binpi.ByteArray(size="prop1")other_data=binpi.List(Data,size="prop3")sub_struct=binpi.WrapType(Data)children_count=binpi.Int()children=binpi.List(binpi.RecursiveType(),size="children_count")# deserializingheader_data=binpi.deserialize(FileHeader,binpi.FileReader("./some_path"),endianness=binpi.LITTLE_ENDIAN)# modifyheader_data.prop2=200# serializingwriter=binpi.serialize(header_data,binpi.FileWriter("./another_path"),endianness=binpi.LITTLE_ENDIAN)For more complex examples, check./examples/How to install:pipinstallbinpiSupported Types:Int, UInt, Short, UShort, Byte, UByte, Float, DoubleIntEnumTypeList, String, ByteArrayBooleanRecursiveType (for cases where the structure contains list of substructures of the same type, check theadvanced_structureexample)WrapType (for subtypes, check thesimple_image_archive_formatexample)All the types above support LE/BEComparing with other (de)serializing librariespickle- should be used for completely different use-cases thanbinpi, which is just simple deserializing of python objects, without having to care about its structure.struct- anythingbinpidoes can be implemented usingstruct, butbinpiprovides simpler interface for defining data structure, for the cost of performance.origami- origami might be a better choice for (de)serializing fixed size data, but it doesn't provide (de)serializing of dynamically sized data, out of the box.bstruct- same asorigamiconstruct- probably the most comparable library tobinpi, has even more feature, but instead ofbinpi, the data structures and output is represented using dictionariesInterfaceSerializingdefserialize(value,# value to be serializedwriter:Writer,# the output writerfirst=None,# first field to serializelast=None# last field to serialize)->None:...classWriter(Protocol):""" writer can be anything that implements method write_bytes """defwrite_bytes(self,data:bytes)->None:...binpi containsFileWriterandBufferWriterDeserializingdefdeserialize(class_:type,# type of the target objectreader:Reader,# the input readerfirst=None,# first field to serializelast=None# last field to serialize)->None:...classReader(Protocol):""" reader can be anything that implements method read_bytes """defread_bytes(self,n:int)->bytes:...binpi containsFileReaderandBufferReaderExtending with custom typesTo create your own custom (de)serializable type, you have to just create a new child class ofSerializableTypethat implementsload_from_bytesandwrite_from_valueimporttyping,binpi,structclassCustomDoubledInt(binpi.SerializableType):defload_from_bytes(self,deserializer:binpi.Deserializer,instance,*args,**kwargs):returnstruct.unpack("<i",deserializer.reader.read_bytes(4))[0]*2defwrite_from_value(self,serializer:binpi.Serializer,value,parent_instance,*args,**kwargs):serializer.writer.write_bytes(struct.pack("<i",value//2))""" In case we want to have functional typechecking """CustomDoubleInt:typing.Callable[...,int]TODO:TestsPerformance benchmarks