o
    µ+ke«  ã                   @   s<   d dl mZ G dd„ deƒZG dd„ dƒZG dd„ dƒZdS )	é   )ÚErrorc                       s    e Zd ZdZ‡ fdd„Z‡  ZS )Ú
StableDictz,A dict subclass with stable items() orderingc                    s   t tƒ  ¡ ƒS ©N)ÚsortedÚsuperÚitems©Úself©Ú	__class__© ú;usr/lib/python3.10/site-packages/borg/helpers/datastruct.pyr      s   zStableDict.items)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__classcell__r   r   r
   r   r      s    r   c                   @   sH   e Zd ZdZG dd„ deeƒZddd„Zdd	„ Zddd„Z	ddd„Z
dS )ÚBufferz/
    Provides a managed, resizable buffer.
    c                   @   ó   e Zd ZdZdS )zBuffer.MemoryLimitExceededz2Requested buffer size {} is above the limit of {}.N©r   r   r   r   r   r   r   r   ÚMemoryLimitExceeded   ó    r   é   Nc                 C   sF   t |ƒsJ dƒ‚|du s||ksJ dƒ‚|| _|| _| j|dd dS )z–
        Initialize the buffer: use allocator(size) call to allocate a buffer.
        Optionally, set the upper <limit> for the buffer size.
        z-must give alloc(size) function as first paramNzinitial size must be <= limitT)Úinit)ÚcallableÚ	allocatorÚlimitÚresize)r	   r   Úsizer   r   r   r   Ú__init__   s
   zBuffer.__init__c                 C   s
   t | jƒS r   )ÚlenÚbufferr   r   r   r   Ú__len__   s   
zBuffer.__len__Fc                 C   sN   t |ƒ}| jdur|| jkrt || j¡‚|st| ƒ|k r%|  |¡| _dS dS )a$  
        resize the buffer - to avoid frequent reallocation, we usually always grow (if needed).
        giving init=True it is possible to first-time initialize or shrink the buffer.
        if a buffer size beyond the limit is requested, raise Buffer.MemoryLimitExceeded (OSError).
        N)Úintr   r   r   r    r   r!   ©r	   r   r   r   r   r   r       s   ÿzBuffer.resizec                 C   s   |dur
|   ||¡ | jS )z¯
        return a buffer of at least the requested size (None: any current size).
        init=True can be given to trigger shrinking of the buffer to the given size.
        N)r   r!   r$   r   r   r   Úget,   s   z
Buffer.get)r   N)F)NF)r   r   r   r   r   ÚOSErrorr   r   r"   r   r%   r   r   r   r   r   
   s    

r   c                   @   sP   e Zd ZdZG dd„ deƒZdd„ Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dd„ ZdS )ÚEfficientCollectionQueuezL
    An efficient FIFO queue that splits received elements into chunks.
    c                   @   r   )z&EfficientCollectionQueue.SizeUnderflowzHCould not pop_front first {} elements, collection only has {} elements..Nr   r   r   r   r   ÚSizeUnderflow;   r   r(   c                 C   s   g | _ d| _|| _|| _dS )z¶
        Initializes empty queue.
        Requires split_size to define maximum chunk size.
        Requires member_type to be type defining what base collection looks like.
        é    N)Úbuffersr   Ú
split_sizeÚmember_type)r	   r+   r,   r   r   r   r   >   s   
z!EfficientCollectionQueue.__init__c                 C   s   | j s|  ¡ S | j d }|S )zÅ
        Returns first chunk from queue without removing it.
        Returned collection will have between 1 and split_size length.
        Returns empty collection when nothing is queued.
        r)   )r*   r,   )r	   r!   r   r   r   Ú
peek_frontI   s   
z#EfficientCollectionQueue.peek_frontc                 C   s‚   || j krt || j ¡‚|dkr?| jd }t|t|ƒƒ}||d… }|r*|| jd< n| jd= ||8 }|  j |8  _ |dksdS dS )z~
        Removes first size elements from queue.
        Throws if requested removal size is larger than whole queue.
        r)   N)r   r'   r(   r*   Úminr    )r	   r   r!   Ú	to_remover   r   r   Ú	pop_frontT   s   

÷z"EfficientCollectionQueue.pop_frontc                 C   sš   | j s	|  ¡ g| _ |rK| j d }t|ƒ| jkr!|  ¡ }| j  |¡ tt|ƒ| jt|ƒ ƒ}||d|… 7 }||d… }|| j d< |  j|7  _|sdS dS )zm
        Adds data at end of queue.
        Takes care to chunk data into split_size sized elements.
        éÿÿÿÿN)r*   r,   r    r+   Úappendr.   r   )r	   Údatar!   Zto_addr   r   r   Ú	push_backf   s   

öz"EfficientCollectionQueue.push_backc                 C   s   | j S )zF
        Current queue length for all elements in all chunks.
        ©r   r   r   r   r   r"   y   s   z EfficientCollectionQueue.__len__c                 C   s
   | j dkS )z4
        Returns true if queue isn't empty.
        r)   r5   r   r   r   r   Ú__bool__   s   
z!EfficientCollectionQueue.__bool__N)r   r   r   r   r   r(   r   r-   r0   r4   r"   r6   r   r   r   r   r'   6   s    r'   N)Úerrorsr   Údictr   r   r'   r   r   r   r   Ú<module>   s    ,