import Limits
from struct import unpack
from struct import pack

#UNPACKING
#Arrays
def Unpack(string, dtype=Limits.UCHAR_DTYPE):
    return unpack('%d%s' % (len(string) // Limits.GetNumberBytes(dtype), dtype), string)

def UnpackSimple(value, dtype):
    return unpack(dtype, value)[0]

def UnpackComplex(string, dtypes):
    return unpack('%s' % (dtypes), string)
                  

#Little-endian
def UnpackBool(value):
    return unpack(Limits.BOOL_DTYPE, value)[0]

def UnpackSChar(value):
    return unpack(Limits.SCHAR_DTYPE, value)[0]

def UnpackUChar(value):
    return unpack(Limits.UCHAR_DTYPE, value)[0]

def UnpackSShort(value):
    return unpack(Limits.SSHORT_DTYPE, value)[0]

def UnpackUShort(value):
    return unpack(Limits.USHORT_DTYPE, value)[0]

def UnpackSInt(value):
    return unpack(Limits.SINT_DTYPE, value)[0]

def UnpackUInt(value):
    return unpack(Limits.UINT_DTYPE, value)[0]

def UnpackSLongInt(value):
    return unpack(Limits.SLONGINT_DTYPE, value)[0]

def UnpackULongInt(value):
    return unpack(Limits.ULONGINT_DTYPE, value)[0]

def UnpackFloat(value):
    return unpack(Limits.FLOAT_DTYPE, value)[0]

def UnpackDouble(value):
    return unpack(Limits.DOUBLE_DTYPE, value)[0]

#Big-endian
def UnpackBigBool(value):
    return unpack(Limits.BOOL_DTYPE_BIG, value)[0]

def UnpackBigSChar(value):
    return unpack(Limits.SCHAR_DTYPE_BIG, value)[0]

def UnpackBigUChar(value):
    return unpack(Limits.UCHAR_DTYPE_BIG, value)[0]

def UnpackBigSShort(value):
    return unpack(Limits.SSHORT_DTYPE_BIG, value)[0]

def UnpackBigUShort(value):
    return unpack(Limits.USHORT_DTYPE_BIG, value)[0]

def UnpackBigSInt(value):
    return unpack(Limits.SINT_DTYPE_BIG, value)[0]

def UnpackBigUInt(value):
    return unpack(Limits.UINT_DTYPE_BIG, value)[0]

def UnpackBigSLongInt(value):
    return unpack(Limits.SLONGINT_DTYPE_BIG, value)[0]

def UnpackBigULongInt(value):
    return unpack(Limits.ULONGINT_DTYPE_BIG, value)[0]

def UnpackBigFloat(value):
    return unpack(Limits.FLOAT_DTYPE_BIG, value)[0]

def UnpackBigDouble(value):
    return unpack(Limits.DOUBLE_DTYPE_BIG, value)[0]

#PACKING
#Arrays
def Pack(array, dtype=Limits.UCHAR_DTYPE):
    return pack('%d%s' % (len(array) // Limits.GetNumberBytes(dtype), dtype), *array)

def PackSimple(integer, dtype):
    return pack(dtype, integer)

def PackComplex(array, dtypes):
    return pack('%s' % (dtypes), *array)
                  
#Little-endian
def PackBool(value):
    return pack(Limits.BOOL_DTYPE, value)

def PackSChar(value):
    return pack(Limits.SCHAR_DTYPE, value)

def PackUChar(value):
    return pack(Limits.UCHAR_DTYPE, value)

def PackSShort(value):
    return pack(Limits.SSHORT_DTYPE, value)

def PackUShort(value):
    return pack(Limits.USHORT_DTYPE, value)

def PackSInt(value):
    return pack(Limits.SINT_DTYPE, value)

def PackUInt(value):
    return pack(Limits.UINT_DTYPE, value)

def PackSLongInt(value):
    return pack(Limits.SLONGINT_DTYPE, value)

def PackULongInt(value):
    return pack(Limits.ULONGINT_DTYPE, value)

def PackFloat(value):
    return pack(Limits.FLOAT_DTYPE, value)

def PackDouble(value):
    return pack(Limits.DOUBLE_DTYPE, value)

#Big-endian
def PackBigBool(value):
    return pack(Limits.BOOL_DTYPE_BIG, value)

def PackBigSChar(value):
    return pack(Limits.SCHAR_DTYPE_BIG, value)

def PackBigUChar(value):
    return pack(Limits.UCHAR_DTYPE_BIG, value)

def PackBigSShort(value):
    return pack(Limits.SSHORT_DTYPE_BIG, value)

def PackBigUShort(value):
    return pack(Limits.USHORT_DTYPE_BIG, value)

def PackBigSInt(value):
    return pack(Limits.SINT_DTYPE_BIG, value)

def PackBigUInt(value):
    return pack(Limits.UINT_DTYPE_BIG, value)

def PackBigSLongInt(value):
    return pack(Limits.SLONGINT_DTYPE_BIG, value)

def PackBigULongInt(value):
    return pack(Limits.ULONGINT_DTYPE_BIG, value)

def PackBigFloat(value):
    return pack(Limits.FLOAT_DTYPE_BIG, value)

def PackBigDouble(value):
    return pack(Limits.DOUBLE_DTYPE_BIG, value)

