Skip to content

Instantly share code, notes, and snippets.

@chen3feng
Last active December 10, 2020 04:49
Show Gist options
  • Save chen3feng/59af2ed84e45851cf07c4984206b2f8a to your computer and use it in GitHub Desktop.
Save chen3feng/59af2ed84e45851cf07c4984206b2f8a to your computer and use it in GitHub Desktop.
NamedStruct, a combinationof struct and namedtuple in python, make code more readable
"""
NamedStruct, a combinationof struct and namedtuple in python, make code more readable.
You can access the fields by name rather than index.
"""
from __future__ import print_function
import struct
from collections import namedtuple
_BYTE_ORDERS = (
'native', 'little-endian', 'big-endian', 'network')
_TYPES = {
'char' : 'c',
'int8' : 'b',
'uint8' : 'B',
'bool' : '?',
'int16' : 'h',
'uint16' : 'H',
'int32' : 'i',
'uint32' : 'I',
'int64' : 'q',
'uint64' : 'Q',
'float' : 'f',
'double' : 'd',
'string' : 's',
'psacal_string' : 'p',
'pointer' : 'P',
}
class NamedStruct(object):
def __init__(self, name, fields, byteorder=''):
self.name = name
self.byteorder = byteorder
self.fields, self.names, self.format = self._parse(fields)
self._struct = struct.Struct(self.format)
self._namedtuple = namedtuple(self.name, self.names)
def sizeof(self):
return self._struct.size()
def pack(self, *args):
return self._struct.pack(*args)
def pack_into(self, buffer, offset, *args):
return self._struct.pack_into(buffer, offset, *args)
def unpack(self, string):
return self._namedtuple._make(self._struct.unpack(string))
def unpack_from(self, buffer, offset=0):
return self._namedtuple._make(self._struct.unpack_from(buffer, offset))
def __str__(self):
return 'struct %s {\n %s;\n}' % (self.name, ';\n '.join(self.fields))
def _string_type_format(self, type):
type = type[len('string'):]
return type[1:-1] + _TYPES['string']
def _parse(self, fields):
if isinstance(fields, str):
fields = [f.strip() for f in fields.split(';')]
format = self.byteorder
names = []
for f in fields:
type, name = f.split()
if type.startswith('string'):
format += self._string_type_format(type)
else:
format += _TYPES[type]
names.append(name)
return fields, names, format
def main():
record = 'raymond \x32\x12\x08\x01\x08'
Student = NamedStruct(
'Student', [
'string<10> name',
'uint16 serialnumn',
'uint16 school',
'int8 gradelevel'],
byteorder='<')
print(Student)
student = Student.unpack(record)
print(student)
if __name__ == '__main__':
main()
@chen3feng
Copy link
Author

chen3feng commented May 30, 2020

NamedStruct 让你可以用名字而不是下标来访问结构体成员,提高代码的可读性。

Origin from:
https://stackoverflow.com/questions/11461125/is-there-an-elegant-way-to-use-struct-and-namedtuple-instead-of-this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment