3
uQhq                 @   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j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
d3d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 )4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-build-2nz6shyl/telethon/telethon/extensions/binaryreader.py__init__   s    
zBinaryReader.__init__c             C   s   | j 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| 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| jdd|dS )z%Reads a long integer (8 bytes) value.   r   )r   r   )r   r   r   )r   r   r   r   r   	read_long'   s    zBinaryReader.read_longc             C   s   t d| j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| jdd S )z,Reads a real floating point (8 bytes) value.z<dr   r   )r   r   )r   r   r   r   read_double/   s    zBinaryReader.read_doublec             C   s   t j| j|d d|dS )z"Reads a n-bits long integer value.r   r   )r   r   )r   r   r   )r   bitsr   r   r   r   read_large_int3   s    zBinaryReader.read_large_intr   c             C   sL   | j j|}|dkrBt||krBtdj|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 j S )z?Gets the byte array representing the current buffer as a whole.)r   getvalue)r   r   r   r   	get_bytesD   s    zBinaryReader.get_bytesc             C   sr   | j  }|dkr:| j  | j  d> B | j  d> B }|d }n|}|d d }| j|}|dkrnd| }| j| |S )zi
        Reads a Telegram-encoded byte array, without the need of
        specifying its length.
           r      r   r   r   )r   r   )r   Z
first_byter)   paddingr   r   r   r   tgread_bytesL   s    


zBinaryReader.tgread_bytesc             C   s   t | j dddS )z Reads a Telegram-encoded string.zutf-8replace)encodingerrors)strr0   )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jt|dS )zReads a Telegram boolean value.F)r   l   u2 Tl   7x zInvalid boolean code {}N)r   RuntimeErrorr'   hex)r   valuer   r   r   tgread_boole   s    zBinaryReader.tgread_boolc             C   s   | j  }tt|d S )zbReads and converts Unix time (used by Telegram)
           into a Python datetime object.
        )seconds)r   _EPOCHr   )r   r8   r   r   r   tgread_dateo   s    zBinaryReader.tgread_datec                s    j dd}tj|d}|dkr|}|dkr0dS |dkr<dS |dkr^ fdd	t j  D S tj|d}|dkr jd  j }t| j } j	| ||j
 S )zReads a Telegram object.F)r   Nl   u2 Tl   7x iĵc                s   g | ]} j  qS r   )tgread_object).0_)r   r   r   
<listcomp>   s    z.BinaryReader.tgread_object.<locals>.<listcomp>r   )r   r	   getranger
   seektell_positionr   r   set_positionZfrom_reader)r   Zconstructor_idZclazzr8   poserrorr   )r   r   r=   v   s$    

zBinaryReader.tgread_objectc                s6   d j ddkrtd j  } fddt|D S )z,Reads a vector (a list) of Telegram objects.iĵF)r   z-Invalid constructor code, vector was expectedc                s   g | ]} j  qS r   )r=   )r>   r?   )r   r   r   r@      s    z.BinaryReader.tgread_vector.<locals>.<listcomp>)r   r6   rC   )r   countr   )r   r   tgread_vector   s    zBinaryReader.tgread_vectorc             C   s   | j j  dS )z.Closes the reader, freeing the BytesIO stream.N)r   close)r   r   r   r   rK      s    zBinaryReader.closec             C   s
   | j j S )z)Tells the current position on the stream.)r   tell)r   r   r   r   rE      s    zBinaryReader.tell_positionc             C   s   | j j| dS )z(Sets the current position on the stream.N)r   rD   )r   positionr   r   r   rF      s    zBinaryReader.set_positionc             C   s   | j j|tj dS )zz
        Seeks the stream position given an offset from the current position.
        The offset may be negative.
        N)r   rD   osSEEK_CUR)r   offsetr   r   r   rD      s    zBinaryReader.seekc             C   s   | S )Nr   )r   r   r   r   	__enter__   s    zBinaryReader.__enter__c             C   s   | j   d S )N)rK   )r   exc_typeexc_valexc_tbr   r   r   __exit__   s    zBinaryReader.__exit__N)T)T)T)rV   )__name__
__module____qualname____doc__r   r   r   r    r!   r"   r$   r   r,   r0   r5   r9   r<   r=   rJ   rK   rE   rF   rD   rQ   rU   r   r   r   r   r      s,   





r   )rZ   rN   timer   r   r   ior   structr   r3   r   Ztl.alltlobjectsr	   Ztl.corer
   gmtimeZ_EPOCH_NAIVEr1   utcr;   r   r   r   r   r   <module>   s   