
    d@                     0   d dl mZmZmZ d dlmZmZmZ d dlmZm	Z	 d dl
mZmZ  G d de      Z G d de      Z G d	 d
e      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d d e      Z G d! d"e      Z G d# d$e      Z G d% d&e      Z G d' d(e      Z G d) d*e      Z G d+ d,e      Z  G d- d.e       Z! G d/ d0e       Z"y1)2   )AdapterAdaptationErrorPass)
int_to_bin
bin_to_int
swap_bytes)FlagsContainer	HexString)BytesIOdecodebytesc                       e Zd Zg Zy)BitIntegerErrorN__name__
__module____qualname__	__slots__     =/usr/lib/python3/dist-packages/elftools/construct/adapters.pyr   r   
       Ir   r   c                       e Zd Zg Zy)MappingErrorNr   r   r   r   r   r      r   r   r   c                       e Zd Zg Zy)
ConstErrorNr   r   r   r   r   r      r   r   r   c                       e Zd Zg Zy)ValidationErrorNr   r   r   r   r   r      r   r   r   c                       e Zd Zg Zy)PaddingErrorNr   r   r   r   r   r      r   r   r   c                   0    e Zd ZdZg dZ	 	 ddZd Zd Zy)BitIntegerAdaptera  
    Adapter for bit-integers (converts bitstrings to integers, and vice versa).
    See BitField.

    Parameters:
    * subcon - the subcon to adapt
    * width - the size of the subcon, in bits
    * swapped - whether to swap byte order (little endian/big endian).
      default is False (big endian)
    * signed - whether the value is signed (two's complement). the default
      is False (unsigned)
    * bytesize - number of bits per byte, used for byte-swapping (if swapped).
      default is 8.
    )widthswappedsignedbytesizec                 h    t        j                  | |       || _        || _        || _        || _        y N)r   __init__r"   r#   r$   r%   )selfsubconr"   r#   r$   r%   s         r   r(   zBitIntegerAdapter.__init__(   s.    v&
 r   c                     |dk  r| j                   st        d|      t        || j                        }| j                  rt        || j                        }|S )N    z+object is negative, but field is not signed)r"   r%   )r$   r   r   r"   r#   r   r%   )r)   objcontextobj2s       r   _encodezBitIntegerAdapter._encode/   sN    74;;!"O #tzz2<<dt}}=Dr   c                 v    | j                   rt        || j                        }t        || j                        S )Nr-   )r$   )r#   r   r%   r   r$   r)   r.   r/   s      r   _decodezBitIntegerAdapter._decode7   s*    <<ST]];C#44r   N)FF   r   r   r   __doc__r   r(   r1   r4   r   r   r   r!   r!      s#     ;I@E!5r   r!   c                   0    e Zd ZdZg dZeefdZd Zd Zy)MappingAdaptera  
    Adapter that maps objects to other objects.
    See SymmetricMapping and Enum.

    Parameters:
    * subcon - the subcon to map
    * decoding - the decoding (parsing) mapping (a dict)
    * encoding - the encoding (building) mapping (a dict)
    * decdefault - the default return value when the object is not found
      in the decoding mapping. if no object is given, an exception is raised.
      if `Pass` is used, the unmapped object will be passed as-is
    * encdefault - the default return value when the object is not found
      in the encoding mapping. if no object is given, an exception is raised.
      if `Pass` is used, the unmapped object will be passed as-is
    )encodingdecoding
encdefault
decdefaultc                 h    t        j                  | |       || _        || _        || _        || _        y r'   )r   r(   r;   r:   r=   r<   )r)   r*   r;   r:   r=   r<   s         r   r(   zMappingAdapter.__init__M   s.    v&  $$r   c                     	 | j                   |   S # t        t        f$ r] | j                  t        u r&t        d|d| j                  j                  d      | j                  t        u r|cY S | j                  cY S w xY w)Nzno encoding mapping for  [])	r:   KeyError	TypeErrorr<   NotImplementedr   r*   namer   r3   s      r   r1   zMappingAdapter._encodeT   r    	#==%%)$ 	#.0"))$+ , ,$&
??"	#    AA=.A=<A=c                     	 | j                   |   S # t        t        f$ r] | j                  t        u r&t        d|d| j                  j                  d      | j                  t        u r|cY S | j                  cY S w xY w)Nzno decoding mapping for r@   rA   )	r;   rB   rC   r=   rD   r   r*   rE   r   r3   s      r   r4   zMappingAdapter._decode^   rF   rG   N)	r   r   r   r7   r   rD   r(   r1   r4   r   r   r   r9   r9   <   s#     EI,>%	#	#r   r9   c                   (    e Zd ZdZdgZd Zd Zd Zy)FlagsAdaptera  
    Adapter for flag fields. Each flag is extracted from the number, resulting
    in a FlagsContainer object. Not intended for direct usage.
    See FlagsEnum.

    Parameters
    * subcon - the subcon to extract
    * flags - a dictionary mapping flag-names to their value
    flagsc                 >    t        j                  | |       || _        y r'   )r   r(   rK   )r)   r*   rK   s      r   r(   zFlagsAdapter.__init__t       v&
r   c                 t    d}| j                   j                         D ]  \  }}t        ||d      s||z  } |S )Nr,   F)rK   itemsgetattr)r)   r.   r/   rK   rE   values         r   r1   zFlagsAdapter._encodew   sC    ::++- 	KD%sD%(	 r   c           	          t               }| j                  j                         D ]  \  }}t        ||t	        ||z                 |S r'   )r	   rK   rO   setattrbool)r)   r.   r/   r0   rE   rQ   s         r   r4   zFlagsAdapter._decode}   sD    ::++- 	3KD%D$S5[ 12	3r   Nr6   r   r   r   rJ   rJ   i   s     	Ir   rJ   c                   *    e Zd ZdZdgZddZd Zd Zy)StringAdapteraA  
    Adapter for strings. Converts a sequence of characters into a python
    string, and optionally handles character encoding.
    See String.

    Parameters:
    * subcon - the subcon to convert
    * encoding - the character encoding name (e.g., "utf8"), or None to
      return raw bytes (usually 8-bit ASCII).
    r:   Nc                 >    t        j                  | |       || _        y r'   )r   r(   r:   )r)   r*   r:   s      r   r(   zStringAdapter.__init__       v& r   c                 T    | j                   r|j                  | j                         }|S r'   )r:   encoder3   s      r   r1   zStringAdapter._encode        ==**T]]+C
r   c                 T    | j                   r|j                  | j                         }|S r'   )r:   decoder3   s      r   r4   zStringAdapter._decode   r[   r   r'   r6   r   r   r   rV   rV      s    	 I!r   rV   c                   0    e Zd ZdZg dZ	 	 ddZd Zd Zy)PaddedStringAdaptera  
    Adapter for padded strings.
    See String.

    Parameters:
    * subcon - the subcon to adapt
    * padchar - the padding character. default is b"\x00".
    * paddir - the direction where padding is placed ("right", "left", or
      "center"). the default is "right".
    * trimdir - the direction where trimming will take place ("right" or
      "left"). the default is "right". trimming is only meaningful for
      building, when the given string is too long.
    )padcharpaddirtrimdirc                     |dvrt        d|      |dvrt        d|      t        j                  | |       || _        || _        || _        y )N)rightleftcenterz*paddir must be 'right', 'left' or 'center')rd   re   z!trimdir must be 'right' or 'left')
ValueErrorr   r(   r`   ra   rb   )r)   r*   r`   ra   rb   s        r   r(   zPaddedStringAdapter.__init__   sZ    44I ++@'JJv&r   c                     | j                   dk(  r|j                  | j                        }|S | j                   dk(  r|j                  | j                        }|S |j	                  | j                        }|S Nrd   re   )ra   rstripr`   lstripstripr3   s      r   r4   zPaddedStringAdapter._decode   sg    ;;'!**T\\*C
 
	 [[F"**T\\*C 
 ))DLL)C
r   c                 d   | j                  |      }| j                  dk(  r|j                  || j                        }nH| j                  dk(  r|j	                  || j                        }n|j                  || j                        }t        |      |kD  r| j                  dk(  r|d | }|S || d  }|S ri   )_sizeofra   ljustr`   rjustrf   lenrb   )r)   r.   r/   sizes       r   r1   zPaddedStringAdapter._encode   s    ||G$;;'!))D$,,/C[[F"))D$,,/C**T4<<0Cs8d?||w&%4j 
 4%&k
r   N)    rd   rd   r   r   r   r7   r   r(   r4   r1   r   r   r   r_   r_      s#     1I;B"
r   r_   c                        e Zd ZdZg Zd Zd Zy)LengthValueAdapterz
    Adapter for length-value pairs. It extracts only the value from the
    pair, and calculates the length based on the value.
    See PrefixedArray and PascalString.

    Parameters:
    * subcon - the subcon returning a length-value pair
    c                     t        |      |fS r'   )rq   r3   s      r   r1   zLengthValueAdapter._encode   s    C#r   c                     |d   S )Nr   r   r3   s      r   r4   zLengthValueAdapter._decode   s    1vr   N)r   r   r   r7   r   r1   r4   r   r   r   rv   rv      s     Ir   rv   c                   *    e Zd ZdZdgZddZd Zd Zy)CStringAdapterar  
    Adapter for C-style strings (strings terminated by a terminator char).

    Parameters:
    * subcon - the subcon to convert
    * terminators - a sequence of terminator chars. default is b"\x00".
    * encoding - the character encoding to use (e.g., "utf8"), or None to
      return raw-bytes. the terminator characters are not affected by the
      encoding.
    terminatorsNc                 B    t         j                  | ||       || _        y )N)r:   )rV   r(   r{   )r)   r*   r{   r:   s       r   r(   zCStringAdapter.__init__   s    tVA&r   c                 P    t         j                  | ||      | j                  dd z   S )Nr,   r   )rV   r1   r{   r3   s      r   r1   zCStringAdapter._encode   s)    $$T384;K;KAa;PPPr   c                 T    t         j                  | dj                  |d d       |      S )Nr   )rV   r4   joinr3   s      r   r4   zCStringAdapter._decode   s&    $$T388CH+=wGGr   )rs   Nr6   r   r   r   rz   rz      s!    	 I'QHr   rz   c                   (    e Zd ZdZdgZd Zd Zd Zy)TunnelAdapteraC  
    Adapter for tunneling (as in protocol tunneling). A tunnel is construct
    nested upon another (layering). For parsing, the lower layer first parses
    the data (note: it must return a string!), then the upper layer is called
    to parse that data (bottom-up). For building it works in a top-down manner;
    first the upper layer builds the data, then the lower layer takes it and
    writes it to the stream.

    Parameters:
    * subcon - the lower layer subcon
    * inner_subcon - the upper layer (tunneled/nested) subcon

    Example:
    # a pascal string containing compressed data (zlib encoding), so first
    # the string is read, decompressed, and finally re-parsed as an array
    # of UBInt16
    TunnelAdapter(
        PascalString("data", encoding = "zlib"),
        GreedyRange(UBInt16("elements"))
    )
    inner_subconc                 >    t        j                  | |       || _        y r'   )r   r(   r   )r)   r*   r   s      r   r(   zTunnelAdapter.__init__  s    v&(r   c                 L    | j                   j                  t        |      |      S r'   )r   _parser   r3   s      r   r4   zTunnelAdapter._decode	  s      ''g>>r   c                 p    t               }| j                  j                  |||       |j                         S r'   )r   r   _buildgetvalue)r)   r.   r/   streams       r   r1   zTunnelAdapter._encode  s.      fg6  r   Nrt   r   r   r   r   r      s     *   I)?!r   r   c                       e Zd ZdZddgZd Zy)ExprAdaptera>  
    A generic adapter that accepts 'encoder' and 'decoder' as parameters. You
    can use ExprAdapter instead of writing a full-blown class when only a
    simple expression is needed.

    Parameters:
    * subcon - the subcon to adapt
    * encoder - a function that takes (obj, context) and returns an encoded
      version of obj
    * decoder - a function that takes (obj, context) and returns a decoded
      version of obj

    Example:
    ExprAdapter(UBInt8("foo"),
        encoder = lambda obj, ctx: obj / 4,
        decoder = lambda obj, ctx: obj * 4,
    )
    r1   r4   c                 L    t        j                  | |       || _        || _        y r'   )r   r(   r1   r4   )r)   r*   encoderdecoders       r   r(   zExprAdapter.__init__$  s     v&r   N)r   r   r   r7   r   r(   r   r   r   r   r     s    $ I&Ir   r   c                   *    e Zd ZdZdgZddZd Zd Zy)HexDumpAdapterzT
    Adapter for hex-dumping strings. It returns a HexString, which is a string
    linesizec                 >    t        j                  | |       || _        y r'   )r   r(   r   )r)   r*   r   s      r   r(   zHexDumpAdapter.__init__.  rX   r   c                     |S r'   r   r3   s      r   r1   zHexDumpAdapter._encode1  s    
r   c                 0    t        || j                        S )N)r   )r
   r   r3   s      r   r4   zHexDumpAdapter._decode3  s    77r   N)   r6   r   r   r   r   r   )  s     I!8r   r   c                   (    e Zd ZdZdgZd Zd Zd Zy)ConstAdaptera,  
    Adapter for enforcing a constant value ("magic numbers"). When decoding,
    the return value is checked; when building, the value is substituted in.

    Parameters:
    * subcon - the subcon to validate
    * value - the expected value

    Example:
    Const(Field("signature", 2), "MZ")
    rQ   c                 >    t        j                  | |       || _        y r'   )r   r(   rQ   )r)   r*   rQ   s      r   r(   zConstAdapter.__init__C  rM   r   c                 r    ||| j                   k(  r| j                   S t        d| j                   d|      Nz	expected z, found rQ   r   r3   s      r   r1   zConstAdapter._encodeF  s0    ;#+::

CHIIr   c                 Z    || j                   k7  rt        d| j                   d|      |S r   r   r3   s      r   r4   zConstAdapter._decodeK  s'    $**

CHII
r   Nr6   r   r   r   r   r   6  s     
 	IJ
r   r   c                   ,    e Zd ZdZg dZddZd Zd Zy)SlicingAdapterz
    Adapter for slicing a list (getting a slice from that list)

    Parameters:
    * subcon - the subcon to slice
    * start - start index
    * stop - stop index (or None for up-to-end)
    * step - step (or None for every element)
    )startstopstepNc                 L    t        j                  | |       || _        || _        y r'   )r   r(   r   r   )r)   r*   r   r   s       r   r(   zSlicingAdapter.__init__[  s     v&
	r   c                 D    | j                   |S d g| j                   z  |z   S r'   )r   r3   s      r   r1   zSlicingAdapter._encode_  s'    ::Jv

"S((r   c                 4    || j                   | j                   S r'   )r   r   r3   s      r   r4   zSlicingAdapter._decodec  s    4::dii((r   r'   r6   r   r   r   r   r   P  s     *I))r   r   c                   (    e Zd ZdZdgZd Zd Zd Zy)IndexingAdapterz
    Adapter for indexing a list (getting a single item from that list)

    Parameters:
    * subcon - the subcon to index
    * index - the index of the list to get
    indexc                     t        j                  | |       t        |      t        urt	        dt        |            || _        y )Nzindex must be an integer)r   r(   typeintrC   r   )r)   r*   r   s      r   r(   zIndexingAdapter.__init__o  s7    v&;c!6UDD
r   c                 *    d g| j                   z  |gz   S r'   r   r3   s      r   r1   zIndexingAdapter._encodet  s    v

"cU**r   c                      || j                      S r'   r   r3   s      r   r4   zIndexingAdapter._decodev  s    4::r   Nr6   r   r   r   r   r   f  s     	I
+r   r   c                   ,    e Zd ZdZddgZddZd Zd Zy)	PaddingAdaptera+  
    Adapter for padding.

    Parameters:
    * subcon - the subcon to pad
    * pattern - the padding pattern (character as byte). default is b"\x00"
    * strict - whether or not to verify, during parsing, that the given
      padding matches the padding pattern. default is False (unstrict)
    patternstrictc                 L    t        j                  | |       || _        || _        y r'   )r   r(   r   r   )r)   r*   r   r   s       r   r(   zPaddingAdapter.__init__  s     v&r   c                 >    | j                  |      | j                  z  S r'   )rn   r   r3   s      r   r1   zPaddingAdapter._encode  s    ||G$t||33r   c                     | j                   r4| j                  |      | j                  z  }||k7  rt        d|d|      |S r   )r   rn   r   r   )r)   r.   r/   expecteds       r   r4   zPaddingAdapter._decode  s<    ;;||G,t||;Hh"h#LMM
r   N)rs   Fr6   r   r   r   r   r   y  s"     H%I4r   r   c                   &    e Zd ZdZg Zd Zd Zd Zy)	Validatorz
    Abstract class: validates a condition on the encoded/decoded object.
    Override _validate(obj, context) in deriving classes.

    Parameters:
    * subcon - the subcon to validate
    c                 B    | j                  ||      st        d|      |S )Nzinvalid object)	_validater   r3   s      r   r4   zValidator._decode  s#    ~~c7+!"2C88
r   c                 &    | j                  ||      S r'   )r4   r3   s      r   r1   zValidator._encode  s    ||C))r   c                     t               r'   )NotImplementedErrorr3   s      r   r   zValidator._validate  s    !##r   N)r   r   r   r7   r   r4   r1   r   r   r   r   r   r     s     I*$r   r   c                   "    e Zd ZdZdgZd Zd Zy)OneOfai  
    Validates that the object is one of the listed values.

    :param ``Construct`` subcon: object to validate
    :param iterable valids: a set of valid values

    >>> OneOf(UBInt8("foo"), [4,5,6,7]).parse("\x05")
    5
    >>> OneOf(UBInt8("foo"), [4,5,6,7]).parse("\x08")
    Traceback (most recent call last):
        ...
    construct.core.ValidationError: ('invalid object', 8)
    >>>
    >>> OneOf(UBInt8("foo"), [4,5,6,7]).build(5)
    '\x05'
    >>> OneOf(UBInt8("foo"), [4,5,6,7]).build(9)
    Traceback (most recent call last):
        ...
    construct.core.ValidationError: ('invalid object', 9)
    validsc                 >    t         j                  | |       || _        y r'   )r   r(   r   )r)   r*   r   s      r   r(   zOneOf.__init__  s    4(r   c                     || j                   v S r'   )r   r3   s      r   r   zOneOf._validate  s    dkk!!r   Nr   r   r   r7   r   r(   r   r   r   r   r   r     s    ( 
I"r   r   c                   "    e Zd ZdZdgZd Zd Zy)NoneOfa  
    Validates that the object is none of the listed values.

    :param ``Construct`` subcon: object to validate
    :param iterable invalids: a set of invalid values

    >>> NoneOf(UBInt8("foo"), [4,5,6,7]).parse("\x08")
    8
    >>> NoneOf(UBInt8("foo"), [4,5,6,7]).parse("\x06")
    Traceback (most recent call last):
        ...
    construct.core.ValidationError: ('invalid object', 6)
    invalidsc                 >    t         j                  | |       || _        y r'   )r   r(   r   )r)   r*   r   s      r   r(   zNoneOf.__init__  s    4( r   c                     || j                   vS r'   )r   r3   s      r   r   zNoneOf._validate  s    $--''r   Nr   r   r   r   r   r     s     I!(r   r   N)#corer   r   r   libr   r   r   r	   r
   lib.py3compatr   r   r   r   r   r   r   r!   r9   rJ   rV   r_   rv   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s%   0 0 3 3 * /o ?  o ? "5 "5H+#W +#Z7 4G 0/' /b H] H(!G !B' 28W 87 4)W ),g &W 8$ $$"I "8(Y (r   