Skip to content

Decode Complex Objects #23

@thewhaleking

Description

@thewhaleking

I can decode complex objects (like 'Extrinsic') in py-scalecodec like so:

def get_decoder_class(self, type_string: Union[str, dict]):
    """
    Lookup and return a ScaleDecoder class for given `type_string`

    Parameters
    ----------
    type_string

    Returns
    -------
    ScaleDecoder
    """

    if type(type_string) is dict:
        # Inner struct
        decoder_class = type('InnerStruct', (self.get_decoder_class('Struct'),), {
            'type_mapping': tuple(type_string.items())
        })
        decoder_class.runtime_config = self
        return decoder_class

    if type_string.strip() == '':
        return None

    if self.implements_scale_info is False:
        type_string = self.convert_type_string(type_string)

    decoder_class = self.type_registry.get('types', {}).get(type_string.lower(), None)

    if not decoder_class:

        # Type string containg subtype
        if type_string[-1:] == '>':

            # Extract sub types
            type_parts = self.arrow_match_re.match(type_string)

            if type_parts:
                type_parts = type_parts.groups()

            if type_parts:
                # Create dynamic class for Part1<Part2> based on Part1 and set class variable Part2 as sub_type
                base_class = self.type_registry.get('types', {}).get(type_parts[0].lower(), None)
                if base_class:
                    decoder_class = type(type_string, (base_class,), {'sub_type': type_parts[1]})

        # Custom tuples
        elif type_string != '()' and type_string[0] == '(' and type_string[-1] == ')':

            decoder_class = type(type_string, (self.get_decoder_class('tuple'),), {
                'type_string': type_string
            })

            decoder_class.build_type_mapping()

        elif type_string[0] == '[' and type_string[-1] == ']':
            type_parts = self.bracket_match_re.match(type_string)

            if type_parts:
                type_parts = type_parts.groups()

            if type_parts:
                # Create dynamic class for e.g. [u8; 4] resulting in array of u8 with 4 elements
                decoder_class = type(type_string, (self.get_decoder_class('FixedLengthArray'),), {
                    'sub_type': type_parts[0],
                    'element_count': int(type_parts[1])
                })

    if decoder_class:
        # Attach RuntimeConfigurationObject to new class
        decoder_class.runtime_config = self

    return decoder_class

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions