# Path: aredis/exceptions.py
# class ConnectionError(RedisError):
#     pass
# 
# class TimeoutError(RedisError):
#     pass
# 
# class RedisError(Exception):
#     pass
# 
# class ExecAbortError(ResponseError):
#     pass
# 
# class BusyLoadingError(ConnectionError):
#     pass
# 
# class NoScriptError(ResponseError):
#     pass
# 
# class ReadOnlyError(ResponseError):
#     pass
# 
# class ResponseError(RedisError):
#     pass
# 
# class InvalidResponse(RedisError):
#     pass
# 
# class AskError(ResponseError):
#     """
#     src node: MIGRATING to dst node
#         get > ASK error
#         ask dst node > ASKING command
#     dst node: IMPORTING from src node
#         asking command only affects next command
#         any op will be allowed after asking command
#     """
# 
#     def __init__(self, resp):
#         """should only redirect to master node"""
#         self.args = (resp,)
#         self.message = resp
#         slot_id, new_node = resp.split(' ')
#         host, port = new_node.rsplit(':', 1)
#         self.slot_id = int(slot_id)
#         self.node_addr = self.host, self.port = host, int(port)
# 
# class MovedError(AskError):
#     pass
# 
# class TryAgainError(ResponseError):
# 
#     def __init__(self, *args, **kwargs):
#         pass
# 
# class ClusterDownError(ClusterError, ResponseError):
# 
#     def __init__(self, resp):
#         self.args = (resp,)
#         self.message = resp
# 
# class ClusterCrossSlotError(ResponseError):
#     message = "Keys in request don't hash to the same slot"
# 
# Path: aredis/utils.py
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# def nativestr(x):
#     return x if isinstance(x, str) else x.decode('utf-8', 'replace')
# 
# LOOP_DEPRECATED = sys.version_info >= (3, 8)


import asyncio
import inspect
import os
import socket
import ssl
import sys
import time
import warnings
import aredis.compat
    import hiredis
from io import BytesIO
from aredis.exceptions import (ConnectionError, TimeoutError,
                               RedisError, ExecAbortError,
                               BusyLoadingError, NoScriptError,
                               ReadOnlyError, ResponseError,
                               InvalidResponse, AskError,
                               MovedError, TryAgainError,
                               ClusterDownError, ClusterCrossSlotError)
from aredis.utils import b, nativestr, LOOP_DEPRECATED
            return await asyncio.wait_for(coroutine, timeout, loop=loop)
    except asyncio.TimeoutError as exc:
        raise TimeoutError(exc)


class SocketBuffer:
    def __init__(self, stream_reader, read_size):
        self._stream = stream_reader
        self.read_size = read_size
        self._buffer = BytesIO()
        # number of bytes written to the buffer from the socket
        self.bytes_written = 0
        # number of bytes read from the buffer
        self.bytes_read = 0

    @property
    def length(self):
        return self.bytes_written - self.bytes_read

    async def _read_from_socket(self, length=None):
        buf = self._buffer
        buf.seek(self.bytes_written)
        marker = 0

        try:
            while True:
                data = await self._stream.read(self.read_size)
                # an empty string indicates the server shutdown the socket
                if isinstance(data, bytes) and len(data) == 0:
                    raise ConnectionError('Socket closed on remote end')

# Path: aredis/exceptions.py
# class ConnectionError(RedisError):
#     pass
# 
# class TimeoutError(RedisError):
#     pass
# 
# class RedisError(Exception):
#     pass
# 
# class ExecAbortError(ResponseError):
#     pass
# 
# class BusyLoadingError(ConnectionError):
#     pass
# 
# class NoScriptError(ResponseError):
#     pass
# 
# class ReadOnlyError(ResponseError):
#     pass
# 
# class ResponseError(RedisError):
#     pass
# 
# class InvalidResponse(RedisError):
#     pass
# 
# class AskError(ResponseError):
#     """
#     src node: MIGRATING to dst node
#         get > ASK error
#         ask dst node > ASKING command
#     dst node: IMPORTING from src node
#         asking command only affects next command
#         any op will be allowed after asking command
#     """
# 
#     def __init__(self, resp):
#         """should only redirect to master node"""
#         self.args = (resp,)
#         self.message = resp
#         slot_id, new_node = resp.split(' ')
#         host, port = new_node.rsplit(':', 1)
#         self.slot_id = int(slot_id)
#         self.node_addr = self.host, self.port = host, int(port)
# 
# class MovedError(AskError):
#     pass
# 
# class TryAgainError(ResponseError):
# 
#     def __init__(self, *args, **kwargs):
#         pass
# 
# class ClusterDownError(ClusterError, ResponseError):
# 
#     def __init__(self, resp):
#         self.args = (resp,)
#         self.message = resp
# 
# class ClusterCrossSlotError(ResponseError):
#     message = "Keys in request don't hash to the same slot"
# 
# Path: aredis/utils.py
# def b(x):
#     return x.encode('latin-1') if not isinstance(x, bytes) else x
# 
# def nativestr(x):
#     return x if isinstance(x, str) else x.decode('utf-8', 'replace')
# 
# LOOP_DEPRECATED = sys.version_info >= (3, 8)


# Path: aredis/connection.py
import asyncio
import inspect
import os
import socket
import ssl
import sys
import time
import warnings
import aredis.compat
    import hiredis
from io import BytesIO
from aredis.exceptions import (ConnectionError, TimeoutError,
                               RedisError, ExecAbortError,
                               BusyLoadingError, NoScriptError,
                               ReadOnlyError, ResponseError,
                               InvalidResponse, AskError,
                               MovedError, TryAgainError,
                               ClusterDownError, ClusterCrossSlotError)
from aredis.utils import b, nativestr, LOOP_DEPRECATED

            return await asyncio.wait_for(coroutine, timeout, loop=loop)
    except asyncio.TimeoutError as exc:
        raise TimeoutError(exc)


class SocketBuffer:
    def __init__(self, stream_reader, read_size):
        self._stream = stream_reader
        self.read_size = read_size
        self._buffer = BytesIO()
        # number of bytes written to the buffer from the socket
        self.bytes_written = 0
        # number of bytes read from the buffer
        self.bytes_read = 0

    @property
    def length(self):
        return self.bytes_written - self.bytes_read

    async def _read_from_socket(self, length=None):
        buf = self._buffer
        buf.seek(self.bytes_written)
        marker = 0

        try:
            while True:
                data = await self._stream.read(self.read_size)
                # an empty string indicates the server shutdown the socket
                if isinstance(data, bytes) and len(data) == 0:
                    raise ConnectionError('Socket closed on remote end')

                buf.write(data)