o
    g-                     @  s   d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	 ddl
mZ ddlmZmZmZmZ ddlmZ dd	lmZ d
gZedZG dd
 d
ZdS )    )annotationsN)AnyCallableIterableIterator   )ConcurrencyError)	OP_BINARYOP_CONTOP_TEXTFrame)Data   )Deadline	Assemblerzutf-8c                   @  s   e Zd ZdZdddd dd fd*ddZd+d,ddZd-ddZd.d/ddZd+d0dd Zd1d"d#Z	d2d$d%Z
d2d&d'Zd2d(d)ZdS )3r   a  
    Assemble messages from frames.

    :class:`Assembler` expects only data frames. The stream of frames must
    respect the protocol; if it doesn't, the behavior is undefined.

    Args:
        pause: Called when the buffer of frames goes above the high water mark;
            should pause reading from the network.
        resume: Called when the buffer of frames goes below the low water mark;
            should resume reading from the network.

    Nc                   C     d S N r   r   r   O/var/www/visachat/venv/lib/python3.10/site-packages/websockets/sync/messages.py<lambda>&       zAssembler.<lambda>c                   C  r   r   r   r   r   r   r   r   '   r   high
int | NonelowpauseCallable[[], Any]resumereturnNonec                 C  s   t  | _t | _|d ur|d u r|d }|d u r"|d ur"|d }|d ur:|d ur:|dk r2td||k r:td||| _| _|| _	|| _
d| _d| _d| _d S )N   r   z%low must be positive or equal to zeroz)high must be greater than or equal to lowF)	threadingLockmutexqueueSimpleQueueframes
ValueErrorr   r   r   r   pausedget_in_progressclosed)selfr   r   r   r   r   r   r   __init__"   s"   
	

zAssembler.__init__timeoutfloat | Noner   c                 C  s   | j rz	| jjdd}W n: tjy   tdd w z|d ur+|dkr+| jjdd}n| jjd|d}W n tjyF   td|dd	d w |d u rOtd|S )
NFblockstream of frames endedr   T)r/   r,   ztimed out in z.1fs)r)   r%   getr#   EmptyEOFErrorTimeoutError)r*   r,   framer   r   r   get_next_frameH   s"   
zAssembler.get_next_framer%   Iterable[Frame]c              	   C  s   | j 8 g }z	 || jjdd q tjy   Y nw |D ]}| j| q|D ]}| j| q*W d    d S 1 s>w   Y  d S )NTFr.   )r"   appendr%   r2   r#   r3   put)r*   r%   queuedr6   r   r   r   reset_queue^   s   "zAssembler.reset_queuedecodebool | Noner   c                 C  sn  | j  | jrtdd| _W d   n1 sw   Y  zt|}| |jdd}| j  |   W d   n1 s=w   Y  |jtu sN|jt	u sNJ |du rW|jtu }|g}|j
sz| |jdd}W n tyu   | |  w | j  |   W d   n1 sw   Y  |jtu sJ || |j
r]W d| _nd| _w ddd |D }|r| S |S )	a?  
        Read the next message.

        :meth:`get` returns a single :class:`str` or :class:`bytes`.

        If the message is fragmented, :meth:`get` waits until the last frame is
        received, then it reassembles the message and returns it. To receive
        messages frame by frame, use :meth:`get_iter` instead.

        Args:
            timeout: If a timeout is provided and elapses before a complete
                message is received, :meth:`get` raises :exc:`TimeoutError`.
            decode: :obj:`False` disables UTF-8 decoding of text frames and
                returns :class:`bytes`. :obj:`True` forces UTF-8 decoding of
                binary frames and returns :class:`str`.

        Raises:
            EOFError: If the stream of frames has ended.
            UnicodeDecodeError: If a text frame contains invalid UTF-8.
            ConcurrencyError: If two coroutines run :meth:`get` or
                :meth:`get_iter` concurrently.
            TimeoutError: If a timeout is provided and elapses before a
                complete message is received.

        &get() or get_iter() is already runningTNF)raise_if_elapsed    c                 s  s    | ]}|j V  qd S r   )data).0r6   r   r   r   	<genexpr>   s    z Assembler.get.<locals>.<genexpr>)r"   r(   r   r   r7   r,   maybe_resumeopcoder   r	   finr5   r<   r
   r9   joinr=   )r*   r,   r=   deadliner6   r%   rB   r   r   r   r2   q   sH   





zAssembler.getIterator[Data]c                 c  s<   | j  | jrtdd| _W d   n1 sw   Y  |  }| j  |   W d   n1 s4w   Y  |jtu sE|jtu sEJ |du rN|jtu }|r]t }|	|j
|jV  n|j
V  |js|  }| j  |   W d   n1 szw   Y  |jtu sJ |r|	|j
|jV  n|j
V  |jrdd| _dS )a  
        Stream the next message.

        Iterating the return value of :meth:`get_iter` yields a :class:`str` or
        :class:`bytes` for each frame in the message.

        The iterator must be fully consumed before calling :meth:`get_iter` or
        :meth:`get` again. Else, :exc:`ConcurrencyError` is raised.

        This method only makes sense for fragmented messages. If messages aren't
        fragmented, use :meth:`get` instead.

        Args:
            decode: :obj:`False` disables UTF-8 decoding of text frames and
                returns :class:`bytes`. :obj:`True` forces UTF-8 decoding of
                binary frames and returns :class:`str`.

        Raises:
            EOFError: If the stream of frames has ended.
            UnicodeDecodeError: If a text frame contains invalid UTF-8.
            ConcurrencyError: If two coroutines run :meth:`get` or
                :meth:`get_iter` concurrently.

        r?   TNF)r"   r(   r   r7   rE   rF   r   r	   UTF8Decoderr=   rB   rG   r
   )r*   r=   r6   decoderr   r   r   get_iter   s8   




zAssembler.get_iterr6   c                 C  sN   | j  | jrtd| j| |   W d   dS 1 s w   Y  dS )z
        Add ``frame`` to the next message.

        Raises:
            EOFError: If the stream of frames has ended.

        r0   N)r"   r)   r4   r%   r:   maybe_pause)r*   r6   r   r   r   r:      s   
"zAssembler.putc                 C  sL   | j du rdS | j sJ | j | j kr"| js$d| _|   dS dS dS )z7Pause the writer if queue is above the high water mark.NT)r   r"   lockedr%   qsizer'   r   r*   r   r   r   rN        
zAssembler.maybe_pausec                 C  sL   | j du rdS | j sJ | j | j kr"| jr$d| _|   dS dS dS )z7Resume the writer if queue is below the low water mark.NF)r   r"   rO   r%   rP   r'   r   rQ   r   r   r   rE     rR   zAssembler.maybe_resumec                 C  s   | j 3 | jr	 W d   dS d| _| jr| jd | jr.d| _|   W d   dS W d   dS 1 s9w   Y  dS )z
        End the stream of frames.

        Calling :meth:`close` concurrently with :meth:`get`, :meth:`get_iter`,
        or :meth:`put` is safe. They will raise :exc:`EOFError`.

        NTF)r"   r)   r(   r%   r:   r'   r   rQ   r   r   r   close)  s   

"zAssembler.close)
r   r   r   r   r   r   r   r   r   r   r   )r,   r-   r   r   )r%   r8   r   r   )NN)r,   r-   r=   r>   r   r   )r=   r>   r   rJ   )r6   r   r   r   )r   r   )__name__
__module____qualname____doc__r+   r7   r<   r2   rM   r:   rN   rE   rS   r   r   r   r   r      s    &
G
>

)
__future__r   codecsr#   r    typingr   r   r   r   
exceptionsr   r%   r	   r
   r   r   r   utilsr   __all__getincrementaldecoderrK   r   r   r   r   r   <module>   s    
