# Path: azmq/errors.py
# class ProtocolError(AZMQError):
#     def __init__(self, msg, fatal=False):
#         super().__init__(msg)
#         self.fatal = fatal
# 
# Path: azmq/metadata.py
# def buffer_to_metadata(buffer):
#     """
#     Transform a buffer to a metadata dictionary.
# 
#     :param buffer: The buffer, as received in a READY command.
#     :returns: A metadata dictionary, with its keys normalized (in
#         lowercase).
#     """
#     offset = 0
#     size = len(buffer)
#     metadata = {}
# 
#     while offset < size:
#         name_size = struct.unpack_from('B', buffer, offset)[0]
#         offset += 1
# 
#         if name_size > size - 4:
#             raise ProtocolError(
#                 "Invalid name size in metadata",
#                 fatal=True,
#             )
# 
#         name = buffer[offset:offset + name_size]
#         offset += name_size
# 
#         value_size = struct.unpack_from('!I', buffer, offset)[0]
#         offset += 4
# 
#         if value_size > size - name_size - 5:
#             raise ProtocolError(
#                 "Invalid value size in metadata",
#                 fatal=True,
#             )
# 
#         value = buffer[offset:offset + value_size]
#         offset += value_size
#         metadata[name.lower()] = value
# 
#     return metadata
# 
# def metadata_to_buffers(metadata):
#     """
#     Transform a dict of metadata into a sequence of buffers.
# 
#     :param metadata: The metadata, as a dict.
#     :returns: A list of buffers.
#     """
#     results = []
# 
#     for key, value in metadata.items():
#         assert len(key) < 256
#         assert len(value) < 2 ** 32
#         results.extend([
#             struct.pack('!B', len(key)),
#             key,
#             struct.pack('!I', len(value)),
#             value,
#         ])
# 
#     return results


import struct
from itertools import islice
from ..errors import ProtocolError
from ..metadata import (
    buffer_to_metadata,
    metadata_to_buffers,
)

        :param reader: The reader to use.
        :returns: The command data.
        """
        size_type = struct.unpack('B', await reader.readexactly(1))[0]

        if size_type == 0x04:
            size = struct.unpack('!B', await reader.readexactly(1))[0]
        elif size_type == 0x06:
            size = struct.unpack('!Q', await reader.readexactly(8))[0]
        else:
            raise ProtocolError(
                "Unexpected size type: %0x" % size_type,
                fatal=True,
            )

        name_size = struct.unpack('B', await reader.readexactly(1))[0]

        if name_size != len(name):
            raise ProtocolError(
                "Unexpected command name size: %s (expecting %s)" % (
                    name_size,
                    len(name),
                ),
                fatal=True,
            )

        c_name = await reader.readexactly(name_size)

        if c_name != name:

# Path: azmq/errors.py
# class ProtocolError(AZMQError):
#     def __init__(self, msg, fatal=False):
#         super().__init__(msg)
#         self.fatal = fatal
# 
# Path: azmq/metadata.py
# def buffer_to_metadata(buffer):
#     """
#     Transform a buffer to a metadata dictionary.
# 
#     :param buffer: The buffer, as received in a READY command.
#     :returns: A metadata dictionary, with its keys normalized (in
#         lowercase).
#     """
#     offset = 0
#     size = len(buffer)
#     metadata = {}
# 
#     while offset < size:
#         name_size = struct.unpack_from('B', buffer, offset)[0]
#         offset += 1
# 
#         if name_size > size - 4:
#             raise ProtocolError(
#                 "Invalid name size in metadata",
#                 fatal=True,
#             )
# 
#         name = buffer[offset:offset + name_size]
#         offset += name_size
# 
#         value_size = struct.unpack_from('!I', buffer, offset)[0]
#         offset += 4
# 
#         if value_size > size - name_size - 5:
#             raise ProtocolError(
#                 "Invalid value size in metadata",
#                 fatal=True,
#             )
# 
#         value = buffer[offset:offset + value_size]
#         offset += value_size
#         metadata[name.lower()] = value
# 
#     return metadata
# 
# def metadata_to_buffers(metadata):
#     """
#     Transform a dict of metadata into a sequence of buffers.
# 
#     :param metadata: The metadata, as a dict.
#     :returns: A list of buffers.
#     """
#     results = []
# 
#     for key, value in metadata.items():
#         assert len(key) < 256
#         assert len(value) < 2 ** 32
#         results.extend([
#             struct.pack('!B', len(key)),
#             key,
#             struct.pack('!I', len(value)),
#             value,
#         ])
# 
#     return results


# Path: azmq/mechanisms/base.py
import struct
from itertools import islice
from ..errors import ProtocolError
from ..metadata import (
    buffer_to_metadata,
    metadata_to_buffers,
)


        :param reader: The reader to use.
        :returns: The command data.
        """
        size_type = struct.unpack('B', await reader.readexactly(1))[0]

        if size_type == 0x04:
            size = struct.unpack('!B', await reader.readexactly(1))[0]
        elif size_type == 0x06:
            size = struct.unpack('!Q', await reader.readexactly(8))[0]
        else:
            raise ProtocolError(
                "Unexpected size type: %0x" % size_type,
                fatal=True,
            )

        name_size = struct.unpack('B', await reader.readexactly(1))[0]

        if name_size != len(name):
            raise ProtocolError(
                "Unexpected command name size: %s (expecting %s)" % (
                    name_size,
                    len(name),
                ),
                fatal=True,
            )

        c_name = await reader.readexactly(name_size)

        if c_name != name:

            raise ProtocolError(