# Path: telethon/types/_core/tlmessage.py
# class TLMessage(tlobject.TLObject):
#     """
#     https://core.telegram.org/mtproto/service_messages#simple-container.
# 
#     Messages are what's ultimately sent to Telegram:
#         message msg_id:long seqno:int bytes:int body:bytes = Message;
# 
#     Each message has its own unique identifier, and the body is simply
#     the serialized request that should be executed on the server, or
#     the response object from Telegram. Since the body is always a valid
#     object, it makes sense to store the object and not the bytes to
#     ease working with them.
# 
#     There is no need to add serializing logic here since that can be
#     inlined and is unlikely to change. Thus these are only needed to
#     encapsulate responses.
#     """
#     SIZE_OVERHEAD = 12
# 
#     def __init__(self, msg_id, seq_no, obj):
#         self.msg_id = msg_id
#         self.seq_no = seq_no
#         self.obj = obj
# 
#     def to_dict(self):
#         return {
#             '_': 'TLMessage',
#             'msg_id': self.msg_id,
#             'seq_no': self.seq_no,
#             'obj': self.obj
#         }
# 
# Path: telethon/types/_core/messagecontainer.py
# class MessageContainer(TLObject):
#     CONSTRUCTOR_ID = 0x73f1f8dc
# 
#     # Maximum size in bytes for the inner payload of the container.
#     # Telegram will close the connection if the payload is bigger.
#     # The overhead of the container itself is subtracted.
#     MAXIMUM_SIZE = 1044456 - 8
# 
#     # Maximum amount of messages that can't be sent inside a single
#     # container, inclusive. Beyond this limit Telegram will respond
#     # with BAD_MESSAGE 64 (invalid container).
#     #
#     # This limit is not 100% accurate and may in some cases be higher.
#     # However, sending up to 100 requests at once in a single container
#     # is a reasonable conservative value, since it could also depend on
#     # other factors like size per request, but we cannot know this.
#     MAXIMUM_LENGTH = 100
# 
#     def __init__(self, messages):
#         self.messages = messages
# 
#     def to_dict(self):
#         return {
#             '_': 'MessageContainer',
#             'messages':
#                 [] if self.messages is None else [
#                     None if x is None else x.to_dict() for x in self.messages
#                 ],
#         }
# 
#     @classmethod
#     def _from_reader(cls, reader):
#         # This assumes that .read_* calls are done in the order they appear
#         messages = []
#         for _ in range(reader.read_int()):
#             msg_id = reader.read_long()
#             seq_no = reader.read_int()
#             length = reader.read_int()
#             before = reader.tell_position()
#             obj = reader.tgread_object()  # May over-read e.g. RpcResult
#             reader.set_position(before + length)
#             messages.append(TLMessage(msg_id, seq_no, obj))
#         return MessageContainer(messages)


import asyncio
import collections
import io
import struct
from .._tl import TLRequest
from ..types._core import MessageContainer, TLMessage
        self._state = state
        self._deque = collections.deque()
        self._ready = asyncio.Event()
        self._log = loggers[__name__]

    def append(self, state):
        self._deque.append(state)
        self._ready.set()

    def extend(self, states):
        self._deque.extend(states)
        self._ready.set()

    async def get(self):
        """
        Returns (batch, data) if one or more items could be retrieved.

        If the cancellation occurs or only invalid items were in the
        queue, (None, None) will be returned instead.
        """
        if not self._deque:
            self._ready.clear()
            await self._ready.wait()

        buffer = io.BytesIO()
        batch = []
        size = 0

        # Fill a new batch to return while the size is small enough,
        # as long as we don't exceed the maximum length of messages.

# Path: telethon/types/_core/tlmessage.py
# class TLMessage(tlobject.TLObject):
#     """
#     https://core.telegram.org/mtproto/service_messages#simple-container.
# 
#     Messages are what's ultimately sent to Telegram:
#         message msg_id:long seqno:int bytes:int body:bytes = Message;
# 
#     Each message has its own unique identifier, and the body is simply
#     the serialized request that should be executed on the server, or
#     the response object from Telegram. Since the body is always a valid
#     object, it makes sense to store the object and not the bytes to
#     ease working with them.
# 
#     There is no need to add serializing logic here since that can be
#     inlined and is unlikely to change. Thus these are only needed to
#     encapsulate responses.
#     """
#     SIZE_OVERHEAD = 12
# 
#     def __init__(self, msg_id, seq_no, obj):
#         self.msg_id = msg_id
#         self.seq_no = seq_no
#         self.obj = obj
# 
#     def to_dict(self):
#         return {
#             '_': 'TLMessage',
#             'msg_id': self.msg_id,
#             'seq_no': self.seq_no,
#             'obj': self.obj
#         }
# 
# Path: telethon/types/_core/messagecontainer.py
# class MessageContainer(TLObject):
#     CONSTRUCTOR_ID = 0x73f1f8dc
# 
#     # Maximum size in bytes for the inner payload of the container.
#     # Telegram will close the connection if the payload is bigger.
#     # The overhead of the container itself is subtracted.
#     MAXIMUM_SIZE = 1044456 - 8
# 
#     # Maximum amount of messages that can't be sent inside a single
#     # container, inclusive. Beyond this limit Telegram will respond
#     # with BAD_MESSAGE 64 (invalid container).
#     #
#     # This limit is not 100% accurate and may in some cases be higher.
#     # However, sending up to 100 requests at once in a single container
#     # is a reasonable conservative value, since it could also depend on
#     # other factors like size per request, but we cannot know this.
#     MAXIMUM_LENGTH = 100
# 
#     def __init__(self, messages):
#         self.messages = messages
# 
#     def to_dict(self):
#         return {
#             '_': 'MessageContainer',
#             'messages':
#                 [] if self.messages is None else [
#                     None if x is None else x.to_dict() for x in self.messages
#                 ],
#         }
# 
#     @classmethod
#     def _from_reader(cls, reader):
#         # This assumes that .read_* calls are done in the order they appear
#         messages = []
#         for _ in range(reader.read_int()):
#             msg_id = reader.read_long()
#             seq_no = reader.read_int()
#             length = reader.read_int()
#             before = reader.tell_position()
#             obj = reader.tgread_object()  # May over-read e.g. RpcResult
#             reader.set_position(before + length)
#             messages.append(TLMessage(msg_id, seq_no, obj))
#         return MessageContainer(messages)


# Path: telethon/_misc/messagepacker.py
import asyncio
import collections
import io
import struct
from .._tl import TLRequest
from ..types._core import MessageContainer, TLMessage

        self._state = state
        self._deque = collections.deque()
        self._ready = asyncio.Event()
        self._log = loggers[__name__]

    def append(self, state):
        self._deque.append(state)
        self._ready.set()

    def extend(self, states):
        self._deque.extend(states)
        self._ready.set()

    async def get(self):
        """
        Returns (batch, data) if one or more items could be retrieved.

        If the cancellation occurs or only invalid items were in the
        queue, (None, None) will be returned instead.
        """
        if not self._deque:
            self._ready.clear()
            await self._ready.wait()

        buffer = io.BytesIO()
        batch = []
        size = 0

        # Fill a new batch to return while the size is small enough,
        # as long as we don't exceed the maximum length of messages.

        while self._deque and len(batch) <= MessageContainer.MAXIMUM_LENGTH: