U
    g                     @  s   d dl mZ d dlZd dlmZmZmZmZmZ ddl	m
Z
mZ ddlmZmZ ddlmZ ddlmZ zdd	lmZ W n  ek
r   dd	lmZ Y nX G d
d deZdddddZdddddZeZddlmZ dddddZddddddZdS )    )annotationsN)Any	AwaitableCallable
NamedTupleSequence   )
extensionsframes)PayloadTooBigProtocolError)	BytesLike)Data)
apply_maskc                   @  s   e Zd ZU ded< ded< ded< dZded< dZded	< dZded
< eddddZddddZ	ddddZ
edddddddd dddZdddddddd d!ZdS )"Frameboolfinzframes.OpcodeopcodebytesdataFrsv1rsv2rsv3zframes.Frame)returnc                 C  s    t | j| j| j| j| j| jS N)r
   r   r   r   r   r   r   r   self r   =/tmp/pip-unpacked-wheel-dx_q7dq3/websockets/legacy/framing.py	new_frame   s    zFrame.new_framestrc                 C  s
   t | jS r   )r    r   r   r   r   r   __str__%   s    zFrame.__str__Nonec                 C  s
   | j  S r   )r   checkr   r   r   r   r#   (   s    zFrame.checkN)max_sizer	   z!Callable[[int], Awaitable[bytes]]z
int | Nonez%Sequence[extensions.Extension] | None)readermaskr$   r	   r   c             
     s  |dI dH }t d|\}}|d@ r*dnd}|d@ r:dnd}	|d@ rJdnd}
|d	@ rZdnd}zt|d
@ }W n, tk
r } ztd|W 5 d}~X Y nX |d@ rdnd|krtd|d@ }|dkr|dI dH }t d|\}n&|dkr|dI dH }t d|\}|dk	r8||kr8td| d| d|rL|dI dH }||I dH }|rjt||}t||||	|
|}|dkrg }t	|D ]}|j
||d}q|  | |j|j|j|j|j|jS )a@  
        Read a WebSocket frame.

        Args:
            reader: Coroutine that reads exactly the requested number of
                bytes, unless the end of file is reached.
            mask: Whether the frame should be masked i.e. whether the read
                happens on the server side.
            max_size: Maximum payload size in bytes.
            extensions: List of extensions, applied in reverse order.

        Raises:
            PayloadTooBig: If the frame exceeds ``max_size``.
            ProtocolError: If the frame contains incorrect values.

        r   Nz!BB   TF@             zinvalid opcodezincorrect masking   ~   z!H   z!Qzover size limit (z > z bytes)   )r$   )structunpackr
   Opcode
ValueErrorr   r   r   r   reverseddecoder#   r   r   r   r   r   r   )clsr%   r&   r$   r	   r   Zhead1Zhead2r   r   r   r   r   exclengthZ	mask_bitsr   	extensionr   r   r   read+   sP    


z
Frame.read)r	   zCallable[[bytes], Any])writer&   r	   r   c                C  s   || j j||d dS )a  
        Write a WebSocket frame.

        Args:
            frame: Frame to write.
            write: Function that writes bytes.
            mask: Whether the frame should be masked i.e. whether the write
                happens on the client side.
            extensions: List of extensions, applied in order.

        Raises:
            ProtocolError: If the frame contains incorrect values.

        )r&   r	   N)r   	serialize)r   r;   r&   r	   r   r   r   r;   z   s    zFrame.write)__name__
__module____qualname____annotations__r   r   r   propertyr   r!   r#   classmethodr:   r;   r   r   r   r   r      s    

Sr   r   ztuple[int, bytes])r   r   c                 C  s<   t | trtjj|  fS t | tr0tjj| fS tddS )a  
    Convert a string or byte-like object to an opcode and a bytes-like object.

    This function is designed for data frames.

    If ``data`` is a :class:`str`, return ``OP_TEXT`` and a :class:`bytes`
    object encoding ``data`` in UTF-8.

    If ``data`` is a bytes-like object, return ``OP_BINARY`` and a bytes-like
    object.

    Raises:
        TypeError: If ``data`` doesn't have a supported type.

    data must be str or bytes-likeN)	
isinstancer    r
   r2   ZTEXTencoder   ZBINARY	TypeErrorr   r   r   r   prepare_data   s
    

rH   r   c                 C  s0   t | tr|  S t | tr$t| S tddS )ai  
    Convert a string or byte-like object to bytes.

    This function is designed for ping and pong frames.

    If ``data`` is a :class:`str`, return a :class:`bytes` object encoding
    ``data`` in UTF-8.

    If ``data`` is a bytes-like object, return a :class:`bytes` object.

    Raises:
        TypeError: If ``data`` doesn't have a supported type.

    rC   N)rD   r    rE   r   r   rF   rG   r   r   r   prepare_ctrl   s
    

rI   )Closeztuple[int, str]c                 C  s   t | }|j|jfS )z
    Parse the payload from a close frame.

    Returns:
        Close code and reason.

    Raises:
        ProtocolError: If data is ill-formed.
        UnicodeDecodeError: If the reason isn't valid UTF-8.

    )rJ   parsecodereason)r   closer   r   r   parse_close   s    
rO   intr    )rL   rM   r   c                 C  s   t | | S )z3
    Serialize the payload for a close frame.

    )rJ   r<   )rL   rM   r   r   r   serialize_close   s    rQ   )
__future__r   r0   typingr   r   r   r   r    r	   r
   
exceptionsr   r   r   r   Zspeedupsr   ImportErrorutilsr   rH   rI   Zencode_datarJ   rO   rQ   r   r   r   r   <module>   s$    