U
    g}<                     @   sH  d Z ddlZddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZmZmZ ddlmZmZ d	d
dddddddddddddddddddddd d!d"d#d$d%d&gZd'Zd(d) Zd*d Zd+d, Zd-Zd.Zdlee ed/d0dZed1d2dZdmeed3d4d5Zed6d7dZ dnd9dZ!doe"d1d:dZ#e"d1d;dZ$dpe"d<d=dZ%ed>d?G d@d dZ&G dAd	 d	e'Z(G dBd
 d
e(Z)G dCd de)Z*G dDd de)Z+G dEd de(Z,G dFd de)Z-dGd Z.G dHd deZ/G dIdJ dJeZ0G dKdL dLZ1ddMe2edNdOdZ3edPZ4edQZ5edRZ6ee4de6f ee4ge5f ee5de6f dSdTdUZ7ee4 ee4ddf dVdWdXZ8dqee9e:f eee9e:f  dYdZd!Z;dre9d[d\d Z<dse9d[d]dZ=G d^d# d#e>Z?d_d Z@d`d ZAdad ZBeeCgef d1dbdcZDeCeddded%ZEG dfdg dgee4 ZFee4 ee4 dhdid&ZGdjdk ZHdS )tz
Utility functions for PDF library.
Taken from PyPDF2 with modifications and additions, see
:ref:`here <pypdf2-license>` for the original license of the PyPDF2 project.

Generally, all of these constitute internal API, except for the exception
classes.
    N)	dataclass)datetimetimezone)Enum)BytesIO)Callable	GeneratorIterableOptionalTypeVarUnion)CancelableAsyncIteratorConsListPdfErrorPdfReadErrorPdfStrictReadErrorPdfWriteErrorPdfStreamErrorIndirectObjectExpectedget_and_applyOrderedEnumStringWithLanguageis_regular_characterread_non_whitespaceread_until_whitespaceread_until_delimiterread_until_regexskip_over_whitespaceskip_over_commentinstance_testpeek!assert_writable_and_random_accessprepare_rw_output_streamfinalise_outputDEFAULT_CHUNK_SIZEchunked_writechunked_digestchunk_streamr   	Singletonrdisoparselift_iterable_asynci   c                 C   s
   t | dS )N   )roundx r0   :/tmp/pip-unpacked-wheel-owvgwkas/pyhanko/pdf_utils/misc.py<lambda>9       r2   c                    s    fddS )Nc                    s
   t |  S N)
isinstancer.   clsr0   r1   r2   =   r3   zinstance_test.<locals>.<lambda>r0   r6   r0   r6   r1   r   <   s    c                 c   sf   t | }zt|}W n tk
r*   Y d S X zt|}W n tk
rT   tdY nX ||fV  qd S )NzList has odd number of elements)iternextStopIteration
ValueError)lstix1Zx2r0   r0   r1   	pair_iter@   s    r?   s    
	 s
   ()<>[]{}/%)maxcharsreturnc                 C   s   t t| |dS )a  
    Reads non-whitespace characters and returns them.
    Stops upon encountering whitespace, or, if ``maxchars`` is not ``None``,
    when maxchars is reached.

    :param stream:
        stream to read
    :param maxchars:
        maximal number of bytes to read before returning
    )r@   )_read_until_classPDF_WHITESPACE)streamr@   r0   r0   r1   r   R   s    rA   c                 C   s    t tt | }| dtj |S )z
    Read until a token delimiter (i.e. a delimiter character or a PDF
    whitespace character) is encountered, and rewind the stream to the previous
    character.

    :param stream:
        A stream.
    :return:
        The bytes read.
    )rB   rC   PDF_DELIMITERSseekosSEEK_CUR)rD   resultr0   r0   r1   r   a   s    )class_charsrA   c                    s(   dkrdS  fdd}d | S )Nr   r3   c                  3   sP   d krd n
   } d ks,  | k rLd}| ksL|sDqL|V  qd S )N   )tellread)Zstop_attokrL   r@   rD   r0   r1   _buildu   s    
z!_read_until_class.<locals>._build)join)rL   rD   r@   rR   r0   rQ   r1   rB   q   s    rB   Z
byte_valuec                 C   s   | t ko| tkS r4   )rC   rG   rT   r0   r0   r1   r      s    Fc                 C   sr   t d }|t kr0|s$|rdS td| d}q|dkr<q\q| dtj t|  t d }q|rn| dtj |S )zQ
    Finds and reads the next non-whitespace character (ignores whitespace).
    r   r3   Stream ended prematurelyrM      %rF   )rC   r   rO   rH   rI   rJ   r   )rD   Z	seek_backZ	allow_eofrP   r0   r0   r1   r      s    
c                 C   s   t d }d}|t krp| d}|s*td|d7 }|r|dkrF|dkS |dkr| d}|dksd|sp|dkS qpq| dtj |dkS )a  
    Similar to :func:`read_non_whitespace`, but returns a ``bool`` if more than
    one whitespace character was read.

    Will return the cursor to before the first non-whitespace character
    encountered, or after the first end-of-line sequence if one is encountered.
    r   rM   rU      
   rF   )rC   rO   r   rH   rI   rJ   )rD   Zstop_after_eolrP   Zcntnxtr0   r0   r1   r      s"    

c                 C   s^   |  d}| dd |dkrZ|dkr2|  d}q|  d}|rV|dkrV| dtj dS dS )a  
    Skip over a comment and position the cursor at the first byte after
    the EOL sequence following the comment. If there is no comment under
    the cursor, do nothing.

    :param stream:
        stream to read
    :return:
        ``True`` if a comment was read.
    rM   rF   rV   )rW   rX   r3   rW   TF)rO   rH   rI   rJ   )rD   rP   rY   r0   r0   r1   r      s    

)
ignore_eofc                 C   sp   d}|  d}|s"|r|S td||}|dk	rb||d|  7 }| | t| d ql||7 }q|S )ah  
    Reads until the regular expression pattern matched (ignore the match)
    Raise :class:`PdfStreamError` on premature end-of-file.

    :param stream:
        stream to search
    :param regex:
        regex to match
    :param ignore_eof:
        if true, ignore end-of-line and return immediately
    :raises PdfStreamError:
        on premature EOF
    r3      zStream has ended unexpectedlyNrM   )rO   r   searchstartrH   len)rD   regexrZ   namerP   mr0   r0   r1   r      s    


T)frozenc                   @   sB   e Zd ZU dZeed< dZee ed< dZee ed< dd Z	dS )r   z2
    A string with a language attached to it.
    valueN	lang_codecountry_codec                 C   s   | j S r4   )rc   selfr0   r0   r1   __str__   s    zStringWithLanguage.__str__)
__name__
__module____qualname____doc__str__annotations__rd   r
   re   rh   r0   r0   r0   r1   r      s
   
c                       s"   e Zd Zed fddZ  ZS )r   msgc                    s   || _ t j|f|  d S r4   )rp   super__init__)rg   rp   args	__class__r0   r1   rr     s    zPdfError.__init__)ri   rj   rk   rm   rr   __classcell__r0   r0   rt   r1   r     s   c                   @   s   e Zd ZdS )r   Nri   rj   rk   r0   r0   r0   r1   r   	  s   c                   @   s   e Zd ZdS )r   Nrw   r0   r0   r0   r1   r     s   c                       s(   e Zd Zdee d fddZ  ZS )r   Nro   c                    s   t  j|pdd d S )Nzindirect object expectedro   )rq   rr   )rg   rp   rt   r0   r1   rr     s    zIndirectObjectExpected.__init__)N)ri   rj   rk   r
   rm   rr   rv   r0   r0   rt   r1   r     s   c                   @   s   e Zd ZdS )r   Nrw   r0   r0   r0   r1   r     s   c                   @   s   e Zd ZdS )r   Nrw   r0   r0   r0   r1   r     s   c                    s(   t t  fdd} | fS )Nc                   3   s    V  E d H  d S r4   r0   r0   firstitrr0   r1   _itr"  s    zpeek.<locals>._itr)r8   r9   )rz   r{   r0   rx   r1   r      s    c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r   z6
    Ordered enum (from the Python documentation)
    c                 C   s    | j |j kr| j|jkS td S r4   ru   rc   NotImplementedErrorrg   otherr0   r0   r1   __ge__.  s    zOrderedEnum.__ge__c                 C   s    | j |j kr| j|jkS td S r4   r|   r~   r0   r0   r1   __gt__3  s    zOrderedEnum.__gt__c                 C   s    | j |j kr| j|jkS td S r4   r|   r~   r0   r0   r1   __le__8  s    zOrderedEnum.__le__c                 C   s    | j |j kr| j|jk S td S r4   r|   r~   r0   r0   r1   __lt__=  s    zOrderedEnum.__lt__Nri   rj   rk   rl   r   r   r   r   r0   r0   r0   r1   r   )  s
   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )VersionEnumz
    Ordered enum with support for ``None``, for future-proofing version-based
    enums. In such enums, the value ``None`` can be used as a stand-in for
    "any future version".
    c                 C   s@   | j |j kr8| j}|j}|d kr$dS |d kr0dS ||kS td S NTFr|   rg   r   valZ	other_valr0   r0   r1   r   J  s    zVersionEnum.__ge__c                 C   sD   | j |j kr<| j}|j}|d kr(|d k	S |d kr4dS ||kS td S NFr|   r   r0   r0   r1   r   V  s    zVersionEnum.__gt__c                 C   s@   | j |j kr8| j}|j}|d kr$dS |d kr0dS ||kS td S r   r|   r   r0   r0   r1   r   b  s    zVersionEnum.__le__c                 C   sD   | j |j kr<| j}|j}|d kr(|d k	S |d kr4dS ||k S td S r   r|   r   r0   r0   r1   r   n  s    zVersionEnum.__lt__Nr   r0   r0   r0   r1   r   C  s
   r   c                   @   s   e Zd Zdd Zdd ZdS )LazyJoinc                 C   s   || _ || _d S r4   )sepiterator)rg   r   r   r0   r0   r1   rr   |  s    zLazyJoin.__init__c                 C   s   | j | jS r4   )r   rS   r   rf   r0   r0   r1   rh     s    zLazyJoin.__str__N)ri   rj   rk   rr   rh   r0   r0   r0   r1   r   {  s   r   )default)
dictionaryfunctionc                C   s.   z| | }W n t k
r$   | Y S X ||S r4   )KeyError)r   keyr   r   rc   r0   r0   r1   r     s
    
XYR)genfuncrA   c              
   c   sF   z|t | V  W q  tk
r> } z|j W Y S d }~X Y q X q d S r4   )r9   r:   rc   )r   r   er0   r0   r1   map_with_return  s    r   )r/   rA   c                 c   s   | E d H  d S r4   r0   r.   r0   r0   r1   _as_gen  s    r   )temp_bufferrA   c                 c   s   d}|d ks||k r| }|d k	rD|| }|t | k rDt| d | }||}||7 }|s^d S |t |k r|t|d | }n|}|V  qd S )Nr   )r^   
memoryviewreadinto)r   rD   max_readZ
total_readZread_bufferZto_read
bytes_readZto_feedr0   r0   r1   r'     s    
)r   c                 C   s"   t | ||dD ]}|| qd S N)r   )r'   update)r   rD   Zmdr   chunkr0   r0   r1   r&     s    c                 C   s"   t | ||dD ]}|| qd S r   )r'   write)r   rD   outputr   r   r0   r0   r1   r%     s    c                   @   s   e Zd Zdd ZdS )r(   c                    s,   t | |||}t |  fdd|_|S )Nc                    s    S r4   r0   )_instancer0   r1   r2     r3   z#Singleton.__new__.<locals>.<lambda>)type__new____call__)Zmcsr`   basesdctr7   r0   r   r1   r     s    
zSingleton.__new__N)ri   rj   rk   r   r0   r0   r0   r1   r(     s   c                 C   s    |   std|  o|  S )z
    Raise an error if the buffer in question is not writable, and return
    a boolean to indicate whether it supports random-access reading.

    :param output:
    :return:
    zOutput buffer is not writable)writableIOErrorseekablereadabler   r0   r0   r1   r!     s    c                 C   s"   | dkrt  } nt| st  } | S )aB  
    Prepare an output stream that supports both reading and writing.
    Intended to be used for writing & updating signed files:
    when producing a signature, we render the PDF to a byte buffer with
    placeholder values for the signature data, or straight to the provided
    output stream if possible.

    More precisely: this function will return the original output stream
    if it is writable, readable and seekable.
    If the ``output`` parameter is ``None``, not readable or not seekable,
    this function will return a :class:`.BytesIO` instance instead.
    If the ``output`` parameter is not ``None`` and not writable,
    :class:`.IOError` will be raised.

    :param output:
        A writable file-like object, or ``None``.
    :return:
        A file-like object that supports reading, writing and seeking.
    N)r   r!   r   r0   r0   r1   r"     s
    c                 C   s@   | dk	r<| |k	r<t |tst| }| | |  | S |S )z
    Several internal APIs transparently replaces non-readable/seekable
    buffers with BytesIO for signing operations, but we don't want to
    expose that to the public API user.
    This internal API function handles the unwrapping.
    N)r5   r   AssertionError	getbufferr   release)Zorig_outputZreturned_outputZraw_bufr0   r0   r1   r#     s    
c                  C   s2   zddl m}  | W S  tk
r,   tj Y S X d S )Nr   )r*   )Zdateutil.parserr*   ImportErrorr   fromisoformat)parser0   r0   r1   _get_isoparse  s
    r   )dt_strrA   c                 C   s*   t  }|| }|jd kr&|jtjd}|S )N)tzinfo)r   r   replacer   utc)r   r   dtr0   r0   r1   r*     s
    
c                   @   s4   e Zd ZedddZdd Zee dddZd	S )
_LiftedIterablerE   c                    s
   t | jS r4   )r9   r=   rf   r0   r0   r1   	__anext__"  s    z_LiftedIterable.__anext__c                    s   d S r4   r0   rf   r0   r0   r1   cancel%  s    z_LiftedIterable.cancelr=   c                 C   s   t || _d S r4   )r8   r=   )rg   r=   r0   r0   r1   rr   (  s    z_LiftedIterable.__init__N)ri   rj   rk   r   r   r   r	   rr   r0   r0   r0   r1   r   !  s   r   )r=   rA   c                 C   s   t | S r4   )r   r   r0   r0   r1   r+   ,  s    c                  G   s   | D ]}|d k	r|  S qd S r4   r0   )rs   argr0   r0   r1   coalesce0  s    
r   )N)N)FF)F)F)N)N)N)Irl   rI   Zdataclassesr   r   r   enumr   ior   typingr   r   r	   r
   r   r   Zpyhanko_certvalidator.utilr   r   __all__r$   r)   r   r?   rC   rG   intbytesr   r   rB   r   r   boolr   r   r   r   	Exceptionr   r   r   r   r   r   r    r   r   r   dictr   r   r   r   r   r   	bytearrayr   r'   r&   r%   r   r(   r!   r"   r#   rm   r   r*   r   r+   r   r0   r0   r0   r1   <module>   s   	 !
 8	  
	