Feature request: Make cstruct iterable
Opened this issue · 1 comments
arnoutdekimo commented
Hi,
Just a thing for the wishlist: I would like to be able to parse binary data into a cstruct, and then convert it to e.g. a json element.
Currently though, the cstruct class isn't iterable.
If that would be added, it would be possible to convert generic objects to e.g. json and back, which is a pretty interesting feature.
Kind regards,
Arnout
arnoutdekimo commented
Well, I ended up implementing a new function in mem_cstruct.py:
def get_dict(self, convert_bytes_to_string = False) -> dict:
# Returns a dict and recursively parses more children
retdict = {}
for field, field_type in self.__fields_types__.items():
child = getattr(self, field)
if field_type.is_struct or field_type.is_union:
child = getattr(self, field)
if isinstance(child, list):
retdict[field] = []
for listelm in child:
# TODO: Can this be a list again, or will it always be a cstruct?
subchild = listelm.get_dict(convert_bytes_to_string)
retdict[field].append(subchild)
else:
retdict[field] = getattr(self, field).get_dict(convert_bytes_to_string)
else:
if type(child) == bytes and convert_bytes_to_string:
child = child.decode('utf-8', errors='ignore').rstrip('\0')
retdict[field] = child
return retdict
def update_from_dict(self, dict_in, convert_strings_to_bytes = False):
# Iterate through the dict levels, and attempt to update the matching nodes.
# Do this recursively
for key in dict_in:
value = dict_in[key]
if isinstance(value, dict):
# Recurse into child
getattr(self, key).update_from_dict(value, convert_strings_to_bytes)
elif isinstance(value, list):
cstructlist = getattr(self, key)
if isinstance(cstructlist, List):
for idx in range(0, len(value)):
# TODO: Assume never list in list
if isinstance(value[idx], dict):
cstructlist[idx].update_from_dict(value[idx], convert_strings_to_bytes)
else:
cstructlist[idx] = value[idx]
else:
raise Exception("Wrong type mapping for list object")
else:
# Attempt to update the current node
if convert_strings_to_bytes and isinstance(value, str):
value = value.encode('utf-8')
setattr(self, key, value)
This returns a dictionary, which can then easily be converted into json later