##
# @file   comm_packing.py
# @brief  packing and unpacking functions
#
# @copyright
#
# @addtogroup
# @{

import struct


# Basic types
def pack_uint8(value):
    return [(value & 0xFF)]


def unpack_uint8(data):
    if isinstance(data, list):
        return data[0]
    else:
        return data


def pack_sint8(value):
    return [ord(c) for c in struct.pack('>b', value)]


def unpack_sint8(data):
    if isinstance(data, list):
        data = data[0]
    return struct.unpack('>b', chr(data))[0]


def pack_uint16(value, msb=True):
    if (msb):
        return [ord(c) for c in struct.pack('>H', value)]
    else:
        return [ord(c) for c in struct.pack('<H', value)]

def unpack_uint16(data, msb=True):
    assert isinstance(data, list)
    if (msb):
        return struct.unpack('>H', ''.join([chr(x) for x in data]))[0]
    else:
        return struct.unpack('<H', ''.join([chr(x) for x in data]))[0]

def pack_sint16(value, msb=True):
    if (msb):
        return [ord(c) for c in struct.pack('>h', value)]
    else:
        return [ord(c) for c in struct.pack('<h', value)]

def unpack_sint16(data, msb=True):
    assert isinstance(data, list)
    if (msb):
        return struct.unpack('>h', ''.join([chr(x) for x in data]))[0]
    else:
        return struct.unpack('<h', ''.join([chr(x) for x in data]))[0]

def pack_uint32(value, msb=True):
    if (msb):
        return [ord(c) for c in struct.pack('>I', value)]
    else:
        return [ord(c) for c in struct.pack('<I', value)]

def unpack_uint32(data, msb=True):
    assert isinstance(data, list)
    if (msb):
        return struct.unpack('>I', ''.join([chr(x) for x in data]))[0]
    else:
        return struct.unpack('<I', ''.join([chr(x) for x in data]))[0]

def pack_sint32(value, msb=True):
    if (msb):
        return [ord(c) for c in struct.pack('>i', value)]
    else:
        return [ord(c) for c in struct.pack('<i', value)]

def unpack_sint32(data, msb=True):
    assert isinstance(data, list)
    if (msb):
        return struct.unpack('>i', ''.join([chr(x) for x in data]))[0]
    else:
        return struct.unpack('<i', ''.join([chr(x) for x in data]))[0]

def pack_bool(value):
    if value:
        return [0x01]
    else:
        return [0x00]


def unpack_bool(data):
    if isinstance(data, list):
        data = data[0]
    return True if data > 0 else False


def pack_bit(value, bit):
    if value:
        return (1 << bit)
    else:
        return 0


def unpack_bit(data, bit):
    if isinstance(data, list):
        data = data[0]
    if (data >> bit) & 0x01 > 0:
        return True
    else:
        return False


def pack_float(value):
    return [ord(c) for c in struct.pack('>f', value)]


def unpack_float(data):
    assert isinstance(data, list)
    return struct.unpack('>f', ''.join([chr(x) for x in data]))[0]


def pack_string(value, length):
    assert isinstance(value, str)
    # restrict the string to length
    data = []
    for c in value[0:length]:
        data.append(ord(c))
    # and pad it if not long enough
    data += [0] * (length - len(data))
    return data


def unpack_string(data):
    assert isinstance(data, list)
    return (''.join([chr(b) for b in data])).rstrip('\0')

def my_unpack_string(data):
    assert isinstance(data, list)
    return ''.join([chr(b) for b in data])

if __name__ == '__main__':
    pass

# @}
