# Path: prpc/protocol/constants.py
# class MessageType(enum.IntEnum):
#     """Capstone enumeration of all protocol message types.
# 
#     Each message has it's own payload format, as defined in
#     :mod:`prpc.protocol.messages` module.
#     """
#     REQUEST_HANDSHAKE = 1
#     REQUEST_CALL_START = 2
#     REQUEST_CALL_CANCEL = 3
#     REQUEST_STREAM_MESSAGE = 4
#     REQUEST_STREAM_CLOSE = 5
#     RESPONSE_HANDSHAKE = 6
#     RESPONSE_RESULT = 7
#     RESPONSE_STREAM_MESSAGE = 8
#     RESPONSE_STREAM_CLOSE = 9


import collections
import msgpack
from .constants import MessageType
    generated using some factory. However, generating 'first-class' classes
    without self-introspection would require really ugly hacks with exec
    (e.g. see collections.namedtuple).
    As a bonus, manual classes are IDE-friendly.

Note:
    namedtuple itself isn't right as there is no sane way to 'bind' the
    first tuple argument to be constant (MessageType).
"""





_message_by_type = {}


def message_class(cls):
    """Decorator to register message class for deserialization.

    Explicit mapping looks cleaner than __subclasses__ hacks and
    adds some bonus validation.

    Args:
      cls: Class with (not yet registered) class-level MESSAGE_TYPE variable.

    Return:
      Cls itself without any changes.
    """
    global _message_by_type

# Path: prpc/protocol/constants.py
# class MessageType(enum.IntEnum):
#     """Capstone enumeration of all protocol message types.
# 
#     Each message has it's own payload format, as defined in
#     :mod:`prpc.protocol.messages` module.
#     """
#     REQUEST_HANDSHAKE = 1
#     REQUEST_CALL_START = 2
#     REQUEST_CALL_CANCEL = 3
#     REQUEST_STREAM_MESSAGE = 4
#     REQUEST_STREAM_CLOSE = 5
#     RESPONSE_HANDSHAKE = 6
#     RESPONSE_RESULT = 7
#     RESPONSE_STREAM_MESSAGE = 8
#     RESPONSE_STREAM_CLOSE = 9


# Path: prpc/protocol/messages.py
import collections
import msgpack
from .constants import MessageType

    generated using some factory. However, generating 'first-class' classes
    without self-introspection would require really ugly hacks with exec
    (e.g. see collections.namedtuple).
    As a bonus, manual classes are IDE-friendly.

Note:
    namedtuple itself isn't right as there is no sane way to 'bind' the
    first tuple argument to be constant (MessageType).
"""





_message_by_type = {}


def message_class(cls):
    """Decorator to register message class for deserialization.

    Explicit mapping looks cleaner than __subclasses__ hacks and
    adds some bonus validation.

    Args:
      cls: Class with (not yet registered) class-level MESSAGE_TYPE variable.

    Return:
      Cls itself without any changes.
    """
    global _message_by_type

    assert cls.MESSAGE_TYPE in MessageType