o
    ²µj  ć                   @   s   d Z ddlZG dd dZdS )zt
Async version of gunicorn/http/unreader.py for ASGI workers.

Provides async reading with pushback buffer support.
é    Nc                   @   sT   e Zd ZdZdddZdd Zdd Zd	d
 ZdddZdd Z	dd Z
dd ZdS )ŚAsyncUnreadera8  Async socket reader with pushback buffer support.

    This class wraps an asyncio StreamReader and provides the ability
    to "unread" data back into a buffer for re-parsing.

    Performance optimization: Reuses BytesIO buffer with truncate/seek
    instead of creating new objects to reduce GC pressure.
    é    c                 C   s    || _ t ” | _|| _d| _dS )zInitialize the async unreader.

        Args:
            reader: asyncio.StreamReader instance
            max_chunk: Maximum bytes to read at once
        r   N)ŚreaderŚioŚBytesIOŚbufŚ	max_chunkŚ
_buf_start)Śselfr   r   © r   śK/var/www/ai-app/venv/lib/python3.10/site-packages/gunicorn/asgi/unreader.pyŚ__init__   s   

zAsyncUnreader.__init__c                 C   s"   | j  d” | j  d” d| _dS )z7Reset buffer for reuse instead of creating new BytesIO.r   N)r   ŚseekŚtruncater	   ©r
   r   r   r   Ś_reset_buffer$   s   
zAsyncUnreader._reset_bufferc                 C   s$   | j  | j” | j  ” }|  ”  |S )z'Get all buffered data and reset buffer.)r   r   r	   Śreadr   )r
   Śdatar   r   r   Ś_get_buffered_data*   s   
z AsyncUnreader._get_buffered_datac                 C   s   | j  dtj”}|| j S )zGet size of buffered data.r   )r   r   r   ŚSEEK_ENDr	   )r
   Śendr   r   r   Ś_buffer_size1   s   
zAsyncUnreader._buffer_sizeNc                 Ć   s   |durt |tstd|dur|dkrdS |dk rd}|  ” }|du r.|dkr.|  ” S |du r;|  ” I dH }|S ||k rd|  ” I dH }|sL|  ” S | j dtj	” | j 
|” |t|7 }||k s?| j | j” | j |”}|  j|7  _| jdkr| j ” }|  ”  |r| j 
|” |S )a  Read data from the stream, using buffered data first.

        Args:
            size: Number of bytes to read. If None, returns all buffered
                  data or reads a single chunk.

        Returns:
            bytes: Data read from buffer or stream
        Nz&size parameter must be an int or long.r   ó    r   )Ś
isinstanceŚintŚ	TypeErrorr   r   Ś_read_chunkr   r   r   r   ŚwriteŚlenr	   r   r   )r
   ŚsizeŚbuf_sizeŚchunkr   Ś	remainingr   r   r   r   6   s>   
ś	

zAsyncUnreader.readc                 Ć   s.   z| j  | j”I dH W S  ty   Y dS w )z0Read a chunk of data from the underlying stream.Nr   )r   r   r   Ś	Exceptionr   r   r   r   r   k   s   ’zAsyncUnreader._read_chunkc                 C   sL   |r"| j  | j” | j  ” }|  ”  | j  |” |r$| j  |” dS dS dS )zµPush data back into the buffer for re-reading.

        Args:
            data: bytes to push back

        Note: This prepends data to the buffer so it will be read first.
        N)r   r   r	   r   r   r   )r
   r   Śexistingr   r   r   Śunreadr   s   
÷zAsyncUnreader.unreadc                 C   s   |   ” dkS )z-Check if there's data in the pushback buffer.r   )r   r   r   r   r   Śhas_buffered_data   s   zAsyncUnreader.has_buffered_data)r   )N)Ś__name__Ś
__module__Ś__qualname__Ś__doc__r   r   r   r   r   r   r%   r&   r   r   r   r   r      s    
	
5r   )r*   r   r   r   r   r   r   Ś<module>   s   