o
    UhS                    @   s  d Z ddlmZmZ g dZddlZddlZddlmZm	Z	 e
 Ze	 Ze	 Ze	 Ze	 ZejddZe	 Ze	jZd	Ze	jZe	jZe	je	j e	j!fZ"e	j#Z$e	j%Z&e	j'Z(e	j)Z*e	j+Z,e	j-Z.e	j/Z0e	j1Z2e	j3Z4e	j5Z6e	j7Z8e	j9Z:e	j3Z;e	j5Z<e	j=Z>e	j?Z@e	jAZBe	jCZDe	jEZFe	jGZHe	jIZJe	jKZLe	jMZNe	jOZPe	jQZRe	jSZTe	jUZVe	jWZXe	jYZZe	j[Z\e	j]Z^e	j_Z`e	jaZbdZcdZddZedZfd
d ZgG dd dZhG dd dZiG dd dZjG dd dZkG dd delZmdd Zndd ZoG dd depZqdd Zrdd Zsd d! ZtG d"d# d#epZuG d$d% d%epZvG d&d' d'epZwG d(d) d)epZxG d*d+ d+epZyG d,d- d-epZzd.d/ Z{d0d1 Z|d2d3 Z}G d4d5 d5epZ~				6						dAd7d8ZG d9d: d:epZG d;d< d<epZG d=d> d>epZG d?d@ d@epZdS )Bz=Python interface to the Zstandard (zstd) compression library.    )absolute_importunicode_literals)FBufferSegmentBufferSegmentsBufferWithSegmentsBufferWithSegmentsCollectionZstdCompressionChunkerZstdCompressionDictZstdCompressionObjZstdCompressionParametersZstdCompressionReaderZstdCompressionWriterZstdCompressorZstdDecompressionObjZstdDecompressionReaderZstdDecompressionWriterZstdDecompressor	ZstdErrorFrameParametersbackend_features#estimate_decompression_context_sizeframe_content_sizeframe_header_sizeget_frame_parameterstrain_dictionaryFLUSH_BLOCKFLUSH_FRAMECOMPRESSOBJ_FLUSH_FINISHCOMPRESSOBJ_FLUSH_BLOCKZSTD_VERSIONFRAME_HEADERCONTENTSIZE_UNKNOWNCONTENTSIZE_ERRORMAX_COMPRESSION_LEVEL"COMPRESSION_RECOMMENDED_INPUT_SIZE#COMPRESSION_RECOMMENDED_OUTPUT_SIZE$DECOMPRESSION_RECOMMENDED_INPUT_SIZE%DECOMPRESSION_RECOMMENDED_OUTPUT_SIZEMAGIC_NUMBERBLOCKSIZELOG_MAXBLOCKSIZE_MAXWINDOWLOG_MINWINDOWLOG_MAXCHAINLOG_MINCHAINLOG_MAXHASHLOG_MINHASHLOG_MAXMINMATCH_MINMINMATCH_MAXSEARCHLOG_MINSEARCHLOG_MAXSEARCHLENGTH_MINSEARCHLENGTH_MAXTARGETLENGTH_MINTARGETLENGTH_MAXLDM_MINMATCH_MINLDM_MINMATCH_MAXLDM_BUCKETSIZELOG_MAXSTRATEGY_FASTSTRATEGY_DFASTSTRATEGY_GREEDYSTRATEGY_LAZYSTRATEGY_LAZY2STRATEGY_BTLAZY2STRATEGY_BTOPTSTRATEGY_BTULTRASTRATEGY_BTULTRA2DICT_TYPE_AUTODICT_TYPE_RAWCONTENTDICT_TYPE_FULLDICTFORMAT_ZSTD1FORMAT_ZSTD1_MAGICLESSN   )ffilibF)should_clear_after_allocs   (/c                	   C   sH   zt  pdW S  ty   Y nw zt dW S  ttfy#   Y dS w )Nr   SC_NPROCESSORS_ONLN)os	cpu_countAttributeErrorsysconf
ValueError rT   rT   j/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/zstandard/backend_cffi.py
_cpu_count   s   rV   c                   @   s,   e Zd ZdZedd Zdd Zdd ZdS )	r   zRepresents a segment within a ``BufferWithSegments``.

    This type is essentially a reference to N bytes within a
    ``BufferWithSegments``.

    The object conforms to the buffer protocol.
    c                 C      t  )z9The byte offset of this segment within its parent buffer.NotImplementedErrorselfrT   rT   rU   offset      zBufferSegment.offsetc                 C   rW   )z+Obtain the length of the segment, in bytes.rX   rZ   rT   rT   rU   __len__      zBufferSegment.__len__c                 C   rW   )z"Obtain bytes copy of this segment.rX   rZ   rT   rT   rU   tobytes   r_   zBufferSegment.tobytesN)__name__
__module____qualname____doc__propertyr\   r^   r`   rT   rT   rT   rU   r      s    
r   c                   @   s   e Zd ZdZdS )r   a	  Represents an array of ``(offset, length)`` integers.

    This type is effectively an index used by :py:class:`BufferWithSegments`.

    The array members are 64-bit unsigned integers using host/native bit order.

    Instances conform to the buffer protocol.
    N)ra   rb   rc   rd   rT   rT   rT   rU   r      s    r   c                   @   s<   e Zd ZdZedd Zdd Zdd Zdd	 Zd
d Z	dS )r   ac  A memory buffer containing N discrete items of known lengths.

    This type is essentially a fixed size memory address and an array
    of 2-tuples of ``(offset, length)`` 64-bit unsigned native-endian
    integers defining the byte offset and length of each segment within
    the buffer.

    Instances behave like containers.

    Instances also conform to the buffer protocol. So a reference to the
    backing bytes can be obtained via ``memoryview(o)``. A *copy* of the
    backing bytes can be obtained via ``.tobytes()``.

    This type exists to facilitate operations against N>1 items without
    the overhead of Python object creation and management. Used with
    APIs like :py:meth:`ZstdDecompressor.multi_decompress_to_buffer`, it
    is possible to decompress many objects in parallel without the GIL
    held, leading to even better performance.
    c                 C   rW   )z)Total sizein bytes of the backing buffer.rX   rZ   rT   rT   rU   size   r]   zBufferWithSegments.sizec                 C   rW   NrX   rZ   rT   rT   rU   r^         zBufferWithSegments.__len__c                 C   rW   )zObtains a segment within the buffer.

        The returned object references memory within this buffer.

        :param i:
           Integer index of segment to retrieve.
        :return:
           :py:class:`BufferSegment`
        rX   r[   irT   rT   rU   __getitem__   s   
zBufferWithSegments.__getitem__c                 C   rW   )zObtain the array of ``(offset, length)`` segments in the buffer.

        :return:
           :py:class:`BufferSegments`
        rX   rZ   rT   rT   rU   segments   s   zBufferWithSegments.segmentsc                 C   rW   )z#Obtain bytes copy of this instance.rX   rZ   rT   rT   rU   r`     r_   zBufferWithSegments.tobytesN)
ra   rb   rc   rd   re   rf   r^   rk   rl   r`   rT   rT   rT   rU   r      s    
r   c                   @   s    e Zd ZdZdd Zdd ZdS )r   a.  A virtual spanning view over multiple BufferWithSegments.

    Instances are constructed from 1 or more :py:class:`BufferWithSegments`
    instances. The resulting object behaves like an ordered sequence whose
    members are the segments within each ``BufferWithSegments``.

    If the object is composed of 2 ``BufferWithSegments`` instances with the
    first having 2 segments and the second have 3 segments, then ``b[0]``
    and ``b[1]`` access segments in the first object and ``b[2]``, ``b[3]``,
    and ``b[4]`` access segments from the second.
    c                 C   rW   )z9The number of segments within all ``BufferWithSegments``.rX   rZ   rT   rT   rU   r^     r_   z$BufferWithSegmentsCollection.__len__c                 C   rW   )z*Obtain the ``BufferSegment`` at an offset.rX   ri   rT   rT   rU   rk     r_   z(BufferWithSegmentsCollection.__getitem__N)ra   rb   rc   rd   r^   rk   rT   rT   rT   rU   r   	  s    r   c                   @   s   e Zd ZdS )r   N)ra   rb   rc   rT   rT   rT   rU   r     s    r   c                 C   s   t t| dS )Nutf-8)rK   stringrL   ZSTD_getErrorNamedecode)zresultrT   rT   rU   _zstd_error#  s   rr   c                 C   s  t  }|tjkrt t|t j}t j| jft j	| j
ft j| jft j| jft j| jft j| jft j| jft j| jft j| jft j| jft j| jft j| jft j| j ft j!| j"ft j#| j$ft j%| j&ft j'| j(ft j)| j*ft j+| j,ft j-| j.ft j/| j0fg}|D ]
\}}t1||| q|S rg   )2rL   ZSTD_createCCtxParamsrK   NULLMemoryErrorgcZSTD_freeCCtxParamsZSTD_c_formatformatZSTD_c_compressionLevelcompression_levelZSTD_c_windowLog
window_logZSTD_c_hashLoghash_logZSTD_c_chainLog	chain_logZSTD_c_searchLog
search_logZSTD_c_minMatch	min_matchZSTD_c_targetLengthtarget_lengthZSTD_c_strategystrategyZSTD_c_contentSizeFlagwrite_content_sizeZSTD_c_checksumFlagwrite_checksumZSTD_c_dictIDFlagwrite_dict_idZSTD_c_nbWorkersthreadsZSTD_c_jobSizejob_sizeZSTD_c_overlapLogoverlap_logZSTD_c_forceMaxWindowforce_max_window!ZSTD_c_enableLongDistanceMatching
enable_ldmZSTD_c_ldmHashLogldm_hash_logZSTD_c_ldmMinMatchldm_min_matchZSTD_c_ldmBucketSizeLogldm_bucket_size_logZSTD_c_ldmHashRateLogldm_hash_rate_log_set_compression_parameter)paramsresattrsparamvaluerT   rT   rU   _make_cctx_params*  s:   





















r   c                   @   sV  e Zd ZdZed6ddZ																					d7ddZed	d
 Zedd Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zedd  Zed!d" Zed#d$ Zed%d& Zed'd( Zed)d* Zed+d, Zed-d. Zed/d0 Zed1d2 Zd3d4 Zd5S )8r   a  Low-level zstd compression parameters.

    This type represents a collection of parameters to control how zstd
    compression is performed.

    Instances can be constructed from raw parameters or derived from a
    base set of defaults specified from a compression level (recommended)
    via :py:meth:`ZstdCompressionParameters.from_level`.

    >>> # Derive compression settings for compression level 7.
    >>> params = zstandard.ZstdCompressionParameters.from_level(7)

    >>> # With an input size of 1MB
    >>> params = zstandard.ZstdCompressionParameters.from_level(7, source_size=1048576)

    Using ``from_level()``, it is also possible to override individual compression
    parameters or to define additional settings that aren't automatically derived.
    e.g.:

    >>> params = zstandard.ZstdCompressionParameters.from_level(4, window_log=10)
    >>> params = zstandard.ZstdCompressionParameters.from_level(5, threads=4)

    Or you can define low-level compression settings directly:

    >>> params = zstandard.ZstdCompressionParameters(window_log=12, enable_ldm=True)

    Once a ``ZstdCompressionParameters`` instance is obtained, it can be used to
    configure a compressor:

    >>> cctx = zstandard.ZstdCompressor(compression_params=params)

    Some of these are very low-level settings. It may help to consult the official
    zstandard documentation for their behavior. Look for the ``ZSTD_p_*`` constants
    in ``zstd.h`` (https://github.com/facebook/zstd/blob/dev/lib/zstd.h).
    r   c                 K   sX   t | ||}dddddddd}| D ]\}}||vr$t||||< qtd
i |S )au  Create compression parameters from a compression level.

        :param level:
           Integer compression level.
        :param source_size:
           Integer size in bytes of source to be compressed.
        :param dict_size:
           Integer size in bytes of compression dictionary to use.
        :return:
           :py:class:`ZstdCompressionParameters`
        	windowLogchainLoghashLog	searchLogminMatchtargetLengthr   )r}   r   r   r   r   r   r   NrT   )rL   ZSTD_getCParamsitemsgetattrr   )levelsource_size	dict_sizekwargsr   argsargattrrT   rT   rU   
from_levelt  s   
z$ZstdCompressionParameters.from_levelrJ   c                 C   s  t  }|tjkrt t|t j}|| _|dk rt }t	|t j
| t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| |	dkrbd}	t	|t j|	 t	|t j|
 t	|t j| t	|t j| t	|t j| |dkrd}t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| t	|t j| |dkrd}t	|t j| d S )Nr   r   )rL   rs   rK   rt   ru   rv   rw   _paramsrV   r   r   rx   rz   r|   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r[   ry   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rT   rT   rU   __init__  sh   
z"ZstdCompressionParameters.__init__c                 C      t | jtjS rg   )_get_compression_parameterr   rL   rx   rZ   rT   rT   rU   ry        z ZstdCompressionParameters.formatc                 C   r   rg   )r   r   rL   rz   rZ   rT   rT   rU   r{        z+ZstdCompressionParameters.compression_levelc                 C   r   rg   )r   r   rL   r|   rZ   rT   rT   rU   r}     r   z$ZstdCompressionParameters.window_logc                 C   r   rg   )r   r   rL   r~   rZ   rT   rT   rU   r     r   z"ZstdCompressionParameters.hash_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z#ZstdCompressionParameters.chain_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z$ZstdCompressionParameters.search_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z#ZstdCompressionParameters.min_matchc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z'ZstdCompressionParameters.target_lengthc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z"ZstdCompressionParameters.strategyc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z,ZstdCompressionParameters.write_content_sizec                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z(ZstdCompressionParameters.write_checksumc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r     r   z'ZstdCompressionParameters.write_dict_idc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   !  r   z"ZstdCompressionParameters.job_sizec                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   %  r   z%ZstdCompressionParameters.overlap_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   )  r   z*ZstdCompressionParameters.force_max_windowc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   /  r   z$ZstdCompressionParameters.enable_ldmc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   5  r   z&ZstdCompressionParameters.ldm_hash_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   9  r   z'ZstdCompressionParameters.ldm_min_matchc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   =  r   z-ZstdCompressionParameters.ldm_bucket_size_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   C  r   z+ZstdCompressionParameters.ldm_hash_rate_logc                 C   r   rg   )r   r   rL   r   rZ   rT   rT   rU   r   I  r   z!ZstdCompressionParameters.threadsc                 C      t | jS )zAEstimated size in bytes needed to compress with these parameters.)rL   %ZSTD_estimateCCtxSize_usingCCtxParamsr   rZ   rT   rT   rU   "estimated_compression_context_sizeM  s   z<ZstdCompressionParameters.estimated_compression_context_sizeNr   r   )r   r   r   r   r   r   r   r   r   rJ   r   r   r   r   r   r   r   r   r   r   r   )ra   rb   rc   rd   staticmethodr   r   re   ry   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rT   rT   rT   rU   r   O  s    $ 
Z




















r   c                   C   s   t  S )zuEstimate the memory size requirements for a decompressor instance.

    :return:
       Integer number of bytes.
    )rL   ZSTD_estimateDCtxSizerT   rT   rT   rU   r   R  s   r   c                 C   s,   t | ||}t |rtdt| d S )Nz/unable to set compression context parameter: %s)rL   ZSTD_CCtxParams_setParameterZSTD_isErrorr   rr   )r   r   r   rq   rT   rT   rU   r   [  s   
r   c                 C   s:   t d}t| ||}t|rtdt| |d S )Nzint *z/unable to get compression context parameter: %sr   )rK   newrL   ZSTD_CCtxParams_getParameterr   r   rr   )r   r   resultrq   rT   rT   rU   r   d  s   

r   c                   @   s   e Zd ZdZ	d5ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zedd Zdd Zdd Zd6ddZd6ddZd7dd Zd!d" Zd7d#d$Zd%d& Zd'd( Zd6d)d*Zd+d, Zd-d. Zd/d0 Zefd1d2Zd3d4 ZdS )8r   ae  Writable compressing stream wrapper.

    ``ZstdCompressionWriter`` is a write-only stream interface for writing
    compressed data to another stream.

    This type conforms to the ``io.RawIOBase`` interface and should be usable
    by any type that operates against a *file-object* (``typing.BinaryIO``
    in Python type hinting speak). Only methods that involve writing will do
    useful things.

    As data is written to this stream (e.g. via ``write()``), that data
    is sent to the compressor. As compressed data becomes available from
    the compressor, it is sent to the underlying stream by calling its
    ``write()`` method.

    Both ``write()`` and ``flush()`` return the number of bytes written to the
    object's ``write()``. In many cases, small inputs do not accumulate enough
    data to cause a write and ``write()`` will return ``0``.

    Calling ``close()`` will mark the stream as closed and subsequent I/O
    operations will raise ``ValueError`` (per the documented behavior of
    ``io.RawIOBase``). ``close()`` will also call ``close()`` on the underlying
    stream if such a method exists and the instance was constructed with
    ``closefd=True``

    Instances are obtained by calling :py:meth:`ZstdCompressor.stream_writer`.

    Typically usage is as follows:

    >>> cctx = zstandard.ZstdCompressor(level=10)
    >>> compressor = cctx.stream_writer(fh)
    >>> compressor.write(b"chunk 0\n")
    >>> compressor.write(b"chunk 1\n")
    >>> compressor.flush()
    >>> # Receiver will be able to decode ``chunk 0\nchunk 1\n`` at this point.
    >>> # Receiver is also expecting more data in the zstd *frame*.
    >>>
    >>> compressor.write(b"chunk 2\n")
    >>> compressor.flush(zstandard.FLUSH_FRAME)
    >>> # Receiver will be able to decode ``chunk 0\nchunk 1\nchunk 2``.
    >>> # Receiver is expecting no more data, as the zstd frame is closed.
    >>> # Any future calls to ``write()`` at this point will construct a new
    >>> # zstd frame.

    Instances can be used as context managers. Exiting the context manager is
    the equivalent of calling ``close()``, which is equivalent to calling
    ``flush(zstandard.FLUSH_FRAME)``:

    >>> cctx = zstandard.ZstdCompressor(level=10)
    >>> with cctx.stream_writer(fh) as compressor:
    ...     compressor.write(b'chunk 0')
    ...     compressor.write(b'chunk 1')
    ...     ...

    .. important::

       If ``flush(FLUSH_FRAME)`` is not called, emitted data doesn't
       constitute a full zstd *frame* and consumers of this data may complain
       about malformed input. It is recommended to use instances as a context
       manager to ensure *frames* are properly finished.

    If the size of the data being fed to this streaming compressor is known,
    you can declare it before compression begins:

    >>> cctx = zstandard.ZstdCompressor()
    >>> with cctx.stream_writer(fh, size=data_len) as compressor:
    ...     compressor.write(chunk0)
    ...     compressor.write(chunk1)
    ...     ...

    Declaring the size of the source data allows compression parameters to
    be tuned. And if ``write_content_size`` is used, it also results in the
    content size being written into the frame header of the output data.

    The size of chunks being ``write()`` to the destination can be specified:

    >>> cctx = zstandard.ZstdCompressor()
    >>> with cctx.stream_writer(fh, write_size=32768) as compressor:
    ...     ...

    To see how much memory is being used by the streaming compressor:

    >>> cctx = zstandard.ZstdCompressor()
    >>> with cctx.stream_writer(fh) as compressor:
    ...     ...
    ...     byte_size = compressor.memory_size()

    Thte total number of bytes written so far are exposed via ``tell()``:

    >>> cctx = zstandard.ZstdCompressor()
    >>> with cctx.stream_writer(fh) as compressor:
    ...     ...
    ...     total_written = compressor.tell()

    ``stream_writer()`` accepts a ``write_return_read`` boolean argument to
    control the return value of ``write()``. When ``False`` (the default),
    ``write()`` returns the number of bytes that were ``write()``'en to the
    underlying object. When ``True``, ``write()`` returns the number of bytes
    read from the input that were subsequently written to the compressor.
    ``True`` is the *proper* behavior for ``write()`` as specified by the
    ``io.RawIOBase`` interface and will become the default value in a future
    release.
    Tc                 C   s   || _ || _|| _t|| _t|| _d| _d| _d| _d| _	t
d|| _t
d| _| j| j_t| j| j_d| j_t|j|}t|rPtdt| d S )NFr   char[]ZSTD_outBuffer *error setting source size: %s)_compressor_writer_write_sizebool_write_return_read_closefd_entered_closing_closed_bytes_compressedrK   r   _dst_buffer_out_bufferdstlenrf   posrL   ZSTD_CCtx_setPledgedSrcSize_cctxr   r   rr   )r[   
compressorwriterr   
write_sizewrite_return_readclosefdrq   rT   rT   rU   r     s(   	




zZstdCompressionWriter.__init__c                 C   &   | j rtd| jrtdd| _| S Nstream is closedcannot __enter__ multiple timesTr   rS   r   r   rZ   rT   rT   rU   	__enter__     zZstdCompressionWriter.__enter__c                 C   s   d| _ |   d | _dS NF)r   closer   r[   exc_type	exc_valueexc_tbrT   rT   rU   __exit__  s   zZstdCompressionWriter.__exit__c                 C      t  rg   ioUnsupportedOperationrZ   rT   rT   rU   __iter__
     zZstdCompressionWriter.__iter__c                 C   r   rg   r   rZ   rT   rT   rU   __next__  r   zZstdCompressionWriter.__next__c                 C      t | jjS rg   )rL   ZSTD_sizeof_CCtxr   r   rZ   rT   rT   rU   memory_size     z!ZstdCompressionWriter.memory_sizec                 C       t | jdd }|r| S tdNfilenoz)fileno not available on underlying writerr   r   OSErrorr[   frT   rT   rU   r        zZstdCompressionWriter.filenoc                 C   sd   | j rd S zd| _| t W d| _d| _ nd| _d| _ w t| jdd }| jr.|r0|  d S d S d S NTFr   )r   r   flushr   r   r   r   r  rT   rT   rU   r     s   

zZstdCompressionWriter.closec                 C      | j S rg   r   rZ   rT   rT   rU   closed*  r_   zZstdCompressionWriter.closedc                 C      dS r   rT   rZ   rT   rT   rU   isatty.     zZstdCompressionWriter.isattyc                 C   r  r   rT   rZ   rT   rT   rU   readable1  r  zZstdCompressionWriter.readabler   c                 C   r   rg   r   r[   rf   rT   rT   rU   readline4  r   zZstdCompressionWriter.readlinec                 C   r   rg   r   r[   hintrT   rT   rU   	readlines7  r   zZstdCompressionWriter.readlinesNc                 C   r   rg   r   r[   r\   whencerT   rT   rU   seek:  r   zZstdCompressionWriter.seekc                 C   r  r   rT   rZ   rT   rT   rU   seekable=  r  zZstdCompressionWriter.seekablec                 C   r   rg   r   r  rT   rT   rU   truncate@  r   zZstdCompressionWriter.truncatec                 C   r  NTrT   rZ   rT   rT   rU   writableC  r  zZstdCompressionWriter.writablec                 C      t d)Nz#writelines() is not yet implementedrX   r[   linesrT   rT   rU   
writelinesF  r   z ZstdCompressionWriter.writelinesc                 C   r   rg   r   r  rT   rT   rU   readI  r   zZstdCompressionWriter.readc                 C   r   rg   r   rZ   rT   rT   rU   readallL  r   zZstdCompressionWriter.readallc                 C   r   rg   r   r[   brT   rT   rU   readintoO  r   zZstdCompressionWriter.readintoc                 C   s   | j rtdd}t|}td}||_t||_d|_| j	}d|_|j|jk rkt
| jj||t
j}t
|rBtdt| |jre| jt|j|jdd  ||j7 }|  j|j7  _d|_|j|jk s*| jrq|jS |S )z=Send data to the compressor and possibly to the inner stream.r   r   ZSTD_inBuffer *zstd compress error: %sN)r   rS   rK   from_bufferr   srcr   rf   r   r   rL   ZSTD_compressStream2r   r   ZSTD_e_continuer   r   rr   r   writebufferr   r   r   )r[   datatotal_writedata_buffer	in_buffer
out_bufferrq   rT   rT   rU   r*  R  s@   





zZstdCompressionWriter.writec                 C   s  |t krtj}n|tkrtj}ntd| | jrtdd}| j}d|_t	
d}t	j|_d|_d|_	 t| jj|||}t|rLtdt| |jro| jt	|j|jdd  ||j7 }|  j|j7  _d|_|srnq5t| jdd}|r| js|  |S )	a  Evict data from compressor's internal state and write it to inner stream.

        Calling this method may result in 0 or more ``write()`` calls to the
        inner stream.

        This method will also call ``flush()`` on the inner stream, if such a
        method exists.

        :param flush_mode:
           How to flush the zstd compressor.

           ``zstandard.FLUSH_BLOCK`` will flush data already sent to the
           compressor but not emitted to the inner stream. The stream is still
           writable after calling this. This is the default behavior.

           See documentation for other ``zstandard.FLUSH_*`` constants for more
           flushing options.
        :return:
           Integer number of bytes written to the inner stream.
        zunknown flush_mode: %rr   r   r$  Tr%  Nr  )r   rL   ZSTD_e_flushr   
ZSTD_e_endrS   r   r   r   rK   r   rt   r'  rf   r(  r   r   r   r   rr   r   r*  r+  r   r   r   r   )r[   
flush_moder  r-  r0  r/  rq   r  rT   rT   rU   r  |  sH   




zZstdCompressionWriter.flushc                 C   r  rg   r   rZ   rT   rT   rU   tell  rh   zZstdCompressionWriter.tellTr   rg   )ra   rb   rc   rd   r   r   r   r   r   r   r   r   re   r
  r  r  r  r  r  r  r  r  r  r  r   r#  r*  r   r  r5  rT   rT   rT   rU   r   q  s8    o







*Dr   c                   @   s0   e Zd ZdZefddZdd ZefddZdS )	r
   a  A compressor conforming to the API in Python's standard library.

    This type implements an API similar to compression types in Python's
    standard library such as ``zlib.compressobj`` and ``bz2.BZ2Compressor``.
    This enables existing code targeting the standard library API to swap
    in this type to achieve zstd compression.

    .. important::

       The design of this API is not ideal for optimal performance.

       The reason performance is not optimal is because the API is limited to
       returning a single buffer holding compressed data. When compressing
       data, we don't know how much data will be emitted. So in order to
       capture all this data in a single buffer, we need to perform buffer
       reallocations and/or extra memory copies. This can add significant
       overhead depending on the size or nature of the compressed data how
       much your application calls this type.

       If performance is critical, consider an API like
       :py:meth:`ZstdCompressor.stream_reader`,
       :py:meth:`ZstdCompressor.stream_writer`,
       :py:meth:`ZstdCompressor.chunker`, or
       :py:meth:`ZstdCompressor.read_to_iter`, which result in less overhead
       managing buffers.

    Instances are obtained by calling :py:meth:`ZstdCompressor.compressobj`.

    Here is how this API should be used:

    >>> cctx = zstandard.ZstdCompressor()
    >>> cobj = cctx.compressobj()
    >>> data = cobj.compress(b"raw input 0")
    >>> data = cobj.compress(b"raw input 1")
    >>> data = cobj.flush()

    Or to flush blocks:

    >>> cctx.zstandard.ZstdCompressor()
    >>> cobj = cctx.compressobj()
    >>> data = cobj.compress(b"chunk in first block")
    >>> data = cobj.flush(zstandard.COMPRESSOBJ_FLUSH_BLOCK)
    >>> data = cobj.compress(b"chunk in second block")
    >>> data = cobj.flush()

    For best performance results, keep input chunks under 256KB. This avoids
    extra allocations for a large output object.

    It is possible to declare the input size of the data that will be fed
    into the compressor:

    >>> cctx = zstandard.ZstdCompressor()
    >>> cobj = cctx.compressobj(size=6)
    >>> data = cobj.compress(b"foobar")
    >>> data = cobj.flush()
    c                 C   sD   || _ td| _td|| _| j| j_|| j_d| j_d| _d S )Nr   r   r   F)	r   rK   r   _outr   r   rf   r   	_finished)r[   r   r   rT   rT   rU   r     s   

zZstdCompressionObj.__init__c                 C   s   | j rtdt|}td}||_t||_d|_g }|jt|k r^t	
| jj| j|t	j}t	|r>tdt| | jjrW|t| jj| jjdd  d| j_|jt|k s%d|S )a  Send data to the compressor.

        This method receives bytes to feed to the compressor and returns
        bytes constituting zstd compressed data.

        The zstd compressor accumulates bytes and the returned bytes may be
        substantially smaller or larger than the size of the input data on
        any given call. The returned value may be the empty byte string
        (``b""``).

        :param data:
           Data to write to the compressor.
        :return:
           Compressed data.
        z0cannot call compress() after compressor finishedr$  r   r%  N    )r9  r   rK   r&  r   r'  r   rf   r   rL   r(  r   r   r8  r)  r   rr   appendr+  r   join)r[   r,  r.  sourcechunksrq   rT   rT   rU   compress	  s*   




"
zZstdCompressionObj.compressc                 C   s   |t tfvr
td| jrtd|tkrtj}n|t kr$tj}d| _ntd| jj	dks0J t
d}t
j|_d|_d|_	g }	 t| jj| j||}t|rZtdt| | jj	rs|t
| jj| jj	dd  d| j_	|svnqBd	|S )
a  Emit data accumulated in the compressor that hasn't been outputted yet.

        The ``flush_mode`` argument controls how to end the stream.

        ``zstandard.COMPRESSOBJ_FLUSH_FINISH`` (the default) ends the
        compression stream and finishes a zstd frame. Once this type of flush
        is performed, ``compress()`` and ``flush()`` can no longer be called.
        This type of flush **must** be called to end the compression context. If
        not called, the emitted data may be incomplete and may not be readable
        by a decompressor.

        ``zstandard.COMPRESSOBJ_FLUSH_BLOCK`` will flush a zstd block. This
        ensures that all data fed to this instance will have been omitted and
        can be decoded by a decompressor. Flushes of this type can be performed
        multiple times. The next call to ``compress()`` will begin a new zstd
        block.

        :param flush_mode:
           How to flush the zstd compressor.
        :return:
           Compressed data.
        zflush mode not recognizedz"compressor object already finishedTzunhandled flush moder   r$  #error ending compression stream: %sNr:  )r   r   rS   r9  r   rL   r1  r2  r8  r   rK   r   rt   r'  rf   r(  r   r   r   rr   r;  r+  r   r<  )r[   r3  z_flush_moder/  r>  rq   rT   rT   rU   r  3  sD   


"
zZstdCompressionObj.flushN)	ra   rb   rc   rd   r%   r   r?  r   r  rT   rT   rT   rU   r
     s    :
*r
   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r   ar  Compress data to uniformly sized chunks.

    This type allows you to iteratively feed chunks of data into a compressor
    and produce output chunks of uniform size.

    ``compress()``, ``flush()``, and ``finish()`` all return an iterator of
    ``bytes`` instances holding compressed data. The iterator may be empty.
    Callers MUST iterate through all elements of the returned iterator before
    performing another operation on the object or else the compressor's
    internal state may become confused. This can result in an exception being
    raised or malformed data being emitted.

    All chunks emitted by ``compress()`` will have a length of the configured
    chunk size.

    ``flush()`` and ``finish()`` may return a final chunk smaller than
    the configured chunk size.

    Instances are obtained by calling :py:meth:`ZstdCompressor.chunker`.

    Here is how the API should be used:

    >>> cctx = zstandard.ZstdCompressor()
    >>> chunker = cctx.chunker(chunk_size=32768)
    >>>
    >>> with open(path, 'rb') as fh:
    ...     while True:
    ...         in_chunk = fh.read(32768)
    ...         if not in_chunk:
    ...             break
    ...
    ...         for out_chunk in chunker.compress(in_chunk):
    ...             # Do something with output chunk of size 32768.
    ...
    ...     for out_chunk in chunker.finish():
    ...         # Do something with output chunks that finalize the zstd frame.

    This compressor type is often a better alternative to
    :py:class:`ZstdCompressor.compressobj` because it has better performance
    properties.

    ``compressobj()`` will emit output data as it is available. This results
    in a *stream* of output chunks of varying sizes. The consistency of the
    output chunk size with ``chunker()`` is more appropriate for many usages,
    such as sending compressed data to a socket.

    ``compressobj()`` may also perform extra memory reallocations in order
    to dynamically adjust the sizes of the output chunks. Since ``chunker()``
    output chunks are all the same size (except for flushed or final chunks),
    there is less memory allocation/copying overhead.
    c                 C   sj   || _ td| _td|| _| j| j_|| j_d| j_td| _tj	| j_
d| j_d| j_d| _d S )Nr   r   r   r$  F)r   rK   r   r8  r   r   rf   r   _inrt   r'  r9  )r[   r   
chunk_sizerT   rT   rU   r     s   


zZstdCompressionChunker.__init__c                 c   s   | j rtd| jjtjkrtdt|}t|sdS || j_t|| j_d| j_	| jj	| jjk rt
| jj| j| jt
j}| jj	| jjkrVtj| j_d| j_d| j_	t
|rctdt| | jj	| jjkr~t| jj| jj	dd V  d| j_	| jj	| jjk s4dS dS )zFeed new input data into the compressor.

        :param data:
           Data to feed to compressor.
        :return:
           Iterator of ``bytes`` representing chunks of compressed data.
        z1cannot call compress() after compression finishedzHcannot perform operation before consuming output from previous operationNr   r%  )r9  r   rB  r'  rK   rt   r&  r   rf   r   rL   r(  r   r   r8  r)  r   rr   r+  r   )r[   r,  r.  rq   rT   rT   rU   r?    s:   



zZstdCompressionChunker.compressc                 c   s    | j rtd| jjtjkrtd	 t| jj	| j
| jtj}t|r.tdt| | j
jrEt| j
j| j
jdd V  d| j
_|sIdS q)z}Flushes all data currently in the compressor.

        :return:
           Iterator of ``bytes`` of compressed data.
        z.cannot call flush() after compression finishedzCcannot call flush() before consuming output from previous operationTr%  Nr   )r9  r   rB  r'  rK   rt   rL   r(  r   r   r8  r1  r   rr   r   r+  r   r[   rq   rT   rT   rU   r    s*   

zZstdCompressionChunker.flushc                 c   s    | j rtd| jjtjkrtd	 t| jj	| j
| jtj}t|r.tdt| | j
jrEt| j
j| j
jdd V  d| j
_|sLd| _ dS q)zSignals the end of input data.

        No new data can be compressed after this method is called.

        This method will flush buffered data and finish the zstd frame.

        :return:
           Iterator of ``bytes`` of compressed data.
        z/cannot call finish() after compression finishedzDcannot call finish() before consuming output from previous operationTr%  Nr   )r9  r   rB  r'  rK   rt   rL   r(  r   r   r8  r2  r   rr   r   r+  r   rD  rT   rT   rU   finish  s,   


zZstdCompressionChunker.finishN)ra   rb   rc   rd   r   r?  r  rE  rT   rT   rT   rU   r   w  s    4-r   c                   @   s   e Zd ZdZd5d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edd Zdd  Zd!d" Zd#d$ Zd%d& ZeZd'd( Zd)d* Zd6d,d-Zd6d.d/Zd0d1 Zd2d3 Zd4S )7r   a3
  Readable compressing stream wrapper.

    ``ZstdCompressionReader`` is a read-only stream interface for obtaining
    compressed data from a source.

    This type conforms to the ``io.RawIOBase`` interface and should be usable
    by any type that operates against a *file-object* (``typing.BinaryIO``
    in Python type hinting speak).

    Instances are neither writable nor seekable (even if the underlying
    source is seekable). ``readline()`` and ``readlines()`` are not implemented
    because they don't make sense for compressed data. ``tell()`` returns the
    number of compressed bytes emitted so far.

    Instances are obtained by calling :py:meth:`ZstdCompressor.stream_reader`.

    In this example, we open a file for reading and then wrap that file
    handle with a stream from which compressed data can be ``read()``.

    >>> with open(path, 'rb') as fh:
    ...     cctx = zstandard.ZstdCompressor()
    ...     reader = cctx.stream_reader(fh)
    ...     while True:
    ...         chunk = reader.read(16384)
    ...         if not chunk:
    ...             break
    ...
    ...         # Do something with compressed chunk.

    Instances can also be used as context managers:

    >>> with open(path, 'rb') as fh:
    ...     cctx = zstandard.ZstdCompressor()
    ...     with cctx.stream_reader(fh) as reader:
    ...         while True:
    ...             chunk = reader.read(16384)
    ...             if not chunk:
    ...                 break
    ...
    ...             # Do something with compressed chunk.

    When the context manager exits or ``close()`` is called, the stream is
    closed, underlying resources are released, and future operations against
    the compression stream will fail.

    ``stream_reader()`` accepts a ``size`` argument specifying how large the
    input stream is. This is used to adjust compression parameters so they are
    tailored to the source size. e.g.

    >>> with open(path, 'rb') as fh:
    ...     cctx = zstandard.ZstdCompressor()
    ...     with cctx.stream_reader(fh, size=os.stat(path).st_size) as reader:
    ...         ...

    If the ``source`` is a stream, you can specify how large ``read()``
    requests to that stream should be via the ``read_size`` argument.
    It defaults to ``zstandard.COMPRESSION_RECOMMENDED_INPUT_SIZE``. e.g.

    >>> with open(path, 'rb') as fh:
    ...     cctx = zstandard.ZstdCompressor()
    ...     # Will perform fh.read(8192) when obtaining data to feed into the
    ...     # compressor.
    ...     with cctx.stream_reader(fh, read_size=8192) as reader:
    ...         ...
    Tc                 C   sL   || _ || _|| _|| _d| _d| _d| _d| _d| _t	
d| _d | _d S NFr   r$  )r   _source
_read_sizer   r   r   r   _finished_input_finished_outputrK   r   
_in_buffer_source_buffer)r[   r   r=  	read_sizer   rT   rT   rU   r   n  s   
zZstdCompressionReader.__init__c                 C   &   | j rtd| jrtdd| _ | S Nr   r   Tr   rS   r   rZ   rT   rT   rU   r   }  r   zZstdCompressionReader.__enter__c                 C      d| _ d | _|   d | _dS r   )r   r   r   rG  r   rT   rT   rU   r     
   zZstdCompressionReader.__exit__c                 C   r  r  rT   rZ   rT   rT   rU   r    r  zZstdCompressionReader.readablec                 C   r  r   rT   rZ   rT   rT   rU   r    r  zZstdCompressionReader.writablec                 C   r  r   rT   rZ   rT   rT   rU   r    r  zZstdCompressionReader.seekablec                 C   r   rg   r   rZ   rT   rT   rU   r    r   zZstdCompressionReader.readlinec                 C   r   rg   r   rZ   rT   rT   rU   r    r   zZstdCompressionReader.readlinesc                 C   r  Nzstream is not writabler  r[   r,  rT   rT   rU   r*    r   zZstdCompressionReader.writec                 C   r  rS  rT  )r[   ignoredrT   rT   rU   r    r   z ZstdCompressionReader.writelinesc                 C   r  r   rT   rZ   rT   rT   rU   r    r  zZstdCompressionReader.isattyc                 C      d S rg   rT   rZ   rT   rT   rU   r    r  zZstdCompressionReader.flushc                 C   :   | j rd S d| _ t| jdd }| jr|r|  d S d S d S NTr   r   r   rG  r   r  rT   rT   rU   r        

zZstdCompressionReader.closec                 C   r  rg   r	  rZ   rT   rT   rU   r
    r_   zZstdCompressionReader.closedc                 C   r  rg   r4  rZ   rT   rT   rU   r5    rh   zZstdCompressionReader.tellc                 C   ,   g }	 |  d}|sn|| qd|S NTi   r:  r  r;  r<  r[   r>  chunkrT   rT   rU   r        


zZstdCompressionReader.readallc                 C   r   rg   r   rZ   rT   rT   rU   r     r   zZstdCompressionReader.__iter__c                 C   r   rg   r   rZ   rT   rT   rU   r     r   zZstdCompressionReader.__next__c                 C   s   | j rd S t| jdr1| j| j}|sd| _ d S t|| _| j| j_	t
| j| j_d| j_d S t| j| _| j| j_	t
| j| j_d| j_d S Nr  Tr   )rI  hasattrrG  r  rH  rK   r&  rL  rK  r'  r   rf   r   rU  rT   rT   rU   _read_input  s   

z!ZstdCompressionReader._read_inputc                 C   s   | j j| j jkr
d S |j}t| jj|| j tj}|  j|j| 7  _| j j| j jkrDt	j
| j _d| j _d| j _d | _t| jdsDd| _t|rPtdt||joX|j|jkS )Nr   r  Tr%  )rK  r   rf   rL   r(  r   r   r)  r   rK   rt   r'  rL  rc  rG  rI  r   r   rr   )r[   r0  old_posrq   rT   rT   rU   _compress_into_buffer  s(   

z+ZstdCompressionReader._compress_into_bufferr   c                 C   s0  | j rtd|dk rtd|dkr|  S | js|dkr dS td|}td}||_||_d|_| 	|rEt
|j|jd d  S | js`|   | 	|r]t
|j|jd d  S | jrH|j}t| jj|| jtj}|  j|j| 7  _t|rtdt||dkrd	| _t
|j|jd d  S 
Nr   r   )cannot read negative amounts less than -1r   r:  r   r   r@  T)r   rS   r   rJ  rK   r   r   rf   r   rf  r+  rI  rd  rL   r(  r   r   rK  r2  r   r   r   rr   r[   rf   
dst_bufferr0  re  rq   rT   rT   rU   r    s@   



zZstdCompressionReader.readc                 C   sX  | j rtd|dk rtd| js|dkrdS |dkrt}td|}td}||_||_d|_| 	| |jrFt
|j|jd d  S | jss|   | 	|r^t
|j|jd d  S |jrp| jspt
|j|jd d  S | jrI|j}t| jj|| jtj}|  j|j| 7  _t|rtdt| |dkrd	| _t
|j|jd d  S rg  )r   rS   rJ  r%   rK   r   r   rf   r   rf  r+  rI  rd  rL   r(  r   r   rK  r2  r   r   r   rr   ri  rT   rT   rU   read11  sF   





zZstdCompressionReader.read1c                 C   s   | j rtd| jrdS t|}t|dd td}||_t||_	d|_
| |r0|j
S | jsB|   | |r?|j
S | jr3|j
}t| jj|| jtj}|  j|j
| 7  _t|rgtdt||dkrnd| _|j
S Nr   r   r:  r   r@  Tr   rS   rJ  rK   r&  memmover   r   r   rf   r   rf  rI  rd  rL   r(  r   r   rK  r2  r   r   r   rr   r[   r"  dest_bufferr0  re  rq   rT   rT   rU   r#  s  s:   





zZstdCompressionReader.readintoc                 C   s   | j rtd| jrdS t|}t|dd td}||_t||_	d|_
| | |j
r3|j
S | jsN|   | |rB|j
S |j
rK| jsK|j
S | jr6|j
}t| jj|| jtj}|  j|j
| 7  _t|rttdt| |dkr{d| _|j
S rl  rm  ro  rT   rT   rU   	readinto1  s@   







zZstdCompressionReader.readinto1Nr6  r7  )ra   rb   rc   rd   r   r   r   r  r  r  r  r  r*  r  r  r  r   re   r
  r5  r   r   r   nextrd  rf  r  rk  r#  rq  rT   rT   rT   rU   r   +  s8    
B




0B)r   c                   @   s   e Zd ZdZ							dddZdd Zd	d
 Zdd Zd ddZde	fddZ
dee	fddZdedfddZde	ddfddZdee	fddZd ddZdd ZdS )!r   a  
    Create an object used to perform Zstandard compression.

    Each instance is essentially a wrapper around a ``ZSTD_CCtx`` from
    zstd's C API.

    An instance can compress data various ways. Instances can be used
    multiple times. Each compression operation will use the compression
    parameters defined at construction time.

    .. note:

       When using a compression dictionary and multiple compression
       operations are performed, the ``ZstdCompressionParameters`` derived
       from an integer compression ``level`` and the first compressed data's
       size will be reused for all subsequent operations. This may not be
       desirable if source data sizes vary significantly.

    ``compression_params`` is mutually exclusive with ``level``,
    ``write_checksum``, ``write_content_size``, ``write_dict_id``, and
    ``threads``.

    Assume that each ``ZstdCompressor`` instance can only handle a single
    logical compression operation at the same time. i.e. if you call a method
    like ``stream_reader()`` to obtain multiple objects derived from the same
    ``ZstdCompressor`` instance and attempt to use them simultaneously, errors
    will likely occur.

    If you need to perform multiple logical compression operations and you
    can't guarantee those operations are temporally non-overlapping, you need
    to obtain multiple ``ZstdCompressor`` instances.

    Unless specified otherwise, assume that no two methods of
    ``ZstdCompressor`` instances can be called from multiple Python
    threads simultaneously. In other words, assume instances are not thread safe
    unless stated otherwise.

    :param level:
       Integer compression level. Valid values are all negative integers
       through 22. Lower values generally yield faster operations with lower
       compression ratios. Higher values are generally slower but compress
       better. The default is 3, which is what the ``zstd`` CLI uses. Negative
       levels effectively engage ``--fast`` mode from the ``zstd`` CLI.
    :param dict_data:
       A ``ZstdCompressionDict`` to be used to compress with dictionary
        data.
    :param compression_params:
       A ``ZstdCompressionParameters`` instance defining low-level compression
       parameters. If defined, this will overwrite the ``level`` argument.
    :param write_checksum:
       If True, a 4 byte content checksum will be written with the compressed
       data, allowing the decompressor to perform content verification.
    :param write_content_size:
       If True (the default), the decompressed content size will be included
       in the header of the compressed data. This data will only be written if
       the compressor knows the size of the input data.
    :param write_dict_id:
       Determines whether the dictionary ID will be written into the compressed
       data. Defaults to True. Only adds content to the compressed data if
       a dictionary is being used.
    :param threads:
       Number of threads to use to compress data concurrently. When set,
       compression operations are performed on multiple threads. The default
       value (0) disables multi-threaded compression. A value of ``-1`` means
       to set the number of threads to the number of detected logical CPUs.
       Nr   c           
      C   s  |t  krtdt   |dk rt }|r|d urtd|r)|d ur)td|r3|d ur3td|r;|r;td|rCt|| _nR|d u rId}t  }|tjkrUt	 t
|t j| _t| jt j| t| jt j|d urp|nd t| jt j|r|dnd t| jt j|rdnd |rt| jt j| t  }	|	tjkrt	 |	| _|| _z|   W tj
|	t jt |	d	| _d S tj
|	t jt |	d	| _w )
Nzlevel must be less than %dr   z3cannot define compression_params and write_checksumz7cannot define compression_params and write_content_sizez2cannot define compression_params and write_dict_idz,cannot define compression_params and threadsTrJ   rf   )rL   ZSTD_maxCLevelrS   rV   r   r   rs   rK   rt   ru   rv   rw   r   rz   r   r   r   r   ZSTD_createCCtxr   
_dict_data_setup_cctxZSTD_freeCCtxr   )
r[   r   	dict_datacompression_paramsr   r   r   r   r   cctxrT   rT   rU   r     sx   








zZstdCompressor.__init__c                 C   s   t | j| j}t |rtdt| | j}|rC|jr&t 	| j|j}nt 
| j| t|t j|j}t |rEtdt| d S d S )Nz(could not set compression parameters: %sz)could not load compression dictionary: %s)rL   &ZSTD_CCtx_setParametersUsingCCtxParamsr   r   r   r   rr   rw  _cdictZSTD_CCtx_refCDict!ZSTD_CCtx_loadDictionary_advancedas_bytesr   ZSTD_dlm_byRef
_dict_type)r[   rq   rz  rT   rT   rU   rx  j  s8   

zZstdCompressor._setup_cctxc                 C   r   )zObtain the memory usage of this compressor, in bytes.

        >>> cctx = zstandard.ZstdCompressor()
        >>> memory = cctx.memory_size()
        )rL   r   r   rZ   rT   rT   rU   r        zZstdCompressor.memory_sizec                 C   s   t | jt j t|}t t|}td|}t 	| jt|}t 
|r/tdt| td}td}||_||_d|_||_t||_d|_t | j||t j}t 
|rdtdt| |rjtdt||jdd S )	a  
        Compress data in a single operation.

        This is the simplest mechanism to perform compression: simply pass in a
        value and get a compressed value back. It is almost the most prone to
        abuse.

        The input and output values must fit in memory, so passing in very large
        values can result in excessive memory usage. For this reason, one of the
        streaming based APIs is preferred for larger values.

        :param data:
           Source data to compress
        :return:
           Compressed data

        >>> cctx = zstandard.ZstdCompressor()
        >>> compressed = cctx.compress(b"data to compress")
        r   r   r   r$  r   zcannot compress: %szunexpected partial frame flushN)rL   ZSTD_CCtx_resetr   ZSTD_reset_session_onlyrK   r&  ZSTD_compressBoundr   new_nonzeror   r   r   rr   r   r   rf   r   r'  r(  r2  r+  )r[   r,  r.  	dest_sizeoutrq   r0  r/  rT   rT   rU   r?    s2   







zZstdCompressor.compressr   c                 C   sT   t | jt j |dk rt j}t | j|}t |r#tdt| t	| t
}|S )a.  
        Obtain a compressor exposing the Python standard library compression API.

        See :py:class:`ZstdCompressionObj` for the full documentation.

        :param size:
           Size in bytes of data that will be compressed.
        :return:
           :py:class:`ZstdCompressionObj`
        r   r   )rL   r  r   r  ZSTD_CONTENTSIZE_UNKNOWNr   r   r   rr   r
   r%   )r[   rf   rq   cobjrT   rT   rU   compressobj  s   


zZstdCompressor.compressobjc                 C   sR   t | jt j |dk rt j}t | j|}t |r#tdt| t	| |dS )a  
        Create an object for iterative compressing to same-sized chunks.

        This API is similar to :py:meth:`ZstdCompressor.compressobj` but has
        better performance properties.

        :param size:
           Size in bytes of data that will be compressed.
        :param chunk_size:
           Size of compressed chunks.
        :return:
           :py:class:`ZstdCompressionChunker`
        r   r   )rC  )
rL   r  r   r  r  r   r   r   rr   r   )r[   rf   rC  rq   rT   rT   rU   chunker  s   

zZstdCompressor.chunkerc                 C   s  t |ds	tdt |dstdt| jtj |dk r!tj}t| j|}t|r5t	dt
| td}td}td	|}	|	|_||_d|_d
\}
}	 ||}|s[nPt|}|
t|7 }
||_t||_d|_|j|jk rt| j||tj}t|rt	dt
| |jr|t|j|j ||j7 }d|_|j|jk swqS	 t| j||tj}t|rt	dt
| |jr|t|j|j ||j7 }d|_|dkr	 |
|fS q)a"  
        Copy data between 2 streams while compressing it.

        Data will be read from ``ifh``, compressed, and written to ``ofh``.
        ``ifh`` must have a ``read(size)`` method. ``ofh`` must have a
        ``write(data)``
        method.

        >>> cctx = zstandard.ZstdCompressor()
        >>> with open(input_path, "rb") as ifh, open(output_path, "wb") as ofh:
        ...     cctx.copy_stream(ifh, ofh)

        It is also possible to declare the size of the source stream:

        >>> cctx = zstandard.ZstdCompressor()
        >>> cctx.copy_stream(ifh, ofh, size=len_of_input)

        You can also specify how large the chunks that are ``read()``
        and ``write()`` from and to the streams:

        >>> cctx = zstandard.ZstdCompressor()
        >>> cctx.copy_stream(ifh, ofh, read_size=32768, write_size=16384)

        The stream copier returns a 2-tuple of bytes read and written:

        >>> cctx = zstandard.ZstdCompressor()
        >>> read_count, write_count = cctx.copy_stream(ifh, ofh)

        :param ifh:
           Source stream to read from
        :param ofh:
           Destination stream to write to
        :param size:
           Size in bytes of the source stream. If defined, compression
           parameters will be tuned for this size.
        :param read_size:
           Chunk sizes that source stream should be ``read()`` from.
        :param write_size:
           Chunk sizes that destination stream should be ``write()`` to.
        :return:
           2-tuple of ints of bytes read and written, respectively.
        r  (first argument must have a read() methodr*  *second argument must have a write() methodr   r   r$  r   r   r   Tr%  r@  )rc  rS   rL   r  r   r  r  r   r   r   rr   rK   r   r   rf   r   r  r&  r   r'  r(  r)  r*  r+  r2  )r[   ifhofhrf   rM  r   rq   r/  r0  rj  
total_readr-  r,  r.  rT   rT   rU   copy_stream  st   
3













zZstdCompressor.copy_streamTc                 C   sv   t | jt j zt|}W n	 ty   Y nw |dk rt j}t | j|}t |r3t	dt
| t| |||dS )a  
        Wrap a readable source with a stream that can read compressed data.

        This will produce an object conforming to the ``io.RawIOBase``
        interface which can be ``read()`` from to retrieve compressed data
        from a source.

        The source object can be any object with a ``read(size)`` method
        or an object that conforms to the buffer protocol.

        See :py:class:`ZstdCompressionReader` for type documentation and usage
        examples.

        :param source:
           Object to read source data from
        :param size:
           Size in bytes of source object.
        :param read_size:
           How many bytes to request when ``read()``'ing from the source.
        :param closefd:
           Whether to close the source stream when the returned stream is
           closed.
        :return:
           :py:class:`ZstdCompressionReader`
        r   r   r   )rL   r  r   r  r   	Exceptionr  r   r   r   rr   r   )r[   r=  rf   rM  r   rq   rT   rT   rU   stream_readerv  s    

zZstdCompressor.stream_readerc                 C   sD   t |ds	tdt| jtj |dk rtj}t| |||||dS )a  
        Create a stream that will write compressed data into another stream.

        The argument to ``stream_writer()`` must have a ``write(data)`` method.
        As compressed data is available, ``write()`` will be called with the
        compressed data as its argument. Many common Python types implement
        ``write()``, including open file handles and ``io.BytesIO``.

        See :py:class:`ZstdCompressionWriter` for more documentation, including
        usage examples.

        :param writer:
           Stream to write compressed data to.
        :param size:
           Size in bytes of data to be compressed. If set, it will be used
           to influence compression parameter tuning and could result in the
           size being written into the header of the compressed data.
        :param write_size:
           How much data to ``write()`` to ``writer`` at a time.
        :param write_return_read:
           Whether ``write()`` should return the number of bytes that were
           consumed from the input.
        :param closefd:
           Whether to ``close`` the ``writer`` when this stream is closed.
        :return:
           :py:class:`ZstdCompressionWriter`
        r*  )must pass an object with a write() methodr   r  )rc  rS   rL   r  r   r  r  r   )r[   r   rf   r   r   r   rT   rT   rU   stream_writer  s   
#zZstdCompressor.stream_writerc                 c   s0   t |dr	d}nt |drd}d}t|}ntdt| jtj |dk r*tj}t| j|}t	|r>t
dt| td}td	}	tj|_d|_d|_td
|}
|
|	_||	_d|	_	 |	jdksiJ |rq||}nt|| }t||}||||  }||7 }|snPt|}||_t||_d|_|j|jk rt| j|	|tj}t	|rt
dt| |	jrt|	j|	jdd }d|	_|V  |j|jk s|	jdksJ qa	 |	jdksJ t| j|	|tj}t	|rt
dt| |	jrt|	j|	jdd }d|	_|V  |dkrdS q)a#
  
        Read uncompressed data from a reader and return an iterator

        Returns an iterator of compressed data produced from reading from
        ``reader``.

        This method provides a mechanism to stream compressed data out of a
        source as an iterator of data chunks.

        Uncompressed data will be obtained from ``reader`` by calling the
        ``read(size)`` method of it or by reading a slice (if ``reader``
        conforms to the *buffer protocol*). The source data will be streamed
        into a compressor. As compressed data is available, it will be exposed
        to the iterator.

        Data is read from the source in chunks of ``read_size``. Compressed
        chunks are at most ``write_size`` bytes. Both values default to the
        zstd input and and output defaults, respectively.

        If reading from the source via ``read()``, ``read()`` will be called
        until it raises or returns an empty bytes (``b""``). It is perfectly
        valid for the source to deliver fewer bytes than were what requested
        by ``read(size)``.

        The caller is partially in control of how fast data is fed into the
        compressor by how it consumes the returned iterator. The compressor
        will not consume from the reader unless the caller consumes from the
        iterator.

        >>> cctx = zstandard.ZstdCompressor()
        >>> for chunk in cctx.read_to_iter(fh):
        ...     # Do something with emitted data.

        ``read_to_iter()`` accepts a ``size`` argument declaring the size of
        the input stream:

        >>> cctx = zstandard.ZstdCompressor()
        >>> for chunk in cctx.read_to_iter(fh, size=some_int):
        >>>     pass

        You can also control the size that data is ``read()`` from the source
        and the ideal size of output chunks:

        >>> cctx = zstandard.ZstdCompressor()
        >>> for chunk in cctx.read_to_iter(fh, read_size=16384, write_size=8192):
        >>>     pass

        ``read_to_iter()`` does not give direct control over the sizes of chunks
        fed into the compressor. Instead, chunk sizes will be whatever the object
        being read from delivers. These will often be of a uniform size.

        :param reader:
           Stream providing data to be compressed.
        :param size:
           Size in bytes of input data.
        :param read_size:
           Controls how many bytes are ``read()`` from the source.
        :param write_size:
           Controls the output size of emitted chunks.
        :return:
           Iterator of ``bytes``.
        r  Trk   Fr   Gmust pass an object with a read() method or conforms to buffer protocolr   r$  r   r   r%  Nr@  )rc  r   rS   rL   r  r   r  r  r   r   r   rr   rK   r   rt   r'  rf   r   r   r  minr&  r(  r)  r+  r2  )r[   readerrf   rM  r   	have_readbuffer_offsetrq   r/  r0  rj  read_result	remaining
slice_sizeread_bufferr,  rT   rT   rU   read_to_iter  s   
F













zZstdCompressor.read_to_iterc                 C   rW   )a  
        Compress multiple pieces of data as a single function call.

        (Experimental. Not yet supported by CFFI backend.)

        This function is optimized to perform multiple compression operations
        as as possible with as little overhead as possible.

        Data to be compressed can be passed as a ``BufferWithSegmentsCollection``,
        a ``BufferWithSegments``, or a list containing byte like objects. Each
        element of the container will be compressed individually using the
        configured parameters on the ``ZstdCompressor`` instance.

        The ``threads`` argument controls how many threads to use for
        compression. The default is ``0`` which means to use a single thread.
        Negative values use the number of logical CPUs in the machine.

        The function returns a ``BufferWithSegmentsCollection``. This type
        represents N discrete memory allocations, each holding 1 or more
        compressed frames.

        Output data is written to shared memory buffers. This means that unlike
        regular Python objects, a reference to *any* object within the collection
        keeps the shared buffer and therefore memory backing it alive. This can
        have undesirable effects on process memory usage.

        The API and behavior of this function is experimental and will likely
        change. Known deficiencies include:

        * If asked to use multiple threads, it will always spawn that many
          threads, even if the input is too small to use them. It should
          automatically lower the thread count when the extra threads would
          just add overhead.
        * The buffer allocation strategy is fixed. There is room to make it
          dynamic, perhaps even to allow one output buffer per input,
          facilitating a variation of the API to return a list without the
          adverse effects of shared memory buffers.

        :param data:
           Source to read discrete pieces of data to compress.

           Can be a ``BufferWithSegmentsCollection``, a ``BufferWithSegments``,
           or a ``list[bytes]``.
        :return:
           BufferWithSegmentsCollection holding compressed data.
        rX   )r[   r,  r   rT   rT   rU   multi_compress_to_buffer	  s   /z'ZstdCompressor.multi_compress_to_bufferc                 C   s   t | j}|j|j|jfS )a  
        Return information on how much work the compressor has done.

        Returns a 3-tuple of (ingested, consumed, produced).

        >>> cctx = zstandard.ZstdCompressor()
        >>> (ingested, consumed, produced) = cctx.frame_progression()
        )rL   ZSTD_getFrameProgressionr   ingestedconsumedproduced)r[   progressionrT   rT   rU   frame_progression	  s   	z ZstdCompressor.frame_progression)rs  NNNNNr   r7  )ra   rb   rc   rd   r   rx  r   r?  r  r%   r  r$   r  r  r  r  r  r  rT   rT   rT   rU   r     sF    E
Y
7
}
5
2
 
*1r   c                   @   s   e Zd ZdZdd ZdS )r   a  Information about a zstd frame.

    Instances have the following attributes:

    ``content_size``
       Integer size of original, uncompressed content. This will be ``0`` if the
       original content size isn't written to the frame (controlled with the
       ``write_content_size`` argument to ``ZstdCompressor``) or if the input
       content size was ``0``.

    ``window_size``
       Integer size of maximum back-reference distance in compressed data.

    ``dict_id``
       Integer of dictionary ID used for compression. ``0`` if no dictionary
       ID was used or if the dictionary ID was ``0``.

    ``has_checksum``
       Bool indicating whether a 4 byte content checksum is stored at the end
       of the frame.
    c                 C   s(   |j | _|j| _|j| _t|j| _d S rg   )	frameContentSizecontent_size
windowSizewindow_sizedictIDdict_idr   checksumFlaghas_checksum)r[   fparamsrT   rT   rU   r   	  s   zFrameParameters.__init__N)ra   rb   rc   rd   r   rT   rT   rT   rU   r   	  s    r   c                 C   s>   t | }t|t|}|tjkrtd|tjkrdS |S )zObtain the decompressed size of a frame.

    The returned value is usually accurate. But strictly speaking it should
    not be trusted.

    :return:
       ``-1`` if size unknown and a non-negative integer otherwise.
    z#error when determining content sizer   )rK   r&  rL   ZSTD_getFrameContentSizer   ZSTD_CONTENTSIZE_ERRORr   r  )r,  r.  rf   rT   rT   rU   r   	  s   
	

r   c                 C   s8   t | }t|t|}t|rtdt| |S )zSObtain the size of a frame header.

    :return:
       Integer size in bytes.
    z)could not determine frame header size: %s)rK   r&  rL   ZSTD_frameHeaderSizer   r   r   rr   )r,  r.  rq   rT   rT   rU   r   	  s   


r   c                 C   s\   t d}t | }t||t|}t|r tdt| |r(td| t	|d S )a  
    Parse a zstd frame header into frame parameters.

    Depending on which fields are present in the frame and their values, the
    length of the frame parameters varies. If insufficient bytes are passed
    in to fully parse the frame parameters, ``ZstdError`` is raised. To ensure
    frame parameters can be parsed, pass in at least 18 bytes.

    :param data:
       Data from which to read frame parameters.
    :return:
       :py:class:`FrameParameters`
    ZSTD_frameHeader *zcannot get frame parameters: %sz3not enough data for frame parameters; need %d bytesr   )
rK   r   r&  rL   ZSTD_getFrameHeaderr   r   r   rr   r   )r,  r   r.  rq   rT   rT   rU   r   
  s   



r   c                   @   sN   e Zd ZdZeddfddZdd Zdd Zd	d
 ZdddZ	e
dd ZdS )r	   a  Represents a computed compression dictionary.

    Instances are obtained by calling :py:func:`train_dictionary` or by
    passing bytes obtained from another source into the constructor.

    Instances can be constructed from bytes:

    >>> dict_data = zstandard.ZstdCompressionDict(data)

    It is possible to construct a dictionary from *any* data. If the data
    doesn't begin with a magic header, it will be treated as a *prefix*
    dictionary. *Prefix* dictionaries allow compression operations to
    reference raw data within the dictionary.

    It is possible to force the use of *prefix* dictionaries or to require
    a dictionary header:

    >>> dict_data = zstandard.ZstdCompressionDict(data, dict_type=zstandard.DICT_TYPE_RAWCONTENT)
    >>> dict_data = zstandard.ZstdCompressionDict(data, dict_type=zstandard.DICT_TYPE_FULLDICT)

    You can see how many bytes are in the dictionary by calling ``len()``:

    >>> dict_data = zstandard.train_dictionary(size, samples)
    >>> dict_size = len(dict_data)  # will not be larger than ``size``

    Once you have a dictionary, you can pass it to the objects performing
    compression and decompression:

    >>> dict_data = zstandard.train_dictionary(131072, samples)
    >>> cctx = zstandard.ZstdCompressor(dict_data=dict_data)
    >>> for source_data in input_data:
    ...     compressed = cctx.compress(source_data)
    ...     # Do something with compressed data.
    ...
    >>> dctx = zstandard.ZstdDecompressor(dict_data=dict_data)
    >>> for compressed_data in input_data:
    ...     buffer = io.BytesIO()
    ...     with dctx.stream_writer(buffer) as decompressor:
    ...         decompressor.write(compressed_data)
    ...         # Do something with raw data in ``buffer``.

    Dictionaries have unique integer IDs. You can retrieve this ID via:

    >>> dict_id = zstandard.dictionary_id(dict_data)

    You can obtain the raw data in the dict (useful for persisting and constructing
    a ``ZstdCompressionDict`` later) via ``as_bytes()``:

    >>> dict_data = zstandard.train_dictionary(size, samples)
    >>> raw_data = dict_data.as_bytes()

    By default, when a ``ZstdCompressionDict`` is *attached* to a
    ``ZstdCompressor``, each ``ZstdCompressor`` performs work to prepare the
    dictionary for use. This is fine if only 1 compression operation is being
    performed or if the ``ZstdCompressor`` is being reused for multiple operations.
    But if multiple ``ZstdCompressor`` instances are being used with the dictionary,
    this can add overhead.

    It is possible to *precompute* the dictionary so it can readily be consumed
    by multiple ``ZstdCompressor`` instances:

    >>> d = zstandard.ZstdCompressionDict(data)
    >>> # Precompute for compression level 3.
    >>> d.precompute_compress(level=3)
    >>> # Precompute with specific compression parameters.
    >>> params = zstandard.ZstdCompressionParameters(...)
    >>> d.precompute_compress(compression_params=params)

    .. note::

       When a dictionary is precomputed, the compression parameters used to
       precompute the dictionary overwrite some of the compression parameters
       specified to ``ZstdCompressor``.

    :param data:
       Dictionary data.
    :param dict_type:
       Type of dictionary. One of the ``DICT_TYPE_*`` constants.
    r   c                 C   sF   t |tsJ || _|| _|| _|tttfvrtd|| _	d | _
d S )Nz@invalid dictionary load mode: %d; must use DICT_TYPE_* constants)
isinstancebytes_datakdrE   rF   rG   rS   r  r~  )r[   r,  	dict_typer  r  rT   rT   rU   r   s
  s   
zZstdCompressionDict.__init__c                 C   s
   t | jS rg   )r   r  rZ   rT   rT   rU   r^   
  s   
zZstdCompressionDict.__len__c                 C   s   t t| jt| jS )z(Obtain the integer ID of the dictionary.)intrL   ZDICT_getDictIDr  r   rZ   rT   rT   rU   r  
  s   zZstdCompressionDict.dict_idc                 C   r  )z6Obtain the ``bytes`` representation of the dictionary.)r  rZ   rT   rT   rU   r  
  r_   zZstdCompressionDict.as_bytesNc                 C   s   |r|rt d|s|st d|rt|dt| j}n!td}|j|_|j	|_
|j|_|j|_|j|_|j|_|j|_t| jt| jtj| j|tj}|tjkrXtdtj|tjt|d| _dS )zPrecompute a dictionary os it can be used by multiple compressors.

        Calling this method on an instance that will be used by multiple
        :py:class:`ZstdCompressor` instances will improve performance.
        z4must only specify one of level or compression_paramsz/must specify one of level or compression_paramsr   ZSTD_compressionParameterszunable to precompute dictionaryrt  N)rS   rL   r   r   r  rK   r   r   r   r   r   r   r   r   r   r   r   r   r}   r   ZSTD_createCDict_advancedr  r  ZSTD_defaultCMemrt   r   rv   ZSTD_freeCDictZSTD_sizeof_CDictr~  )r[   r   r{  cparamscdictrT   rT   rU   precompute_compress
  s:   

z'ZstdCompressionDict.precompute_compressc                 C   sX   t | jt| jt j| jt j}|tjkrt	dtj
|t jt |d}|| jd< |S )Nz#could not create decompression dictrt  _ddict)rL   ZSTD_createDDict_advancedr  r   r  r  r  rK   rt   r   rv   ZSTD_freeDDictZSTD_sizeof_DDict__dict__)r[   ddictrT   rT   rU   r  
  s   

zZstdCompressionDict._ddict)r   N)ra   rb   rc   rd   rE   r   r^   r  r  r  re   r  rT   rT   rT   rU   r	   "
  s    P
)r	           c              
   C   s  t |ts	td|dk rt }|
s |s |pd}|
pd}
|	pd}	ttt|}td|}tdt|}d}t|D ]"\}}t |t	sFt
dt|}t|| || ||7 }|||< q9td| }td	d }||_||_||_|
|_||_||_||_||j_||j_|	|j_tt|| t|t|dt|t|}t|rtt|d
}t d| t!t"||dd t#|j|jdS )a  Train a dictionary from sample data using the COVER algorithm.

    A compression dictionary of size ``dict_size`` will be created from the
    iterable of ``samples``. The raw dictionary bytes will be returned.

    The dictionary training mechanism is known as *cover*. More details about it
    are available in the paper *Effective Construction of Relative Lempel-Ziv
    Dictionaries* (authors: Liao, Petri, Moffat, Wirth).

    The cover algorithm takes parameters ``k`` and ``d``. These are the
    *segment size* and *dmer size*, respectively. The returned dictionary
    instance created by this function has ``k`` and ``d`` attributes
    containing the values for these parameters. If a ``ZstdCompressionDict``
    is constructed from raw bytes data (a content-only dictionary), the
    ``k`` and ``d`` attributes will be ``0``.

    The segment and dmer size parameters to the cover algorithm can either be
    specified manually or ``train_dictionary()`` can try multiple values
    and pick the best one, where *best* means the smallest compressed data size.
    This later mode is called *optimization* mode.

    Under the hood, this function always calls
    ``ZDICT_optimizeTrainFromBuffer_fastCover()``. See the corresponding C library
    documentation for more.

    If neither ``steps`` nor ``threads`` is defined, defaults for ``d``, ``steps``,
    and ``level`` will be used that are equivalent with what
    ``ZDICT_trainFromBuffer()`` would use.


    :param dict_size:
       Target size in bytes of the dictionary to generate.
    :param samples:
       A list of bytes holding samples the dictionary will be trained from.
    :param k:
       Segment size : constraint: 0 < k : Reasonable range [16, 2048+]
    :param d:
       dmer size : constraint: 0 < d <= k : Reasonable range [6, 16]
    :param f:
       log of size of frequency array : constraint: 0 < f <= 31 : 1 means
       default(20)
    :param split_point:
       Percentage of samples used for training: Only used for optimization.
       The first # samples * ``split_point`` samples will be used to training.
       The last # samples * (1 - split_point) samples will be used for testing.
       0 means default (0.75), 1.0 when all samples are used for both training
       and testing.
    :param accel:
       Acceleration level: constraint: 0 < accel <= 10. Higher means faster
       and less accurate, 0 means default(1).
    :param dict_id:
       Integer dictionary ID for the produced dictionary. Default is 0, which uses
       a random value.
    :param steps:
       Number of steps through ``k`` values to perform when trying parameter
       variations.
    :param threads:
       Number of threads to use when trying parameter variations. Default is 0,
       which means to use a single thread. A negative value can be specified to
       use as many threads as there are detected logical CPUs.
    :param level:
       Integer target compression level when trying parameter variations.
    :param notifications:
       Controls writing of informational messages to ``stderr``. ``0`` (the
       default) means to write nothing. ``1`` writes errors. ``2`` writes
       progression info. ``3`` writes more details. And ``4`` writes all info.
    zsamples must be a listr         rs  r   zsize_t[]zsamples must be byteszZDICT_fastCover_params_t *rm   zcannot train dict: %sN)r  r  r  )$r  list	TypeErrorrV   summapr   r  	enumerater  rS   rK   rn  r   r  r  r  steps	nbThreads
splitPointaccelzParamsnotificationLevelr  compressionLevelrL   'ZDICT_optimizeTrainFromBuffer_fastCover	addressofZDICT_isErrorrn   ZDICT_getErrorNamerp   r   r	   r+  rG   )r   samplesr  r  r  split_pointr  notificationsr  r   r  r   
total_sizesamples_buffersample_sizesr\   rj   samplelrz  dparamsrq   msgrT   rT   rU   r   
  s`   
R





	r   c                   @   sN   e Zd ZdZdd Zdd ZdddZed	d
 Zedd Z	edd Z
dS )r   a  A standard library API compatible decompressor.

    This type implements a compressor that conforms to the API by other
    decompressors in Python's standard library. e.g. ``zlib.decompressobj``
    or ``bz2.BZ2Decompressor``. This allows callers to use zstd compression
    while conforming to a similar API.

    Compressed data chunks are fed into ``decompress(data)`` and
    uncompressed output (or an empty bytes) is returned. Output from
    subsequent calls needs to be concatenated to reassemble the full
    decompressed byte sequence.

    If ``read_across_frames=False``, each instance is single use: once an
    input frame is decoded, ``decompress()`` will raise an exception. If
    ``read_across_frames=True``, instances can decode multiple frames.

    >>> dctx = zstandard.ZstdDecompressor()
    >>> dobj = dctx.decompressobj()
    >>> data = dobj.decompress(compressed_chunk_0)
    >>> data = dobj.decompress(compressed_chunk_1)

    By default, calls to ``decompress()`` write output data in chunks of size
    ``DECOMPRESSION_RECOMMENDED_OUTPUT_SIZE``. These chunks are concatenated
    before being returned to the caller. It is possible to define the size of
    these temporary chunks by passing ``write_size`` to ``decompressobj()``:

    >>> dctx = zstandard.ZstdDecompressor()
    >>> dobj = dctx.decompressobj(write_size=1048576)

    .. note::

       Because calls to ``decompress()`` may need to perform multiple
       memory (re)allocations, this streaming decompression API isn't as
       efficient as other APIs.
    c                 C   s"   || _ || _d| _|| _d| _d S )NFr:  )_decompressorr   r9  _read_across_frames_unused_input)r[   decompressorr   read_across_framesrT   rT   rU   r     s
   
zZstdDecompressionObj.__init__c                 C   sJ  | j rtdtd}td}t|}t|dkrdS ||_t||_d|_td| j	}||_
t||_d|_g }	 t| jj||}t|rTtdt| |jrf|t|j
|jd	d	  |dkr}| js}d| _ d	| _||j|j | _n#|dkr| jr|j|jkrnd|_n|j|jkr|j|jk rnd|_q>d|S )
zSend compressed data to the decompressor and obtain decompressed data.

        :param data:
           Data to feed into the decompressor.
        :return:
           Decompressed bytes.
        z)cannot use a decompressobj multiple timesr$  r   r   r:  r   Tzstd decompressor error: %sN)r9  r   rK   r   r&  r   r'  rf   r   r   r   rL   ZSTD_decompressStreamr  _dctxr   rr   r;  r+  r  r  r<  )r[   r,  r/  r0  r.  rj  r>  rq   rT   rT   rU   
decompress  sP   







	
-zZstdDecompressionObj.decompressr   c                 C   r  )zEffectively a no-op.

        Implemented for compatibility with the standard library APIs.

        Safe to call at any time.

        :return:
           Empty bytes.
        r:  rT   )r[   lengthrT   rT   rU   r    s   
zZstdDecompressionObj.flushc                 C   r  )zBytes past the end of compressed data.

        If ``decompress()`` is fed additional data beyond the end of a zstd
        frame, this value will be non-empty once ``decompress()`` fully decodes
        the input frame.
        )r  rZ   rT   rT   rU   unused_data  s   z ZstdDecompressionObj.unused_datac                 C   r  )z5Data that has not yet been fed into the decompressor.r:  rT   rZ   rT   rT   rU   unconsumed_tail  s   z$ZstdDecompressionObj.unconsumed_tailc                 C   r  )z?Whether the end of the compressed data stream has been reached.)r9  rZ   rT   rT   rU   eof  r]   zZstdDecompressionObj.eofN)r   )ra   rb   rc   rd   r   r  r  re   r  r  r  rT   rT   rT   rU   r   ^  s    $
M
	
r   c                   @   s   e Zd ZdZ	d7ddZdd Zdd Zd	d
 Zdd Zdd Z	d8ddZ
d8ddZdd Zdd Zdd Zdd Zdd Zedd Zd d! Zd"d# Zd$d% Zd&d' ZeZd(d) Zd*d+ Zd8d,d-Zd.d/ Zd8d0d1Zd2d3 Zejfd4d5Z d6S )9r   a 
  Read only decompressor that pull uncompressed data from another stream.

    This type provides a read-only stream interface for performing transparent
    decompression from another stream or data source. It conforms to the
    ``io.RawIOBase`` interface. Only methods relevant to reading are
    implemented.

    >>> with open(path, 'rb') as fh:
    >>> dctx = zstandard.ZstdDecompressor()
    >>> reader = dctx.stream_reader(fh)
    >>> while True:
    ...     chunk = reader.read(16384)
    ...     if not chunk:
    ...         break
    ...     # Do something with decompressed chunk.

    The stream can also be used as a context manager:

    >>> with open(path, 'rb') as fh:
    ...     dctx = zstandard.ZstdDecompressor()
    ...     with dctx.stream_reader(fh) as reader:
    ...         ...

    When used as a context manager, the stream is closed and the underlying
    resources are released when the context manager exits. Future operations
    against the stream will fail.

    The ``source`` argument to ``stream_reader()`` can be any object with a
    ``read(size)`` method or any object implementing the *buffer protocol*.

    If the ``source`` is a stream, you can specify how large ``read()`` requests
    to that stream should be via the ``read_size`` argument. It defaults to
    ``zstandard.DECOMPRESSION_RECOMMENDED_INPUT_SIZE``.:

    >>> with open(path, 'rb') as fh:
    ...     dctx = zstandard.ZstdDecompressor()
    ...     # Will perform fh.read(8192) when obtaining data for the decompressor.
    ...     with dctx.stream_reader(fh, read_size=8192) as reader:
    ...         ...

    Instances are *partially* seekable. Absolute and relative positions
    (``SEEK_SET`` and ``SEEK_CUR``) forward of the current position are
    allowed. Offsets behind the current read position and offsets relative
    to the end of stream are not allowed and will raise ``ValueError``
    if attempted.

    ``tell()`` returns the number of decompressed bytes read so far.

    Not all I/O methods are implemented. Notably missing is support for
    ``readline()``, ``readlines()``, and linewise iteration support. This is
    because streams operate on binary data - not text data. If you want to
    convert decompressed output to text, you can chain an ``io.TextIOWrapper``
    to the stream:

    >>> with open(path, 'rb') as fh:
    ...     dctx = zstandard.ZstdDecompressor()
    ...     stream_reader = dctx.stream_reader(fh)
    ...     text_stream = io.TextIOWrapper(stream_reader, encoding='utf-8')
    ...     for line in text_stream:
    ...         ...
    Tc                 C   sZ   || _ || _|| _t|| _t|| _d| _d| _d| _d| _	d| _
td| _d | _d S rF  )r  rG  rH  r   r  r   r   r   _bytes_decompressedrI  rJ  rK   r   rK  rL  )r[   r  r=  rM  r  r   rT   rT   rU   r   7  s   


z ZstdDecompressionReader.__init__c                 C   rN  rO  rP  rZ   rT   rT   rU   r   M  r   z!ZstdDecompressionReader.__enter__c                 C   rQ  r   )r   r  r   rG  r   rT   rT   rU   r   W  rR  z ZstdDecompressionReader.__exit__c                 C   r  r  rT   rZ   rT   rT   rU   r  _  r  z ZstdDecompressionReader.readablec                 C   r  r   rT   rZ   rT   rT   rU   r  b  r  z ZstdDecompressionReader.writablec                 C   r  r   rT   rZ   rT   rT   rU   r  e  r  z ZstdDecompressionReader.seekabler   c                 C   r   rg   r   r  rT   rT   rU   r  h  r   z ZstdDecompressionReader.readlinec                 C   r   rg   r   r  rT   rT   rU   r  k  r   z!ZstdDecompressionReader.readlinesc                 C   r   rg   r   rU  rT   rT   rU   r*  n  r   zZstdDecompressionReader.writec                 C   r   rg   r   r  rT   rT   rU   r  q  r   z"ZstdDecompressionReader.writelinesc                 C   r  r   rT   rZ   rT   rT   rU   r  t  r  zZstdDecompressionReader.isattyc                 C   rW  rg   rT   rZ   rT   rT   rU   r  w  r  zZstdDecompressionReader.flushc                 C   rX  rY  rZ  r  rT   rT   rU   r   z  r[  zZstdDecompressionReader.closec                 C   r  rg   r	  rZ   rT   rT   rU   r
    r_   zZstdDecompressionReader.closedc                 C   r  rg   )r  rZ   rT   rT   rU   r5    rh   zZstdDecompressionReader.tellc                 C   r\  r]  r^  r_  rT   rT   rU   r     ra  zZstdDecompressionReader.readallc                 C   r   rg   r   rZ   rT   rT   rU   r     r   z ZstdDecompressionReader.__iter__c                 C   r   rg   r   rZ   rT   rT   rU   r     r   z ZstdDecompressionReader.__next__c                 C   s   | j j| j jk r
d S | jrd S t| jdr;| j| j}|s#d| _d S t	|| _
| j
| j _t| j
| j _d| j _d S t	| j| _
| j
| j _t| j
| j _d| j _d S rb  )rK  r   rf   rI  rc  rG  r  rH  rK   r&  rL  r'  r   rU  rT   rT   rU   rd    s"   

z#ZstdDecompressionReader._read_inputc                 C   s   t | jj|| j}| jj| jjkr+tj| j_	d| j_d| j_d| _
t| jds+d| _t |r8tdt| |joH|j|jkpH|dkoH| j S )z|Decompress available input into an output buffer.

        Returns True if data in output buffer should be emitted.
        r   Nr  Tzstd decompress error: %s)rL   r  r  r  rK  r   rf   rK   rt   r'  rL  rc  rG  rI  r   r   rr   r  )r[   r0  rq   rT   rT   rU   _decompress_into_buffer  s"   

z/ZstdDecompressionReader._decompress_into_bufferc                 C   s  | j rtd|dk rtd|dkr|  S | js|dkr dS td|}td}||_||_d|_| 	  | 
|rQ|  j|j7  _t|j|jd d  S | jst| 	  | 
|rq|  j|j7  _t|j|jd d  S | jrT|  j|j7  _t|j|jd d  S Nr   r   rh  r   r:  r   r   )r   rS   r   rJ  rK   r   r   rf   r   rd  r  r  r+  rI  r[   rf   rj  r0  rT   rT   rU   r    s2   


zZstdDecompressionReader.readc                 C   s   | j rtd| jrdS t|}t|dd td}||_t||_	d|_
|   | |r<|  j|j
7  _|j
S | jsV|   | |rS|  j|j
7  _|j
S | jr?|  j|j
7  _|j
S Nr   r   r:  r   )r   rS   rJ  rK   r&  rn  r   r   r   rf   r   rd  r  r  rI  r[   r"  rp  r0  rT   rT   rU   r#    s,   




z ZstdDecompressionReader.readintoc                 C   s   | j rtd|dk rtd| js|dkrdS |dkrt}td|}td}||_||_d|_| j	sE| 
  | | |jrBn| j	r5|  j|j7  _t|j|jd d  S r  )r   rS   rJ  r'   rK   r   r   rf   r   rI  rd  r  r  r+  r  rT   rT   rU   rk    s*   

zZstdDecompressionReader.read1c                 C   s   | j rtd| jrdS t|}t|dd td}||_t||_	d|_
| jsA| jsA|   | | |j
r;n| jsA| jr.|  j|j
7  _|j
S r  )r   rS   rJ  rK   r&  rn  r   r   r   rf   r   rI  rd  r  r  r  rT   rT   rU   rq  ;  s$   



z!ZstdDecompressionReader.readinto1c                 C   s   | j rtdd}|tjkr%|dk rtd|| jk rtd|| j }n|tjkr5|dk r2td|}n	|tjkr>td|rV| t	|t
}|sN	 | jS |t|8 }|s@| jS )Nr   r   z.cannot seek to negative position with SEEK_SETz/cannot seek zstd decompression stream backwardsz9zstd decompression streams cannot be seeked with SEEK_END)r   rS   rO   SEEK_SETr  r  SEEK_CURSEEK_ENDr  r  r'   r   )r[   r   r  read_amountr   rT   rT   rU   r  U  s>   




zZstdDecompressionReader.seekNr6  r7  )!ra   rb   rc   rd   r   r   r   r  r  r  r  r  r*  r  r  r  r   re   r
  r5  r   r   r   rr  rd  r  r  r#  rk  rq  rO   r   r  rT   rT   rT   rU   r     s<    D






$
"r   c                   @   s   e Zd ZdZ	d5ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
edd Zdd Zdd Zdd Zdd Zd6ddZd6ddZd7d!d"Zd#d$ Zd%d& Zd7d'd(Zd)d* Zd+d, Zd6d-d.Zd/d0 Zd1d2 Zd3d4 Zd S )8r   a  
    Write-only stream wrapper that performs decompression.

    This type provides a writable stream that performs decompression and writes
    decompressed data to another stream.

    This type implements the ``io.RawIOBase`` interface. Only methods that
    involve writing will do useful things.

    Behavior is similar to :py:meth:`ZstdCompressor.stream_writer`: compressed
    data is sent to the decompressor by calling ``write(data)`` and decompressed
    output is written to the inner stream by calling its ``write(data)``
    method:

    >>> dctx = zstandard.ZstdDecompressor()
    >>> decompressor = dctx.stream_writer(fh)
    >>> # Will call fh.write() with uncompressed data.
    >>> decompressor.write(compressed_data)

    Instances can be used as context managers. However, context managers add no
    extra special behavior other than automatically calling ``close()`` when
    they exit.

    Calling ``close()`` will mark the stream as closed and subsequent I/O
    operations will raise ``ValueError`` (per the documented behavior of
    ``io.RawIOBase``). ``close()`` will also call ``close()`` on the
    underlying stream if such a method exists and the instance was created with
    ``closefd=True``.

    The size of chunks to ``write()`` to the destination can be specified:

    >>> dctx = zstandard.ZstdDecompressor()
    >>> with dctx.stream_writer(fh, write_size=16384) as decompressor:
    >>>    pass

    You can see how much memory is being used by the decompressor:

    >>> dctx = zstandard.ZstdDecompressor()
    >>> with dctx.stream_writer(fh) as decompressor:
    >>>    byte_size = decompressor.memory_size()

    ``stream_writer()`` accepts a ``write_return_read`` boolean argument to control
    the return value of ``write()``. When ``True`` (the default)``, ``write()``
    returns the number of bytes that were read from the input. When ``False``,
    ``write()`` returns the number of bytes that were ``write()`` to the inner
    stream.
    Tc                 C   sD   |   || _|| _|| _t|| _t|| _d| _d| _d| _	d S r   )
_ensure_dctxr  r   r   r   r   r   r   r   r   )r[   r  r   r   r   r   rT   rT   rU   r     s   


z ZstdDecompressionWriter.__init__c                 C   r   r   r   rZ   rT   rT   rU   r     s   z!ZstdDecompressionWriter.__enter__c                 C   s   d| _ |   dS r   )r   r   r   rT   rT   rU   r     s   z ZstdDecompressionWriter.__exit__c                 C   r   rg   r   rZ   rT   rT   rU   r     r   z ZstdDecompressionWriter.__iter__c                 C   r   rg   r   rZ   rT   rT   rU   r     r   z ZstdDecompressionWriter.__next__c                 C   r   rg   )rL   ZSTD_sizeof_DCtxr  r  rZ   rT   rT   rU   r     r   z#ZstdDecompressionWriter.memory_sizec                 C   sb   | j rd S zd| _|   W d| _d| _ nd| _d| _ w t| jdd }| jr-|r/|  d S d S d S r  )r   r   r  r   r   r   r  rT   rT   rU   r     s   


zZstdDecompressionWriter.closec                 C   r  rg   r	  rZ   rT   rT   rU   r
    r_   zZstdDecompressionWriter.closedc                 C   r   r   r  r  rT   rT   rU   r     r  zZstdDecompressionWriter.filenoc                 C   s4   | j rtdt| jdd }|r| js| S d S d S )Nr   r  )r   rS   r   r   r   r  rT   rT   rU   r    s   
zZstdDecompressionWriter.flushc                 C   r  r   rT   rZ   rT   rT   rU   r    r  zZstdDecompressionWriter.isattyc                 C   r  r   rT   rZ   rT   rT   rU   r    r  z ZstdDecompressionWriter.readabler   c                 C   r   rg   r   r  rT   rT   rU   r    r   z ZstdDecompressionWriter.readlinec                 C   r   rg   r   r  rT   rT   rU   r    r   z!ZstdDecompressionWriter.readlinesNc                 C   r   rg   r   r  rT   rT   rU   r    r   zZstdDecompressionWriter.seekc                 C   r  r   rT   rZ   rT   rT   rU   r    r  z ZstdDecompressionWriter.seekablec                 C   r   rg   r   rZ   rT   rT   rU   r5    r   zZstdDecompressionWriter.tellc                 C   r   rg   r   r  rT   rT   rU   r    r   z ZstdDecompressionWriter.truncatec                 C   r  r  rT   rZ   rT   rT   rU   r    r  z ZstdDecompressionWriter.writablec                 C   r   rg   r   r  rT   rT   rU   r    r   z"ZstdDecompressionWriter.writelinesc                 C   r   rg   r   r  rT   rT   rU   r    r   zZstdDecompressionWriter.readc                 C   r   rg   r   rZ   rT   rT   rU   r      r   zZstdDecompressionWriter.readallc                 C   r   rg   r   r!  rT   rT   rU   r#  #  r   z ZstdDecompressionWriter.readintoc           	      C   s   | j rtdd}td}td}t|}||_t||_d|_td| j	}||_
t||_d|_| jj}|j|jk rtt|||}t|rStdt| |jrn| jt|j
|jd d   ||j7 }d|_|j|jk s?| jrz|jS |S )Nr   r   r$  r   r   r  )r   rS   rK   r   r&  r'  r   rf   r   r   r   r  r  rL   r  r   r   rr   r   r*  r+  r   )	r[   r,  r-  r/  r0  r.  rj  dctxrq   rT   rT   rU   r*  &  s<   







zZstdDecompressionWriter.writer6  r7  rg   )ra   rb   rc   rd   r   r   r   r   r   r   r   re   r
  r   r  r  r  r  r  r  r  r5  r  r  r  r  r   r#  r*  rT   rT   rT   rU   r     s8    6






r   c                   @   s   e Zd ZdZddefddZdd Z				dd
dZedd	fddZ	e
dfddZee
dfddZe
d	d	fddZee
fddZdd Z	dddZdddZdS )r   a  
    Context for performing zstandard decompression.

    Each instance is essentially a wrapper around a ``ZSTD_DCtx`` from zstd's
    C API.

    An instance can compress data various ways. Instances can be used multiple
    times.

    The interface of this class is very similar to
    :py:class:`zstandard.ZstdCompressor` (by design).

    Assume that each ``ZstdDecompressor`` instance can only handle a single
    logical compression operation at the same time. i.e. if you call a method
    like ``decompressobj()`` to obtain multiple objects derived from the same
    ``ZstdDecompressor`` instance and attempt to use them simultaneously, errors
    will likely occur.

    If you need to perform multiple logical decompression operations and you
    can't guarantee those operations are temporally non-overlapping, you need
    to obtain multiple ``ZstdDecompressor`` instances.

    Unless specified otherwise, assume that no two methods of
    ``ZstdDecompressor`` instances can be called from multiple Python
    threads simultaneously. In other words, assume instances are not thread safe
    unless stated otherwise.

    :param dict_data:
       Compression dictionary to use.
    :param max_window_size:
       Sets an upper limit on the window size for decompression operations in
       kibibytes. This setting can be used to prevent large memory allocations
       for inputs using large compression windows.
    :param format:
       Set the format of data for the decoder.

       By default this is ``zstandard.FORMAT_ZSTD1``. It can be set to
       ``zstandard.FORMAT_ZSTD1_MAGICLESS`` to allow decoding frames without
       the 4 byte magic header. Not all decompression APIs support this mode.
    Nr   c                 C   sv   || _ || _|| _t }|tjkrt || _z| 	  W tj
|tjt|d| _d S tj
|tjt|d| _w )Nrt  )rw  _max_window_size_formatrL   ZSTD_createDCtxrK   rt   ru   r  r  rv   ZSTD_freeDCtxr  )r[   rz  max_window_sizery   r  rT   rT   rU   r   y  s   


zZstdDecompressor.__init__c                 C   r   )zSize of decompression context, in bytes.

        >>> dctx = zstandard.ZstdDecompressor()
        >>> size = dctx.memory_size()
        )rL   r  r  rZ   rT   rT   rU   r     r  zZstdDecompressor.memory_sizeFTc                 C   sV  |rt d|   t|}t|t|}|tjkr t d|dkr&dS |tjkr<|s1t dt	d|}|}d}nt	d|}|}t	d}	||	_
||	_d|	_t	d}
||
_t||
_d|
_t| j|	|
}t|rwt d	t| |r}t d
|r|	j|krt d||f |s|
j|
jk r|
j|
j }t d| t||	jdd S )a  
        Decompress data in a single operation.

        This method will decompress the input data in a single operation and
        return the decompressed data.

        The input bytes are expected to contain at least 1 full Zstandard frame
        (something compressed with :py:meth:`ZstdCompressor.compress` or
        similar). If the input does not contain a full frame, an exception will
        be raised.

        ``read_across_frames`` controls whether to read multiple zstandard
        frames in the input. When False, decompression stops after reading the
        first frame. This feature is not yet implemented but the argument is
        provided for forward API compatibility when the default is changed to
        True in a future release. For now, if you need to decompress multiple
        frames, use an API like :py:meth:`ZstdCompressor.stream_reader` with
        ``read_across_frames=True``.

        ``allow_extra_data`` controls how to handle extra input data after a
        fully decoded frame. If False, any extra data (which could be a valid
        zstd frame) will result in ``ZstdError`` being raised. If True, extra
        data is silently ignored. The default will likely change to False in a
        future release when ``read_across_frames`` defaults to True.

        If the input contains extra data after a full frame, that extra input
        data is silently ignored. This behavior is undesirable in many scenarios
        and will likely be changed or controllable in a future release (see
        #181).

        If the frame header of the compressed data does not contain the content
        size, ``max_output_size`` must be specified or ``ZstdError`` will be
        raised. An allocation of size ``max_output_size`` will be performed and an
        attempt will be made to perform decompression into that buffer. If the
        buffer is too small or cannot be allocated, ``ZstdError`` will be
        raised. The buffer will be resized if it is too large.

        Uncompressed data could be much larger than compressed data. As a result,
        calling this function could result in a very large memory allocation
        being performed to hold the uncompressed data. This could potentially
        result in ``MemoryError`` or system memory swapping. If you don't need
        the full output data in a single contiguous array in memory, consider
        using streaming decompression for more resilient memory behavior.

        Usage:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> decompressed = dctx.decompress(data)

        If the compressed data doesn't have its content size embedded within it,
        decompression can be attempted by specifying the ``max_output_size``
        argument:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> uncompressed = dctx.decompress(data, max_output_size=1048576)

        Ideally, ``max_output_size`` will be identical to the decompressed
        output size.

        .. important::

           If the exact size of decompressed data is unknown (not passed in
           explicitly and not stored in the zstd frame), for performance
           reasons it is encouraged to use a streaming API.

        :param data:
           Compressed data to decompress.
        :param max_output_size:
           Integer max size of response.

           If ``0``, there is no limit and we can attempt to allocate an output
           buffer of infinite size.
        :return:
           ``bytes`` representing decompressed output.
        z?ZstdDecompressor.read_across_frames=True is not yet implementedz0error determining content size from frame headerr   r:  z0could not determine content size in frame headerr   r   r$  zdecompression error: %sz2decompression error: did not decompress full framez7decompression error: decompressed %d bytes; expected %dzFcompressed input contains %d bytes of unused data, which is disallowedN)r   r  rK   r&  rL   r  r   r  r  r   r   rf   r   r'  r  r  r   rr   r+  )r[   r,  max_output_sizer  allow_extra_datar.  output_sizeresult_bufferresult_sizer0  r/  rq   countrT   rT   rU   r    sh   S






zZstdDecompressor.decompressc                 C   s   |    t| ||||dS )a\  
        Read-only stream wrapper that performs decompression.

        This method obtains an object that conforms to the ``io.RawIOBase``
        interface and performs transparent decompression via ``read()``
        operations. Source data is obtained by calling ``read()`` on a
        source stream or object implementing the buffer protocol.

        See :py:class:`zstandard.ZstdDecompressionReader` for more documentation
        and usage examples.

        :param source:
           Source of compressed data to decompress. Can be any object
           with a ``read(size)`` method or that conforms to the buffer protocol.
        :param read_size:
           Integer number of bytes to read from the source and feed into the
           compressor at a time.
        :param read_across_frames:
           Whether to read data across multiple zstd frames. If False,
           decompression is stopped at frame boundaries.
        :param closefd:
           Whether to close the source stream when this instance is closed.
        :return:
           :py:class:`zstandard.ZstdDecompressionReader`.
        r  )r  r   )r[   r=  rM  r  r   rT   rT   rU   r  &  s    
zZstdDecompressor.stream_readerc                 C   s&   |dk rt d|   t| ||dS )a  Obtain a standard library compatible incremental decompressor.

        See :py:class:`ZstdDecompressionObj` for more documentation
        and usage examples.

        :param write_size: size of internal output buffer to collect decompressed
          chunks in.
        :param read_across_frames: whether to read across multiple zstd frames.
          If False, reading stops after 1 frame and subsequent decompress
          attempts will raise an exception.
        :return:
           :py:class:`zstandard.ZstdDecompressionObj`
        rJ   zwrite_size must be positive)r   r  )rS   r  r   )r[   r   r  rT   rT   rU   decompressobjK  s   zZstdDecompressor.decompressobjc                 c   s   ||kr	t dt|drd}nt|drd}d}t|}nt d|r7|r-|| n
||kr5t d|}|   td	}td
}	td|}
|
|	_t|
|	_d|	_		 |	j	dks^J |rf||}n|| }t
||}||||  }||7 }|sdS t|}||_t||_d|_	|j	|jk r|	j	dksJ t| j|	|}t|rtdt| |	j	rt|	j|	j	dd }d|	_	|V  |dkrdS |j	|jk sqV)a#
  Read compressed data to an iterator of uncompressed chunks.

        This method will read data from ``reader``, feed it to a decompressor,
        and emit ``bytes`` chunks representing the decompressed result.

        >>> dctx = zstandard.ZstdDecompressor()
        >>> for chunk in dctx.read_to_iter(fh):
        ...     # Do something with original data.

        ``read_to_iter()`` accepts an object with a ``read(size)`` method that
        will return compressed bytes or an object conforming to the buffer
        protocol.

        ``read_to_iter()`` returns an iterator whose elements are chunks of the
        decompressed data.

        The size of requested ``read()`` from the source can be specified:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> for chunk in dctx.read_to_iter(fh, read_size=16384):
        ...    pass

        It is also possible to skip leading bytes in the input data:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> for chunk in dctx.read_to_iter(fh, skip_bytes=1):
        ...    pass

        .. tip::

           Skipping leading bytes is useful if the source data contains extra
           *header* data. Traditionally, you would need to create a slice or
           ``memoryview`` of the data you want to decompress. This would create
           overhead. It is more efficient to pass the offset into this API.

        Similarly to :py:meth:`ZstdCompressor.read_to_iter`, the consumer of the
        iterator controls when data is decompressed. If the iterator isn't consumed,
        decompression is put on hold.

        When ``read_to_iter()`` is passed an object conforming to the buffer protocol,
        the behavior may seem similar to what occurs when the simple decompression
        API is used. However, this API works when the decompressed size is unknown.
        Furthermore, if feeding large inputs, the decompressor will work in chunks
        instead of performing a single operation.

        :param reader:
           Source of compressed data. Can be any object with a
           ``read(size)`` method or any object conforming to the buffer
           protocol.
        :param read_size:
           Integer size of data chunks to read from ``reader`` and feed into
           the decompressor.
        :param write_size:
           Integer size of data chunks to emit from iterator.
        :param skip_bytes:
           Integer number of bytes to skip over before sending data into
           the decompressor.
        :return:
           Iterator of ``bytes`` representing uncompressed data.
        z)skip_bytes must be smaller than read_sizer  Trk   Fr   r  z(skip_bytes larger than first input chunkr$  r   r   r  N)rS   rc  r   r  r  rK   r   r   rf   r   r  r&  r'  rL   r  r  r   r   rr   r+  )r[   r  rM  r   
skip_bytesr  r  rf   r/  r0  rj  r  r  r  r  rq   r,  rT   rT   rU   r  e  sp   D










zZstdDecompressor.read_to_iterc                 C   s$   t |ds	tdt| ||||dS )a  
        Push-based stream wrapper that performs decompression.

        This method constructs a stream wrapper that conforms to the
        ``io.RawIOBase`` interface and performs transparent decompression
        when writing to a wrapper stream.

        See :py:class:`zstandard.ZstdDecompressionWriter` for more documentation
        and usage examples.

        :param writer:
           Destination for decompressed output. Can be any object with a
           ``write(data)``.
        :param write_size:
           Integer size of chunks to ``write()`` to ``writer``.
        :param write_return_read:
           Whether ``write()`` should return the number of bytes of input
           consumed. If False, ``write()`` returns the number of bytes sent
           to the inner stream.
        :param closefd:
           Whether to ``close()`` the inner stream when this stream is closed.
        :return:
           :py:class:`zstandard.ZstdDecompressionWriter`
        r*  r  r  )rc  rS   r   )r[   r   r   r   r   rT   rT   rU   r    s   
zZstdDecompressor.stream_writerc                 C   s  t |ds	tdt |dstd|   td}td}td|}||_||_d|_d	\}}		 ||}
|
s@	 ||	fS t	|
}|t
|7 }||_t
||_d|_|j|jk rt| j||}t|rqtdt| |jr|t|j|j |	|j7 }	d|_|j|jk s\q4)a4  
        Copy data between streams, decompressing in the process.

        Compressed data will be read from ``ifh``, decompressed, and written
        to ``ofh``.

        >>> dctx = zstandard.ZstdDecompressor()
        >>> dctx.copy_stream(ifh, ofh)

        e.g. to decompress a file to another file:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> with open(input_path, 'rb') as ifh, open(output_path, 'wb') as ofh:
        ...     dctx.copy_stream(ifh, ofh)

        The size of chunks being ``read()`` and ``write()`` from and to the
        streams can be specified:

        >>> dctx = zstandard.ZstdDecompressor()
        >>> dctx.copy_stream(ifh, ofh, read_size=8192, write_size=16384)

        :param ifh:
           Source stream to read compressed data from.

           Must have a ``read()`` method.
        :param ofh:
           Destination stream to write uncompressed data to.

           Must have a ``write()`` method.
        :param read_size:
           The number of bytes to ``read()`` from the source in a single
           operation.
        :param write_size:
           The number of bytes to ``write()`` to the destination in a single
           operation.
        :return:
           2-tuple of integers representing the number of bytes read and
           written, respectively.
        r  r  r*  r  r$  r   r   r   r   Tr  )rc  rS   r  rK   r   r   rf   r   r  r&  r   r'  rL   r  r  r   r   rr   r*  r+  )r[   r  r  rM  r   r/  r0  rj  r  r-  r,  r.  rq   rT   rT   rU   r  #  sH   
/








zZstdDecompressor.copy_streamc                 C   sv  t |ts	td|std|d }t |tstdt|}td}t	||t
|}t|r8td|r>td|jtjkrHtd| jd	d
 td|j}td}||_t
||_d|_td}||_t
||_d|_t| j||}t|rtdt| |rtdt
|dkrt|t
|dd S d}	|	t
|k r/||	 }t |tstd|	 t|}t	||t
|}t|rtd|	 |rtd|	 |jtjkrtd|	 td|j}
|
|_t
|
|_d|_||_t
||_d|_t| j||}t|rtdt| |r#td|	 |
}|	d7 }	|	t
|k st|t
|dd S )aW  
        Decompress a series of frames using the content dictionary chaining technique.

        Such a list of frames is produced by compressing discrete inputs where
        each non-initial input is compressed with a *prefix* dictionary consisting
        of the content of the previous input.

        For example, say you have the following inputs:

        >>> inputs = [b"input 1", b"input 2", b"input 3"]

        The zstd frame chain consists of:

        1. ``b"input 1"`` compressed in standalone/discrete mode
        2. ``b"input 2"`` compressed using ``b"input 1"`` as a *prefix* dictionary
        3. ``b"input 3"`` compressed using ``b"input 2"`` as a *prefix* dictionary

        Each zstd frame **must** have the content size written.

        The following Python code can be used to produce a *prefix dictionary chain*:

        >>> def make_chain(inputs):
        ...    frames = []
        ...
        ...    # First frame is compressed in standalone/discrete mode.
        ...    zctx = zstandard.ZstdCompressor()
        ...    frames.append(zctx.compress(inputs[0]))
        ...
        ...    # Subsequent frames use the previous fulltext as a prefix dictionary
        ...    for i, raw in enumerate(inputs[1:]):
        ...        dict_data = zstandard.ZstdCompressionDict(
        ...            inputs[i], dict_type=zstandard.DICT_TYPE_RAWCONTENT)
        ...        zctx = zstandard.ZstdCompressor(dict_data=dict_data)
        ...        frames.append(zctx.compress(raw))
        ...
        ...    return frames

        ``decompress_content_dict_chain()`` returns the uncompressed data of the last
        element in the input chain.

        .. note::

           It is possible to implement *prefix dictionary chain* decompression
           on top of other APIs. However, this function will likely be faster -
           especially for long input chains - as it avoids the overhead of
           instantiating and passing around intermediate objects between
           multiple functions.

        :param frames:
           List of ``bytes`` holding compressed zstd frames.
        :return:
        zargument must be a listzempty input chainr   zchunk 0 must be bytesr  z!chunk 0 is not a valid zstd framez,chunk 0 is too small to contain a zstd framez%chunk 0 missing content size in frameF)	load_dictr   r   r$  z could not decompress chunk 0: %sz%chunk 0 did not decompress full framerJ   Nzchunk %d must be bytesz"chunk %d is not a valid zstd framez-chunk %d is too small to contain a zstd framez&chunk %d missing content size in framez!could not decompress chunk %d: %sz&chunk %d did not decompress full frame)r  r  r  rS   r  rK   r&  r   rL   r  r   r   r  r  r  r   rf   r   r'  r  r  r   rr   r+  )r[   framesr`  chunk_bufferr   rq   last_bufferr0  r/  rj   rp  rT   rT   rU   decompress_content_dict_chain  s   
5

















*z.ZstdDecompressor.decompress_content_dict_chainc                 C   rW   )aK  
        Decompress multiple zstd frames to output buffers as a single operation.

        (Experimental. Not available in CFFI backend.)

        Compressed frames can be passed to the function as a
        ``BufferWithSegments``, a ``BufferWithSegmentsCollection``, or as a
        list containing objects that conform to the buffer protocol. For best
        performance, pass a ``BufferWithSegmentsCollection`` or a
        ``BufferWithSegments``, as minimal input validation will be done for
        that type. If calling from Python (as opposed to C), constructing one
        of these instances may add overhead cancelling out the performance
        overhead of validation for list inputs.

        Returns a ``BufferWithSegmentsCollection`` containing the decompressed
        data. All decompressed data is allocated in a single memory buffer. The
        ``BufferWithSegments`` instance tracks which objects are at which offsets
        and their respective lengths.

        >>> dctx = zstandard.ZstdDecompressor()
        >>> results = dctx.multi_decompress_to_buffer([b'...', b'...'])

        The decompressed size of each frame MUST be discoverable. It can either be
        embedded within the zstd frame or passed in via the ``decompressed_sizes``
        argument.

        The ``decompressed_sizes`` argument is an object conforming to the buffer
        protocol which holds an array of 64-bit unsigned integers in the machine's
        native format defining the decompressed sizes of each frame. If this argument
        is passed, it avoids having to scan each frame for its decompressed size.
        This frame scanning can add noticeable overhead in some scenarios.

        >>> frames = [...]
        >>> sizes = struct.pack('=QQQQ', len0, len1, len2, len3)
        >>>
        >>> dctx = zstandard.ZstdDecompressor()
        >>> results = dctx.multi_decompress_to_buffer(frames, decompressed_sizes=sizes)

        .. note::

           It is possible to pass a ``mmap.mmap()`` instance into this function by
           wrapping it with a ``BufferWithSegments`` instance (which will define the
           offsets of frames within the memory mapped region).

        This function is logically equivalent to performing
        :py:meth:`ZstdCompressor.decompress` on each input frame and returning the
        result.

        This function exists to perform decompression on multiple frames as fast
        as possible by having as little overhead as possible. Since decompression is
        performed as a single operation and since the decompressed output is stored in
        a single buffer, extra memory allocations, Python objects, and Python function
        calls are avoided. This is ideal for scenarios where callers know up front that
        they need to access data for multiple frames, such as when  *delta chains* are
        being used.

        Currently, the implementation always spawns multiple threads when requested,
        even if the amount of work to do is small. In the future, it will be smarter
        about avoiding threads and their associated overhead when the amount of
        work to do is small.

        :param frames:
           Source defining zstd frames to decompress.
        :param decompressed_sizes:
           Array of integers representing sizes of decompressed zstd frames.
        :param threads:
           How many threads to use for decompression operations.

           Negative values will use the same number of threads as logical CPUs
           on the machine. Values ``0`` or ``1`` use a single thread.
        :return:
           ``BufferWithSegmentsCollection``
        rX   )r[   r  decompressed_sizesr   rT   rT   rU   multi_decompress_to_buffer  s   Lz+ZstdDecompressor.multi_decompress_to_bufferc                 C   s   t | jt j | jr t | j| j}t |r tdt| t 	| jt j
| j}t |r7tdt| | jrR|rTt | j| jj}t |rVtdt| d S d S d S )Nz!unable to set max window size: %sz!unable to set decoding format: %sz+unable to reference prepared dictionary: %s)rL   ZSTD_DCtx_resetr  r  r  ZSTD_DCtx_setMaxWindowSizer   r   rr   ZSTD_DCtx_setParameterZSTD_d_formatr  rw  ZSTD_DCtx_refDDictr  )r[   r  rq   rT   rT   rU   r  e  s4   





zZstdDecompressor._ensure_dctx)r   FT)Nr   r6  )ra   rb   rc   rd   rH   r   r   r  r&   r  r'   r  r  r  r  r  r  r  rT   rT   rT   rU   r   O  sB    )
 
'

 
.
_ 
Nr   )
r   r   r   r  r   r   r   r   r   r   )rd   
__future__r   r   __all__r   rO   _cffirK   rL   setr   ZSTD_CStreamInSizer$   ZSTD_CStreamOutSizer%   ZSTD_DStreamInSizer&   ZSTD_DStreamOutSizer'   new_allocatorr  ru  r#   ZSTD_MAGICNUMBERr(   r    r  r!   r  r"   ZSTD_VERSION_MAJORZSTD_VERSION_MINORZSTD_VERSION_RELEASEr   ZSTD_BLOCKSIZELOG_MAXr)   ZSTD_BLOCKSIZE_MAXr*   ZSTD_WINDOWLOG_MINr+   ZSTD_WINDOWLOG_MAXr,   ZSTD_CHAINLOG_MINr-   ZSTD_CHAINLOG_MAXr.   ZSTD_HASHLOG_MINr/   ZSTD_HASHLOG_MAXr0   ZSTD_MINMATCH_MINr1   ZSTD_MINMATCH_MAXr2   ZSTD_SEARCHLOG_MINr3   ZSTD_SEARCHLOG_MAXr4   r5   r6   ZSTD_TARGETLENGTH_MINr7   ZSTD_TARGETLENGTH_MAXr8   ZSTD_LDM_MINMATCH_MINr9   ZSTD_LDM_MINMATCH_MAXr:   ZSTD_LDM_BUCKETSIZELOG_MAXr;   	ZSTD_fastr<   
ZSTD_dfastr=   ZSTD_greedyr>   	ZSTD_lazyr?   
ZSTD_lazy2r@   ZSTD_btlazy2rA   
ZSTD_btoptrB   ZSTD_btultrarC   ZSTD_btultra2rD   ZSTD_dct_autorE   ZSTD_dct_rawContentrF   ZSTD_dct_fullDictrG   ZSTD_f_zstd1rH   ZSTD_f_zstd1_magiclessrI   r   r   r   r   rV   r   r   r   r   r  r   rr   r   objectr   r   r   r   r   r
   r   r   r   r   r   r   r   r	   r   r   r   r   r   rT   rT   rT   rU   <module>   s   J6%  		  U 4 5   %     w 1
     
 Q