U
    hq                     @   s   d Z ddlZddlZddlmZmZmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZ eeddd
  ZejejdZG dd dZdS )z6
This module contains the BinaryReader utility class.
    N)datetimetimezone	timedelta)BytesIO)unpack   )TypeNotFoundError)	tlobjects)core_objects   )tzinfoc                   @   s   e Zd ZdZdd Zdd Zd/ddZd0d	d
Zdd Zdd Z	d1ddZ
d2ddZdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.S )3BinaryReaderz2
    Small utility class to read binary data.
    c                 C   s   t || _d | _d S N)r   stream_last)selfdata r   D/tmp/pip-unpacked-wheel-c81u5j2r/telethon/extensions/binaryreader.py__init__   s    
zBinaryReader.__init__c                 C   s   |  dd S )zReads a single byte value.   r   )readr   r   r   r   	read_byte   s    zBinaryReader.read_byteTc                 C   s   t j| dd|dS )z!Reads an integer (4 bytes) value.   little	byteordersignedint
from_bytesr   r   r   r   r   r   read_int#   s    zBinaryReader.read_intc                 C   s   t j| dd|dS )z%Reads a long integer (8 bytes) value.   r   r   r   r"   r   r   r   	read_long'   s    zBinaryReader.read_longc                 C   s   t d| dd S )z,Reads a real floating point (4 bytes) value.z<fr   r   r   r   r   r   r   r   
read_float+   s    zBinaryReader.read_floatc                 C   s   t d| dd S )z,Reads a real floating point (8 bytes) value.z<dr$   r   r&   r   r   r   r   read_double/   s    zBinaryReader.read_doublec                 C   s   t j| |d d|dS )z"Reads a n-bits long integer value.r$   r   r   r   )r   bitsr   r   r   r   read_large_int3   s
      zBinaryReader.read_large_intc                 C   sL   | j |}|dkrBt||krBtd|t|t|t| j|| _|S )z<Read the given amount of bytes, or -1 to read all remaining.r   z=No more data left to read (need {}, got {}: {}); last read {})r   r   lenBufferErrorformatreprr   )r   lengthresultr   r   r   r   8   s       zBinaryReader.readc                 C   s
   | j  S )z?Gets the byte array representing the current buffer as a whole.)r   getvaluer   r   r   r   	get_bytesD   s    zBinaryReader.get_bytesc                 C   sr   |   }|dkr:|   |   d> B |   d> B }|d }n|}|d d }| |}|dkrnd| }| | |S )zi
        Reads a Telegram-encoded byte array, without the need of
        specifying its length.
           r$      r   r   r   )r   r   )r   Z
first_byter0   paddingr   r   r   r   tgread_bytesL   s    



zBinaryReader.tgread_bytesc                 C   s   t |  dddS )z Reads a Telegram-encoded string.zutf-8replace)encodingerrors)strr7   r   r   r   r   tgread_stringa   s    zBinaryReader.tgread_stringc                 C   s:   | j dd}|dkrdS |dkr$dS tdt|dS )zReads a Telegram boolean value.Fr      u2 T   7x zInvalid boolean code {}N)r#   RuntimeErrorr.   hexr   valuer   r   r   tgread_boole   s    zBinaryReader.tgread_boolc                 C   s   |   }tt|d S )zbReads and converts Unix time (used by Telegram)
           into a Python datetime object.
        )seconds)r#   _EPOCHr   rB   r   r   r   tgread_dateo   s    zBinaryReader.tgread_datec                    s    j dd}t|d}|dkr|}|dkr0dS |dkr<dS |dkr^ fdd	t   D S t|d}|dkr d
   }t|  } 	| ||
 S )zReads a Telegram object.Fr=   Nr>   Tr?   ĵc                    s   g | ]}   qS r   tgread_object.0_r   r   r   
<listcomp>   s     z.BinaryReader.tgread_object.<locals>.<listcomp>)r#   r	   getranger
   seektell_positionr   r   set_positionZfrom_reader)r   Zconstructor_idZclazzrC   poserrorr   r   r   rJ   v   s$    

zBinaryReader.tgread_objectc                    s6   d j ddkrtd   } fddt|D S )z,Reads a vector (a list) of Telegram objects.rH   Fr=   z-Invalid constructor code, vector was expectedc                    s   g | ]}   qS r   rI   rK   r   r   r   rN      s     z.BinaryReader.tgread_vector.<locals>.<listcomp>)r#   r@   rQ   )r   countr   r   r   tgread_vector   s    zBinaryReader.tgread_vectorc                 C   s   | j   dS )z.Closes the reader, freeing the BytesIO stream.N)r   closer   r   r   r   rY      s    zBinaryReader.closec                 C   s
   | j  S )z)Tells the current position on the stream.)r   tellr   r   r   r   rS      s    zBinaryReader.tell_positionc                 C   s   | j | dS )z(Sets the current position on the stream.N)r   rR   )r   positionr   r   r   rT      s    zBinaryReader.set_positionc                 C   s   | j |tj dS )zz
        Seeks the stream position given an offset from the current position.
        The offset may be negative.
        N)r   rR   osSEEK_CUR)r   offsetr   r   r   rR      s    zBinaryReader.seekc                 C   s   | S r   r   r   r   r   r   	__enter__   s    zBinaryReader.__enter__c                 C   s   |    d S r   )rY   )r   exc_typeexc_valexc_tbr   r   r   __exit__   s    zBinaryReader.__exit__N)T)T)T)r+   )__name__
__module____qualname____doc__r   r   r#   r%   r'   r(   r*   r   r3   r7   r<   rD   rG   rJ   rX   rY   rS   rT   rR   r_   rc   r   r   r   r   r      s,   





r   )rg   r\   timer   r   r   ior   structr   r:   r   Ztl.alltlobjectsr	   Ztl.corer
   gmtimeZ_EPOCH_NAIVEr8   utcrF   r   r   r   r   r   <module>   s   