U
    gQ&                     @  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 ddlm	Z	 ddl
mZmZmZmZ ddlmZ dgZed	ZG d
d dZdS )    )annotationsN)Iteratorcast   )ConcurrencyError)	OP_BINARYOP_CONTOP_TEXTFrame)Data	Assemblerzutf-8c                   @  s\   e Zd ZdZddddZdddd	d
dZddddZdddddZddddZdS )r   z)
    Assemble messages from frames.

    None)returnc                 C  sF   t  | _t  | _t  | _d| _d| _d | _g | _	d | _
d| _d S )NF)	threadingLockmutexEventmessage_completemessage_fetchedget_in_progressput_in_progressdecoderchunkschunks_queueclosedself r   </tmp/pip-unpacked-wheel-dx_q7dq3/websockets/sync/messages.py__init__   s    


	zAssembler.__init__Nzfloat | Noner   )timeoutr   c              
   C  s   | j ( | jrtd| jr$tdd| _W 5 Q R X | j|}| j  d| _|sdtd|dd| jrrtd| j st	| j
  | jdkrd	nd
}|| j}g | _| jdkst	| j rt	| j  |W  5 Q R  S Q R X d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`.

        Raises:
            EOFError: If the stream of frames has ended.
            ConcurrencyError: If two threads run :meth:`get` or :meth:`get_iter`
                concurrently.
            TimeoutError: If a timeout is provided and elapses before a
                complete message is received.

        stream of frames ended&get() or get_iter() is already runningTFztimed out in z.1fsN     )r   r   EOFErrorr   r   r   waitTimeoutErroris_setAssertionErrorclearr   joinr   r   r   set)r   r    Z	completedjoinermessager   r   r   get>   s,    

zAssembler.getzIterator[Data]c              	   c  s   | j Z | jrtd| jr$td| j}g | _tdt | _	| j
 rV| j	d d| _W 5 Q R X |D ]
}|V  qj| j	  }dk	r|V  qv| j ^ d| _| jrtd| j
 st| j
  | jg kstd| _	| j rt| j  W 5 Q R X 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.

        Raises:
            EOFError: If the stream of frames has ended.
            ConcurrencyError: If two threads run :meth:`get` or :meth:`get_iter`
                concurrently.

        r!   r"   zqueue.SimpleQueue[Data | None]NTF)r   r   r&   r   r   r   r   queueSimpleQueuer   r   r)   putr0   r*   r+   r   r-   )r   r   chunkr   r   r   get_iter|   s8    	

zAssembler.get_iterr
   )framer   c              	   C  sZ  | j  | jrtd| jr$td|jtkr<tdd| _n |jt	krNd| _n|jt
ks\t| jdk	rz| j|j|j}n|j}| jdkr| j| n| j| |jsW 5 Q R  dS | j rt| j  | jdk	r| jd | j rtd| _W 5 Q R X | j  | j < d| _| jr,td| j s<t| j  d| _W 5 Q R X dS )a,  
        Add ``frame`` to the next message.

        When ``frame`` is the final frame in a message, :meth:`put` waits until
        the message is fetched, which can be achieved by calling :meth:`get` or
        by fully consuming the return value of :meth:`get_iter`.

        :meth:`put` assumes that the stream of frames respects the protocol. If
        it doesn't, the behavior is undefined.

        Raises:
            EOFError: If the stream of frames has ended.
            ConcurrencyError: If two threads run :meth:`put` concurrently.

        r!   zput is already runningstrict)errorsNTF)r   r   r&   r   r   opcoder	   UTF8Decoderr   r   r   r*   decodedataZfinr   r   appendr3   r   r)   r-   r   r'   r+   )r   r6   r<   r   r   r   r3      s@    







zAssembler.putc              	   C  sf   | j V | jrW 5 Q R  dS d| _| jrH| j  | jdk	rH| jd | jrX| j  W 5 Q R X dS )z
        End the stream of frames.

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

        NT)	r   r   r   r   r-   r   r3   r   r   r   r   r   r   close  s    

zAssembler.close)N)	__name__
__module____qualname____doc__r   r0   r5   r3   r>   r   r   r   r   r      s   &>AH)
__future__r   codecsr1   r   typingr   r   
exceptionsr   framesr   r   r	   r
   r   __all__getincrementaldecoderr:   r   r   r   r   r   <module>   s   
