o
    gi$                     @   sL   d Z ddlZddlZddlmZ ddlmZ G dd dZG dd dZdS )	z
This class is the base implementation of a transformer pattern.
It reads bytes from a PDF document, and converts it to JSON-like datastructures.
    N)
AnyPDFType)	Referencec                   @   sB   e Zd ZdZ		ddejejejej	f  deje
 fddZdS )WriteTransformerStateaL  
    This class represents all the meta-information used in the process of persisting a PDF document.
    This includes:
    - the root object (the Document itself)
    - a cache of indirect objects (by id and hash)
    - references that have been resolved (to avoid endless loops)
    - the default compression level
    - etc
    Ndestinationroot_objectc                 C   s.   || _ || _i | _i | _g | _d| _d| _d S )N	   F)r   r   indirect_objects_by_idindirect_objects_by_hashresolved_referencescompression_levelapply_font_subsetting)selfr   r    r   M/home/ubuntu/.local/lib/python3.10/site-packages/borb/io/write/transformer.py__init__   s   
zWriteTransformerState.__init__)NN)__name__
__module____qualname____doc__typingOptionalUnionioBufferedIOBase	RawIOBaser   r   r   r   r   r   r      s    r   c                   @   s   e Zd ZdZdd Zdedeje fddZ	e
dejd	efd
dZdedeje fddZ		 			 dddZdefddZdeded	efddZdddZ	ddedeje fddZdS )Transformerz
    This class represents the base transformer for persisting a PDF Document.
    It allows you to add child BaseWriteTransformer implementations to handle specific cases,
    such as persisting Image objects, or Dictionary objects, etc.
    c                 C   s   g | _ d | _d S N)	_handlers_parent)r   r   r   r   r   B   s   
zTransformer.__init__object_to_transformcontextc                 C   s8   |dusJ d|j dusJ d|j tdd dS )ze
        This function writes the "endobj" bytes whenever a direct object needs to be closed
        NKA WriteTransformerState must be defined in order to write indirect objects.zendobj

latin1)r   writebytes)r   r   r    r   r   r   _end_objectJ   s   
zTransformer._end_objectobjreturnc                 C   sL   d }zt | }W n   Y z|  }W n   Y |d u r$td| jj |S )Nzunhashable type: %s)hash__hash__	TypeError	__class__r   )r&   hr   r   r   _hashY   s   zTransformer._hashc                 C   s   |dusJ d|j dusJ d|j  }| }|dus J t|ts'J ||_|jdus1J |j td|j|j	p<df d dS )z
        This function starts a new direct object by writing
        its reference number followed by "obj" (e.g. "12 0 obj").
        It also does some bookkeeping to ensure the byte offset is stored in the XREF
        Nr!   z
%d %d obj
r   r"   )
r   tellget_reference
isinstancer   byte_offsetobject_numberr#   r$   generation_number)r   r   r    r1   refr   r   r   _start_objectj   s   
zTransformer._start_objecthandlerc                 C   s   | j | | |_| S )a  
        This function adds a BaseWriteTransformer to this WriteBaseTransformer.
        Children of this WriteBaseTransformer will be called in turn, and their
        `can_be_transformed` method should return True if the child WriteBaseTransformer
        can handle the object to be transformed. The first child to return True will have its
        `transform` method called.
        This function returns self.
        )r   appendr   )r   r6   r   r   r   add_child_transformer   s   z!Transformer.add_child_transformerobjectc                 C   s   dS )z
        This function returns True if this WriteBaseTransformer can transform the input object,
        false otherwise
        Fr   )r   r9   r   r   r   can_be_transformed   s   zTransformer.can_be_transformedc                 C   s^  d}z|  }W n   Y t|}||jv r5|j| }t|tr"J | }|dus,J t|ts3J |S | |}|sg||jv rg|j| D ] }||krf| }|dusVJ t|ts]J || |  S qFt	dd dd |j
 D D }	t|	d }
|
|	v r|
d7 }
|
|	v st|
d}|| ||jv r|j| | n|g|j|< ||j|< |S )z
        This function builds a Reference for the input object
        References are re-used whenever possible (hashing is used to detect duplicate objects)
        FNc                 S   s    g | ]}|D ]}|  jqqS r   )r/   r2   ).0sublistitemr   r   r   
<listcomp>   s    z-Transformer.get_reference.<locals>.<listcomp>c                 S   s   g | ]\}}|qS r   r   )r;   kvr   r   r   r>      s       )r2   )	is_uniqueidr   r0   r   r/   r-   r	   set_referencesetitemslenr7   )r   r9   r    rB   obj_idcached_indirect_objectr4   obj_hashr&   existing_obj_numbers
obj_numberr   r   r   r/      sN   







zTransformer.get_referencec                 C   s>   | }|dur|j dur|j }|dur|j dus|dusJ |S )a  
        This function returns the WriteBaseTransformer at the root of this WriteBaseTransformer hierarchy.
        This allows child WriteBaseTransformer implementations to call the root transformer.
        This is useful for instance when transforming a dictionary, where each key/value would then be transformed
        by delegating the call to the root WriteBaseTransformer.
        N)r   )r   pr   r   r   get_root_transformer   s   z Transformer.get_root_transformerNc                 C   s2   d}| j D ]}||r|j||d} |S q|S )z}
        This method writes an object (of type AnyPDFType) to a byte stream (specified in the WriteTransformerState)
        N)r    )r   r:   	transform)r   r   r    return_valuer,   r   r   r   rO      s   	

zTransformer.transform)r6   r   r'   r   )r'   r   r   )r   r   r   r   r   r   r   r   r   r%   staticmethodAnyintr-   r5   r8   r:   r   r/   rN   rO   r   r   r   r   r   7   sF    


$


>r   )r   r   r   borb.io.read.typesr   r   r   r   r   r   r   r   <module>   s   )