U
    (–€h@  ã                   @   sV   d Z ddlmZmZ ddlmZmZmZmZ ddl	m
Z
mZmZ dZG dd„ dƒZd	S )
zy
h2/frame_buffer
~~~~~~~~~~~~~~~

A data structure that provides a way to iterate over a byte buffer in terms of
frames.
é    )ÚInvalidFrameErrorÚInvalidDataError)ÚFrameÚHeadersFrameÚContinuationFrameÚPushPromiseFrameé   )ÚProtocolErrorÚFrameTooLargeErrorÚFrameDataMissingErroré@   c                   @   sB   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dS )ÚFrameBufferz‚
    This is a data structure that expects to act as a buffer for HTTP/2 data
    that allows iteraton in terms of H2 frames.
    Fc                 C   s0   d| _ d| _|rdnd| _t| jƒ| _g | _d S )Nó    r   s   PRI * HTTP/2.0

SM

)ÚdataÚmax_frame_sizeÚ	_preambleÚlenÚ_preamble_lenÚ_headers_buffer)ÚselfÚserver© r   ú3/tmp/pip-unpacked-wheel-axkx3vsa/h2/frame_buffer.pyÚ__init__"   s
    zFrameBuffer.__init__c                 C   sx   | j rft|ƒ}t| j |ƒ}| jd|… |d|… kr<tdƒ‚||d… }|  j |8  _ | j|d… | _|  j|7  _dS )zs
        Add more data to the frame buffer.

        :param data: A bytestring containing the byte buffer.
        NzInvalid HTTP/2 preamble.)r   r   Úminr   r	   r   )r   r   Údata_lenZof_which_preambler   r   r   Úadd_data)   s    zFrameBuffer.add_datac                 C   s    || j krtd|| j f ƒ‚dS )zB
        Confirm that the frame is an appropriate length.
        z*Received overlong frame: length %d, max %dN)r   r
   )r   Úlengthr   r   r   Ú_validate_frame_length<   s    
ÿÿz"FrameBuffer._validate_frame_lengthc                 C   sÎ   | j r¢| j d j}|dk	o,t|tƒo,|j|k}|s:tdƒ‚| j  |¡ t| j ƒtkr\tdƒ‚d|jkrœ| j d }|j 	d¡ d 
dd„ | j D ƒ¡|_g | _ qÊd}n(t|ttfƒrÊd|jkrÊ| j  |¡ d}|S )	z¡
        Updates the internal header buffer. Returns a frame that should replace
        the current one. May throw exceptions if this frame is invalid.
        r   Nz"Invalid frame during header block.z&Too many continuation frames received.ZEND_HEADERSr   c                 s   s   | ]}|j V  qd S ©N)r   )Ú.0Úxr   r   r   Ú	<genexpr>f   s     z4FrameBuffer._update_header_buffer.<locals>.<genexpr>)r   Ú	stream_idÚ
isinstancer   r	   Úappendr   ÚCONTINUATION_BACKLOGÚflagsÚaddÚjoinr   r   r   )r   Úfr#   Zvalid_framer   r   r   Ú_update_header_bufferF   s0    
ÿý

ÿz!FrameBuffer._update_header_bufferc                 C   s   | S r   r   )r   r   r   r   Ú__iter__t   s    zFrameBuffer.__iter__c              
   C   s  t | jƒdk rtƒ ‚zt | jd d… ¡\}}W n6 ttfk
rf } ztdt|ƒ ƒ‚W 5 d }~X Y nX t | jƒ|d k r€tƒ ‚|  	|¡ z | 
t| jdd| … ƒ¡ W n6 tk
rÆ   tdƒ‚Y n tk
rà   tdƒ‚Y nX | jd| d … | _|  |¡}|d k	�r|S |  ¡ S )Né	   z&Received frame with invalid header: %sz&Received frame with non-compliant datazFrame data missing or invalid)r   r   ÚStopIterationr   Zparse_frame_headerr   r   r	   Ústrr   Z
parse_bodyÚ
memoryviewr   r+   Ú__next__)r   r*   r   Úer   r   r   r1   w   s(    
ÿ
 
zFrameBuffer.__next__N)F)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r+   r,   r1   r   r   r   r   r      s   

.r   N)r6   Zhyperframe.exceptionsr   r   Zhyperframe.framer   r   r   r   Ú
exceptionsr	   r
   r   r&   r   r   r   r   r   Ú<module>   s
   