# Auto-generated, do not edit

from messages import *
#from io cimport BytesIO
from io import BytesIO
from libc.stdlib cimport abort

cdef extern from "Python.h":
    int PyArg_ParseTupleAndKeywords(object args, object kwargs, char* format, char** keywords, ...)

cdef class PyMsg:
    def __cinit__(self):
        pass

ctypedef object PyBytesIO

cdef class MessageCodec:
    """
    Implements encode/decode primitives
    """
    cdef list msg_selector

    def __init__(self, list msg_selector):
        self.msg_selector = msg_selector

    @staticmethod
    cdef read_boolean(PyBytesIO reader):
        cdef bint b
        b = reader.read(1)[0]
        return b == 1

    @staticmethod
    def read_bool_method(PyBytesIO reader):
        return MessageCodec.read_boolean(reader)

    @staticmethod
    cdef read_uint(PyBytesIO reader):
        cdef unsigned long x = 0  # the result
        cdef unsigned int s = 0  # the shift (our result is big-ending)
        cdef int i = 0  # n of byte (max 9 for uint64)
        cdef bytes b
        cdef unsigned long num

        while True:
            b = reader.read(1)
            if len(b) == 0:
                raise IndexError('bytes out of range')

            num = int.from_bytes(b, "big", signed=False)

            if num < 0x80:
                if i > 9 or (i == 9 and num > 1):
                    raise OverflowError()
                return int(x | num << s)
            x |= (num & 0x7f) << s
            s += 7
            i += 1

    @staticmethod
    def read_size(PyBytesIO reader):
        cdef unsigned long size = 0
        cdef bytes b
        cdef unsigned long num
        for i in range(3):
            b = reader.read(1)
            num = int.from_bytes(b, "big", signed=False)
            size += num << (8*i)
        return size


    @staticmethod
    def read_int(PyBytesIO reader):
        """
        ux, err := ReadUint(reader)
        x := int64(ux >> 1)
        if err != nil {
            return x, err
        }
        if ux&1 != 0 {
            x = ^x
        }
        return x, err
        """
        cdef unsigned long ux = MessageCodec.read_uint(reader)
        cdef long x = int(ux >> 1)

        if ux & 1 != 0:
            x = - x - 1
        return x

    @staticmethod
    def read_string(PyBytesIO reader):
        cdef unsigned long length = MessageCodec.read_uint(reader)
        cdef bytes s
        try:
            s = reader.read(length)
        except Exception as e:
            print(f'Error while reading string of length {length}')
            raise Exception(e)
        try:
            return s.decode("utf-8", errors="replace").replace("\x00", "\uFFFD")
        except UnicodeDecodeError:
            return None

    @staticmethod
    def read_message_id(PyBytesIO reader):
        """
        Read and return the first byte where the message id is encoded
        """
        cdef unsigned long id_ = MessageCodec.read_uint(reader)
        return id_

    @staticmethod
    def encode(PyMsg m):
        ...

    @staticmethod
    def decode(bytes b):
        cdef PyBytesIO reader = BytesIO(b)
        return MessageCodec.read_head_message(reader)

    @staticmethod
    def check_message_id(bytes b):
        """
        todo: make it static and without reader. It's just the first byte
        Read and return the first byte where the message id is encoded
        """
        cdef PyBytesIO reader = BytesIO(b)
        cdef unsigned long id_ = MessageCodec.read_uint(reader)

        return id_

    @staticmethod
    def decode_key(bytes b):
        """
        Decode the message key (encoded with little endian)
        """
        cdef unsigned long decoded
        try:
            decoded = int.from_bytes(b, "little", signed=False)
        except Exception as e:
            print(f"Error while decoding message key (SessionID) from {b}")
            raise e
        return decoded

    def decode_detailed(self, bytes b):
        cdef PyBytesIO reader = BytesIO(b)
        cdef list messages_list
        cdef int mode
        try:
            messages_list = [self.handler(reader, 0)]
        except IndexError:
            print('[WARN] Broken batch')
            return list()
        if isinstance(messages_list[0], BatchMeta):
            # Old BatchMeta
            mode = 0
        elif isinstance(messages_list[0], BatchMetadata):
            # New BatchMeta
            if messages_list[0].version == 0:
                mode = 0
            else:
                mode = 1
        else:
            return messages_list
        while True:
            try:
                msg_decoded = self.handler(reader, mode)
                if msg_decoded is not None:
                    messages_list.append(msg_decoded)
            except IndexError:
                break
        return messages_list

    def handler(self, PyBytesIO reader, int mode = 0):
        cdef unsigned long message_id = MessageCodec.read_message_id(reader)
        cdef int r_size
        if mode == 1:
            # We read the three bytes representing the length of message. It can be used to skip unwanted messages
            r_size = MessageCodec.read_size(reader)
            if message_id not in self.msg_selector:
                reader.read(r_size)
                return None
            return MessageCodec.read_head_message(reader, message_id)
        elif mode == 0:
            # Old format with no bytes for message length
            return MessageCodec.read_head_message(reader, message_id)
        else:
            raise IOError()

    @staticmethod
    def read_head_message(PyBytesIO reader, unsigned long message_id):

        if message_id == 0:
            return Timestamp(
                timestamp=self.read_uint(reader)
            )

        if message_id == 1:
            return SessionStart(
                timestamp=self.read_uint(reader),
                project_id=self.read_uint(reader),
                tracker_version=self.read_string(reader),
                rev_id=self.read_string(reader),
                user_uuid=self.read_string(reader),
                user_agent=self.read_string(reader),
                user_os=self.read_string(reader),
                user_os_version=self.read_string(reader),
                user_browser=self.read_string(reader),
                user_browser_version=self.read_string(reader),
                user_device=self.read_string(reader),
                user_device_type=self.read_string(reader),
                user_device_memory_size=self.read_uint(reader),
                user_device_heap_size=self.read_uint(reader),
                user_country=self.read_string(reader),
                user_id=self.read_string(reader)
            )

        if message_id == 4:
            return SetPageLocationDeprecated(
                url=self.read_string(reader),
                referrer=self.read_string(reader),
                navigation_start=self.read_uint(reader)
            )

        if message_id == 5:
            return SetViewportSize(
                width=self.read_uint(reader),
                height=self.read_uint(reader)
            )

        if message_id == 6:
            return SetViewportScroll(
                x=self.read_int(reader),
                y=self.read_int(reader)
            )

        if message_id == 7:
            return CreateDocument(
                
            )

        if message_id == 8:
            return CreateElementNode(
                id=self.read_uint(reader),
                parent_id=self.read_uint(reader),
                index=self.read_uint(reader),
                tag=self.read_string(reader),
                svg=self.read_boolean(reader)
            )

        if message_id == 9:
            return CreateTextNode(
                id=self.read_uint(reader),
                parent_id=self.read_uint(reader),
                index=self.read_uint(reader)
            )

        if message_id == 10:
            return MoveNode(
                id=self.read_uint(reader),
                parent_id=self.read_uint(reader),
                index=self.read_uint(reader)
            )

        if message_id == 11:
            return RemoveNode(
                id=self.read_uint(reader)
            )

        if message_id == 12:
            return SetNodeAttribute(
                id=self.read_uint(reader),
                name=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 13:
            return RemoveNodeAttribute(
                id=self.read_uint(reader),
                name=self.read_string(reader)
            )

        if message_id == 14:
            return SetNodeData(
                id=self.read_uint(reader),
                data=self.read_string(reader)
            )

        if message_id == 15:
            return SetCSSData(
                id=self.read_uint(reader),
                data=self.read_string(reader)
            )

        if message_id == 16:
            return SetNodeScroll(
                id=self.read_uint(reader),
                x=self.read_int(reader),
                y=self.read_int(reader)
            )

        if message_id == 17:
            return SetInputTarget(
                id=self.read_uint(reader),
                label=self.read_string(reader)
            )

        if message_id == 18:
            return SetInputValue(
                id=self.read_uint(reader),
                value=self.read_string(reader),
                mask=self.read_int(reader)
            )

        if message_id == 19:
            return SetInputChecked(
                id=self.read_uint(reader),
                checked=self.read_boolean(reader)
            )

        if message_id == 20:
            return MouseMove(
                x=self.read_uint(reader),
                y=self.read_uint(reader)
            )

        if message_id == 21:
            return NetworkRequestDeprecated(
                type=self.read_string(reader),
                method=self.read_string(reader),
                url=self.read_string(reader),
                request=self.read_string(reader),
                response=self.read_string(reader),
                status=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                duration=self.read_uint(reader)
            )

        if message_id == 22:
            return ConsoleLog(
                level=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 23:
            return PageLoadTiming(
                request_start=self.read_uint(reader),
                response_start=self.read_uint(reader),
                response_end=self.read_uint(reader),
                dom_content_loaded_event_start=self.read_uint(reader),
                dom_content_loaded_event_end=self.read_uint(reader),
                load_event_start=self.read_uint(reader),
                load_event_end=self.read_uint(reader),
                first_paint=self.read_uint(reader),
                first_contentful_paint=self.read_uint(reader)
            )

        if message_id == 24:
            return PageRenderTiming(
                speed_index=self.read_uint(reader),
                visually_complete=self.read_uint(reader),
                time_to_interactive=self.read_uint(reader)
            )

        if message_id == 26:
            return IntegrationEvent(
                timestamp=self.read_uint(reader),
                source=self.read_string(reader),
                name=self.read_string(reader),
                message=self.read_string(reader),
                payload=self.read_string(reader)
            )

        if message_id == 27:
            return CustomEvent(
                name=self.read_string(reader),
                payload=self.read_string(reader)
            )

        if message_id == 28:
            return UserID(
                id=self.read_string(reader)
            )

        if message_id == 29:
            return UserAnonymousID(
                id=self.read_string(reader)
            )

        if message_id == 30:
            return Metadata(
                key=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 31:
            return PageEventDeprecated(
                message_id=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                url=self.read_string(reader),
                referrer=self.read_string(reader),
                loaded=self.read_boolean(reader),
                request_start=self.read_uint(reader),
                response_start=self.read_uint(reader),
                response_end=self.read_uint(reader),
                dom_content_loaded_event_start=self.read_uint(reader),
                dom_content_loaded_event_end=self.read_uint(reader),
                load_event_start=self.read_uint(reader),
                load_event_end=self.read_uint(reader),
                first_paint=self.read_uint(reader),
                first_contentful_paint=self.read_uint(reader),
                speed_index=self.read_uint(reader),
                visually_complete=self.read_uint(reader),
                time_to_interactive=self.read_uint(reader)
            )

        if message_id == 32:
            return InputEvent(
                message_id=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                value=self.read_string(reader),
                value_masked=self.read_boolean(reader),
                label=self.read_string(reader)
            )

        if message_id == 33:
            return PageEvent(
                message_id=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                url=self.read_string(reader),
                referrer=self.read_string(reader),
                loaded=self.read_boolean(reader),
                request_start=self.read_uint(reader),
                response_start=self.read_uint(reader),
                response_end=self.read_uint(reader),
                dom_content_loaded_event_start=self.read_uint(reader),
                dom_content_loaded_event_end=self.read_uint(reader),
                load_event_start=self.read_uint(reader),
                load_event_end=self.read_uint(reader),
                first_paint=self.read_uint(reader),
                first_contentful_paint=self.read_uint(reader),
                speed_index=self.read_uint(reader),
                visually_complete=self.read_uint(reader),
                time_to_interactive=self.read_uint(reader),
                web_vitals=self.read_string(reader)
            )

        if message_id == 34:
            return StringDictGlobal(
                key=self.read_uint(reader),
                value=self.read_string(reader)
            )

        if message_id == 35:
            return SetNodeAttributeDictGlobal(
                id=self.read_uint(reader),
                name=self.read_uint(reader),
                value=self.read_uint(reader)
            )

        if message_id == 40:
            return Profiler(
                name=self.read_string(reader),
                duration=self.read_uint(reader),
                args=self.read_string(reader),
                result=self.read_string(reader)
            )

        if message_id == 41:
            return OTable(
                key=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 42:
            return StateAction(
                type=self.read_string(reader)
            )

        if message_id == 44:
            return ReduxDeprecated(
                action=self.read_string(reader),
                state=self.read_string(reader),
                duration=self.read_uint(reader)
            )

        if message_id == 45:
            return Vuex(
                mutation=self.read_string(reader),
                state=self.read_string(reader)
            )

        if message_id == 46:
            return MobX(
                type=self.read_string(reader),
                payload=self.read_string(reader)
            )

        if message_id == 47:
            return NgRx(
                action=self.read_string(reader),
                state=self.read_string(reader),
                duration=self.read_uint(reader)
            )

        if message_id == 48:
            return GraphQLDeprecated(
                operation_kind=self.read_string(reader),
                operation_name=self.read_string(reader),
                variables=self.read_string(reader),
                response=self.read_string(reader),
                duration=self.read_int(reader)
            )

        if message_id == 49:
            return PerformanceTrack(
                frames=self.read_int(reader),
                ticks=self.read_int(reader),
                total_js_heap_size=self.read_uint(reader),
                used_js_heap_size=self.read_uint(reader)
            )

        if message_id == 50:
            return StringDictDeprecated(
                key=self.read_uint(reader),
                value=self.read_string(reader)
            )

        if message_id == 51:
            return SetNodeAttributeDictDeprecated(
                id=self.read_uint(reader),
                name_key=self.read_uint(reader),
                value_key=self.read_uint(reader)
            )

        if message_id == 43:
            return StringDict(
                key=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 52:
            return SetNodeAttributeDict(
                id=self.read_uint(reader),
                name=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 53:
            return ResourceTimingDeprecated(
                timestamp=self.read_uint(reader),
                duration=self.read_uint(reader),
                ttfb=self.read_uint(reader),
                header_size=self.read_uint(reader),
                encoded_body_size=self.read_uint(reader),
                decoded_body_size=self.read_uint(reader),
                url=self.read_string(reader),
                initiator=self.read_string(reader)
            )

        if message_id == 54:
            return ConnectionInformation(
                downlink=self.read_uint(reader),
                type=self.read_string(reader)
            )

        if message_id == 55:
            return SetPageVisibility(
                hidden=self.read_boolean(reader)
            )

        if message_id == 56:
            return PerformanceTrackAggr(
                timestamp_start=self.read_uint(reader),
                timestamp_end=self.read_uint(reader),
                min_fps=self.read_uint(reader),
                avg_fps=self.read_uint(reader),
                max_fps=self.read_uint(reader),
                min_cpu=self.read_uint(reader),
                avg_cpu=self.read_uint(reader),
                max_cpu=self.read_uint(reader),
                min_total_js_heap_size=self.read_uint(reader),
                avg_total_js_heap_size=self.read_uint(reader),
                max_total_js_heap_size=self.read_uint(reader),
                min_used_js_heap_size=self.read_uint(reader),
                avg_used_js_heap_size=self.read_uint(reader),
                max_used_js_heap_size=self.read_uint(reader)
            )

        if message_id == 57:
            return LoadFontFace(
                parent_id=self.read_uint(reader),
                family=self.read_string(reader),
                source=self.read_string(reader),
                descriptors=self.read_string(reader)
            )

        if message_id == 58:
            return SetNodeFocus(
                id=self.read_int(reader)
            )

        if message_id == 60:
            return SetNodeAttributeURLBased(
                id=self.read_uint(reader),
                name=self.read_string(reader),
                value=self.read_string(reader),
                base_url=self.read_string(reader)
            )

        if message_id == 61:
            return SetCSSDataURLBased(
                id=self.read_uint(reader),
                data=self.read_string(reader),
                base_url=self.read_string(reader)
            )

        if message_id == 63:
            return TechnicalInfo(
                type=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 64:
            return CustomIssue(
                name=self.read_string(reader),
                payload=self.read_string(reader)
            )

        if message_id == 66:
            return AssetCache(
                url=self.read_string(reader)
            )

        if message_id == 68:
            return MouseClick(
                id=self.read_uint(reader),
                hesitation_time=self.read_uint(reader),
                label=self.read_string(reader),
                selector=self.read_string(reader),
                normalized_x=self.read_uint(reader),
                normalized_y=self.read_uint(reader)
            )

        if message_id == 69:
            return MouseClickDeprecated(
                id=self.read_uint(reader),
                hesitation_time=self.read_uint(reader),
                label=self.read_string(reader),
                selector=self.read_string(reader)
            )

        if message_id == 70:
            return CreateIFrameDocument(
                frame_id=self.read_uint(reader),
                id=self.read_uint(reader)
            )

        if message_id == 71:
            return AdoptedSSReplaceURLBased(
                sheet_id=self.read_uint(reader),
                text=self.read_string(reader),
                base_url=self.read_string(reader)
            )

        if message_id == 72:
            return AdoptedSSReplace(
                sheet_id=self.read_uint(reader),
                text=self.read_string(reader)
            )

        if message_id == 73:
            return AdoptedSSInsertRuleURLBased(
                sheet_id=self.read_uint(reader),
                rule=self.read_string(reader),
                index=self.read_uint(reader),
                base_url=self.read_string(reader)
            )

        if message_id == 74:
            return AdoptedSSInsertRule(
                sheet_id=self.read_uint(reader),
                rule=self.read_string(reader),
                index=self.read_uint(reader)
            )

        if message_id == 75:
            return AdoptedSSDeleteRule(
                sheet_id=self.read_uint(reader),
                index=self.read_uint(reader)
            )

        if message_id == 76:
            return AdoptedSSAddOwner(
                sheet_id=self.read_uint(reader),
                id=self.read_uint(reader)
            )

        if message_id == 77:
            return AdoptedSSRemoveOwner(
                sheet_id=self.read_uint(reader),
                id=self.read_uint(reader)
            )

        if message_id == 78:
            return JSException(
                name=self.read_string(reader),
                message=self.read_string(reader),
                payload=self.read_string(reader),
                metadata=self.read_string(reader)
            )

        if message_id == 79:
            return Zustand(
                mutation=self.read_string(reader),
                state=self.read_string(reader)
            )

        if message_id == 81:
            return BatchMetadata(
                version=self.read_uint(reader),
                page_no=self.read_uint(reader),
                first_index=self.read_uint(reader),
                timestamp=self.read_int(reader),
                location=self.read_string(reader)
            )

        if message_id == 82:
            return PartitionedMessage(
                part_no=self.read_uint(reader),
                part_total=self.read_uint(reader)
            )

        if message_id == 83:
            return NetworkRequest(
                type=self.read_string(reader),
                method=self.read_string(reader),
                url=self.read_string(reader),
                request=self.read_string(reader),
                response=self.read_string(reader),
                status=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                duration=self.read_uint(reader),
                transferred_body_size=self.read_uint(reader)
            )

        if message_id == 84:
            return WSChannel(
                ch_type=self.read_string(reader),
                channel_name=self.read_string(reader),
                data=self.read_string(reader),
                timestamp=self.read_uint(reader),
                dir=self.read_string(reader),
                message_type=self.read_string(reader)
            )

        if message_id == 112:
            return InputChange(
                id=self.read_uint(reader),
                value=self.read_string(reader),
                value_masked=self.read_boolean(reader),
                label=self.read_string(reader),
                hesitation_time=self.read_int(reader),
                input_duration=self.read_int(reader)
            )

        if message_id == 113:
            return SelectionChange(
                selection_start=self.read_uint(reader),
                selection_end=self.read_uint(reader),
                selection=self.read_string(reader)
            )

        if message_id == 114:
            return MouseThrashing(
                timestamp=self.read_uint(reader)
            )

        if message_id == 115:
            return UnbindNodes(
                total_removed_percent=self.read_uint(reader)
            )

        if message_id == 116:
            return ResourceTiming(
                timestamp=self.read_uint(reader),
                duration=self.read_uint(reader),
                ttfb=self.read_uint(reader),
                header_size=self.read_uint(reader),
                encoded_body_size=self.read_uint(reader),
                decoded_body_size=self.read_uint(reader),
                url=self.read_string(reader),
                initiator=self.read_string(reader),
                transferred_size=self.read_uint(reader),
                cached=self.read_boolean(reader)
            )

        if message_id == 117:
            return TabChange(
                tab_id=self.read_string(reader)
            )

        if message_id == 118:
            return TabData(
                tab_id=self.read_string(reader)
            )

        if message_id == 119:
            return CanvasNode(
                node_id=self.read_string(reader),
                timestamp=self.read_uint(reader)
            )

        if message_id == 120:
            return TagTrigger(
                tag_id=self.read_int(reader)
            )

        if message_id == 121:
            return Redux(
                action=self.read_string(reader),
                state=self.read_string(reader),
                duration=self.read_uint(reader),
                action_time=self.read_uint(reader)
            )

        if message_id == 122:
            return SetPageLocation(
                url=self.read_string(reader),
                referrer=self.read_string(reader),
                navigation_start=self.read_uint(reader),
                document_title=self.read_string(reader)
            )

        if message_id == 123:
            return GraphQL(
                operation_kind=self.read_string(reader),
                operation_name=self.read_string(reader),
                variables=self.read_string(reader),
                response=self.read_string(reader),
                duration=self.read_uint(reader)
            )

        if message_id == 124:
            return WebVitals(
                name=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 125:
            return IssueEvent(
                message_id=self.read_uint(reader),
                timestamp=self.read_uint(reader),
                type=self.read_string(reader),
                context_string=self.read_string(reader),
                context=self.read_string(reader),
                payload=self.read_string(reader),
                url=self.read_string(reader)
            )

        if message_id == 126:
            return SessionEnd(
                timestamp=self.read_uint(reader),
                encryption_key=self.read_string(reader)
            )

        if message_id == 127:
            return SessionSearch(
                timestamp=self.read_uint(reader),
                partition=self.read_uint(reader)
            )

        if message_id == 90:
            return MobileSessionStart(
                timestamp=self.read_uint(reader),
                project_id=self.read_uint(reader),
                tracker_version=self.read_string(reader),
                rev_id=self.read_string(reader),
                user_uuid=self.read_string(reader),
                user_os=self.read_string(reader),
                user_os_version=self.read_string(reader),
                user_device=self.read_string(reader),
                user_device_type=self.read_string(reader),
                user_country=self.read_string(reader)
            )

        if message_id == 91:
            return MobileSessionEnd(
                timestamp=self.read_uint(reader)
            )

        if message_id == 92:
            return MobileMetadata(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                key=self.read_string(reader),
                value=self.read_string(reader)
            )

        if message_id == 93:
            return MobileEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                name=self.read_string(reader),
                payload=self.read_string(reader)
            )

        if message_id == 94:
            return MobileUserID(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                id=self.read_string(reader)
            )

        if message_id == 95:
            return MobileUserAnonymousID(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                id=self.read_string(reader)
            )

        if message_id == 96:
            return MobileScreenChanges(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                x=self.read_uint(reader),
                y=self.read_uint(reader),
                width=self.read_uint(reader),
                height=self.read_uint(reader)
            )

        if message_id == 97:
            return MobileCrash(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                name=self.read_string(reader),
                reason=self.read_string(reader),
                stacktrace=self.read_string(reader)
            )

        if message_id == 98:
            return MobileViewComponentEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                screen_name=self.read_string(reader),
                view_name=self.read_string(reader),
                visible=self.read_boolean(reader)
            )

        if message_id == 100:
            return MobileClickEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                label=self.read_string(reader),
                x=self.read_uint(reader),
                y=self.read_uint(reader)
            )

        if message_id == 101:
            return MobileInputEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                value=self.read_string(reader),
                value_masked=self.read_boolean(reader),
                label=self.read_string(reader)
            )

        if message_id == 102:
            return MobilePerformanceEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                name=self.read_string(reader),
                value=self.read_uint(reader)
            )

        if message_id == 103:
            return MobileLog(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                severity=self.read_string(reader),
                content=self.read_string(reader)
            )

        if message_id == 104:
            return MobileInternalError(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                content=self.read_string(reader)
            )

        if message_id == 105:
            return MobileNetworkCall(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                type=self.read_string(reader),
                method=self.read_string(reader),
                url=self.read_string(reader),
                request=self.read_string(reader),
                response=self.read_string(reader),
                status=self.read_uint(reader),
                duration=self.read_uint(reader)
            )

        if message_id == 106:
            return MobileSwipeEvent(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                label=self.read_string(reader),
                x=self.read_uint(reader),
                y=self.read_uint(reader),
                direction=self.read_string(reader)
            )

        if message_id == 107:
            return MobileBatchMeta(
                timestamp=self.read_uint(reader),
                length=self.read_uint(reader),
                first_index=self.read_uint(reader)
            )

        if message_id == 110:
            return MobilePerformanceAggregated(
                timestamp_start=self.read_uint(reader),
                timestamp_end=self.read_uint(reader),
                min_fps=self.read_uint(reader),
                avg_fps=self.read_uint(reader),
                max_fps=self.read_uint(reader),
                min_cpu=self.read_uint(reader),
                avg_cpu=self.read_uint(reader),
                max_cpu=self.read_uint(reader),
                min_memory=self.read_uint(reader),
                avg_memory=self.read_uint(reader),
                max_memory=self.read_uint(reader),
                min_battery=self.read_uint(reader),
                avg_battery=self.read_uint(reader),
                max_battery=self.read_uint(reader)
            )

        if message_id == 111:
            return MobileIssueEvent(
                timestamp=self.read_uint(reader),
                type=self.read_string(reader),
                context_string=self.read_string(reader),
                context=self.read_string(reader),
                payload=self.read_string(reader)
            )

