Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Make cstruct iterable #26

Open
arnoutdekimo opened this issue Apr 16, 2024 · 1 comment
Open

Feature request: Make cstruct iterable #26

arnoutdekimo opened this issue Apr 16, 2024 · 1 comment

Comments

@arnoutdekimo
Copy link

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
Copy link
Author

arnoutdekimo commented Apr 17, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant