U
    Cvf                     @  s   d Z ddlmZ ddlmZ ddlZddlmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZ ddlmZ d	d
 Zdd Zdd Zdd ZG dd deZd&ddZd'ddZdd ZG dd deZdd Zdd Zd d! Zd"d# Z G d$d% d%ej!Z"dS )(zCoders for strings.    )annotations)partialN)VariableCoderlazy_elemwise_funcpop_tosafe_setitemunpack_for_decodingunpack_for_encoding)indexing)is_duck_dask_array)Variablec                 C  s,   | t tfkrtd| tjdd| idS )Nz!unsupported type for vlen_dtype: Oelement_type)metadata)strbytes	TypeErrornpdtype)r    r   9/tmp/pip-unpacked-wheel-h316xyqg/xarray/coding/strings.pycreate_vlen_dtype   s    r   c                 C  s(   | j dks| jd krd S | jdS d S )Nr   r   )kindr   getr   r   r   r   check_vlen_dtype   s    r   c                 C  s   | j dkpt| tkS )NU)r   r   r   r   r   r   r   is_unicode_dtype#   s    r   c                 C  s   | j dkpt| tkS )NS)r   r   r   r   r   r   r   is_bytes_dtype'   s    r   c                   @  s.   e Zd ZdZd
ddZdddZddd	ZdS )EncodedStringCoderz?Transforms between unicode strings and fixed-width UTF-8 bytes.Tc                 C  s
   || _ d S )N)allows_unicode)selfr!   r   r   r   __init__.   s    zEncodedStringCoder.__init__Nc           
      C  s   t |\}}}}t|j}|ddk}|r2|d= |r||s@| js|d|krVtd||dd}	t|d|	|d t	||	}t
||||S )Nr   S1Z
_FillValuezvariable {!r} has a _FillValue specified, but _FillValue is not yet supported on unicode strings: https://github.com/pydata/xarray/issues/1647	_Encodingutf-8)name)r	   r   r   r   r!   NotImplementedErrorformatpopr   encode_string_arrayr   )
r"   variabler'   dimsdataattrsencodingZcontains_unicodeZencode_as_charstring_encodingr   r   r   encode1   s     

zEncodedStringCoder.encodec           	      C  sP   t |\}}}}d|krBt||d}tt|d}t||tt}t||||S )Nr%   r0   )	r   r   r   decode_bytes_arrayr   r   r   objectr   )	r"   r,   r'   r-   r.   r/   r0   r1   funcr   r   r   decodeI   s    zEncodedStringCoder.decode)T)N)N)__name__
__module____qualname____doc__r#   r2   r7   r   r   r   r   r    +   s   

r    r&   c                   s6   t | }  fdd|  D }t j|td| jS )Nc                   s   g | ]}|  qS r   )r7   .0xr3   r   r   
<listcomp>W   s     z&decode_bytes_array.<locals>.<listcomp>r   )r   asarrayravelarrayr5   reshapeshape)Zbytes_arrayr0   decodedr   r3   r   r4   T   s    
r4   c                   s6   t | }  fdd|  D }t j|td| jS )Nc                   s   g | ]}|  qS r   )r2   r<   r3   r   r   r?   ]   s     z'encode_string_array.<locals>.<listcomp>r   )r   r@   rA   rB   r   rC   rD   )Zstring_arrayr0   encodedr   r3   r   r+   [   s    
r+   c                 C  s<   t | \}}}}t|jtkr.tj|tjd}t||||S )zCEnsure that a variable with vlen bytes is converted to fixed width.r   )r	   r   r   r   r   r@   string_r   )varr-   r.   r/   r0   r   r   r   ensure_fixed_length_bytesa   s    rI   c                   @  s$   e Zd ZdZdddZdddZdS )	CharacterArrayCoderz@Transforms between arrays containing bytes and character arrays.Nc                 C  sz   t |}t|\}}}}|jjdkrl|dtk	rlt|}d| krR|d}nd|j	d  }||f }t
||||S )Nr   r   char_dim_namestring)rI   r	   r   r   r   r   bytes_to_charkeysr*   rD   r   )r"   r,   r'   r-   r.   r/   r0   rK   r   r   r   r2   m   s    
zCharacterArrayCoder.encodec                 C  sL   t |\}}}}|jdkr>|r>|d |d< |d d }t|}t||||S )Nr$   rM   rK   )r   r   char_to_bytesr   )r"   r,   r'   r-   r.   r/   r0   r   r   r   r7   z   s    zCharacterArrayCoder.decode)N)N)r8   r9   r:   r;   r2   r7   r   r   r   r   rJ   j   s   
rJ   c                 C  sT   | j jdkrtdt| rLddlm} |jt| d| j| j j	f | j
gdS t| S )z?Convert numpy/dask arrays from fixed width bytes to characters.r   z,argument must have a fixed-width bytes dtyper   Nr$   )r   chunksZnew_axis)r   r   
ValueErrorr   
dask.arrayrB   
map_blocks_numpy_bytes_to_charrQ   itemsizendim)arrdar   r   r   rN      s    rN   c                 C  s*   t j| ddt jd} | | jd dS )z8Like netCDF4.stringtochar, but faster and more flexible.FC)copyorderr   )   r$   )r   rB   rG   rC   rD   view)rX   r   r   r   rU      s    rU   c                 C  s   | j dkrtd| js| S | jd }|sDtj| jdd tjdS t| rddlm	} t
| jd dkrxtd| t d	t| jd  }|jt| || jdd | jd gd
S t| S dS )z?Convert numpy/dask arrays from characters to fixed width bytes.r$   zargument must have dtype='S1'rM   Nr   r   r]   zRcannot stacked dask character array with multiple chunks in the last dimension: {}r   )r   rQ   Z	drop_axis)r   rR   rW   rD   r   zerosrG   r   rS   rB   lenrQ   r)   r   rT   _numpy_char_to_bytesStackedBytesArray)rX   sizerY   r   r   r   r   rP      s0    


rP   c                 C  s<   t j| ddd} dt| jd  }| || jdd S )z8Like netCDF4.chartostring, but faster and more flexible.FrZ   )r[   r\   r   rM   N)r   rB   r   rD   r^   rC   )rX   r   r   r   r   ra      s    ra   c                   @  sF   e Zd ZdZdd Zedd Zedddd	Zd
d Zdd Z	dS )rb   a>  Wrapper around array-like objects to create a new indexable object where
    values, when accessed, are automatically stacked along the last dimension.

    >>> indexer = indexing.BasicIndexer((slice(None),))
    >>> StackedBytesArray(np.array(["a", "b", "c"], dtype="S1"))[indexer]
    array(b'abc', dtype='|S3')
    c                 C  s"   |j dkrtdt|| _dS )zx
        Parameters
        ----------
        array : array-like
            Original array of values to wrap.
        r$   z9can only use StackedBytesArray if argument has dtype='S1'N)r   rR   r
   Zas_indexablerB   )r"   rB   r   r   r   r#      s
    
zStackedBytesArray.__init__c                 C  s   t dt| jjd  S )Nr   rM   )r   r   r   rB   rD   r"   r   r   r   r      s    zStackedBytesArray.dtypeztuple[int, ...])returnc                 C  s   | j jd d S )NrM   )rB   rD   rd   r   r   r   rD      s    zStackedBytesArray.shapec                 C  s   t | j d| jdS )N())typer8   rB   rd   r   r   r   __repr__   s    zStackedBytesArray.__repr__c                 C  sB   t |t|j| jj}|jd td kr4tdt| j| S )NrM   ztoo many indices)	rh   r
   Zexpanded_indexertuplerB   rW   slice
IndexErrorra   )r"   keyr   r   r   __getitem__   s    zStackedBytesArray.__getitem__N)
r8   r9   r:   r;   r#   propertyr   rD   ri   rn   r   r   r   r   rb      s   
rb   )r&   )r&   )#r;   
__future__r   	functoolsr   Znumpyr   Zxarray.coding.variablesr   r   r   r   r   r	   Zxarray.corer
   Zxarray.core.pycompatr   Zxarray.core.variabler   r   r   r   r   r    r4   r+   rI   rJ   rN   rU   rP   ra   ZExplicitlyIndexedNDArrayMixinrb   r   r   r   r   <module>   s*    )

	$