# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2016. Benoit Michau. ANSSI.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301  USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_core/utils_py3.py
# * Created : 2016-02-11
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
#
# All basic conversion function in native Python should be handled here
#
import sys
from struct    import pack, unpack
from functools import reduce, partial

# use gmpy for handling very large integers
try:
    from gmpy import mpz
except ImportError:
    try:
        from gmpy2 import mpz
    except ImportError:
        # just use Python large integer handling (which is slow)
        _WITH_MPZ = False
    else:
        _WITH_MPZ = True
        _MPZ_T = type(mpz(0))
else:
    _WITH_MPZ = True
    _MPZ_T = type(mpz(0))

#------------------------------------------------------------------------------#
# Python3 oddities
#------------------------------------------------------------------------------#
python_version = sys.version_info[0]

# no more long type in Python3
if _WITH_MPZ:
    integer_types = (int, _MPZ_T)
else:
    integer_types = (int, )
# str are different than bytes in Python3
bytes_types = (bytes, )
# unicode is defined in Python2 and not in Python3
str_types = (str, )
# there is no NoneType in types anymore
NoneType = type(None)

# defines a bchr() which returns a bytes instance to mimic Python2 chr()
bchr = partial(pack, 'B')

#------------------------------------------------------------------------------#
# Pycrate generic error
#------------------------------------------------------------------------------#

class PycrateErr(Exception):
    pass

#------------------------------------------------------------------------------#
# bit list functions
#------------------------------------------------------------------------------#

ARRTOBIT_LUT = {
    0: (0, 0, 0, 0, 0, 0, 0, 0),
    1: (0, 0, 0, 0, 0, 0, 0, 1),
    2: (0, 0, 0, 0, 0, 0, 1, 0),
    3: (0, 0, 0, 0, 0, 0, 1, 1),
    4: (0, 0, 0, 0, 0, 1, 0, 0),
    5: (0, 0, 0, 0, 0, 1, 0, 1),
    6: (0, 0, 0, 0, 0, 1, 1, 0),
    7: (0, 0, 0, 0, 0, 1, 1, 1),
    8: (0, 0, 0, 0, 1, 0, 0, 0),
    9: (0, 0, 0, 0, 1, 0, 0, 1),
    10: (0, 0, 0, 0, 1, 0, 1, 0),
    11: (0, 0, 0, 0, 1, 0, 1, 1),
    12: (0, 0, 0, 0, 1, 1, 0, 0),
    13: (0, 0, 0, 0, 1, 1, 0, 1),
    14: (0, 0, 0, 0, 1, 1, 1, 0),
    15: (0, 0, 0, 0, 1, 1, 1, 1),
    16: (0, 0, 0, 1, 0, 0, 0, 0),
    17: (0, 0, 0, 1, 0, 0, 0, 1),
    18: (0, 0, 0, 1, 0, 0, 1, 0),
    19: (0, 0, 0, 1, 0, 0, 1, 1),
    20: (0, 0, 0, 1, 0, 1, 0, 0),
    21: (0, 0, 0, 1, 0, 1, 0, 1),
    22: (0, 0, 0, 1, 0, 1, 1, 0),
    23: (0, 0, 0, 1, 0, 1, 1, 1),
    24: (0, 0, 0, 1, 1, 0, 0, 0),
    25: (0, 0, 0, 1, 1, 0, 0, 1),
    26: (0, 0, 0, 1, 1, 0, 1, 0),
    27: (0, 0, 0, 1, 1, 0, 1, 1),
    28: (0, 0, 0, 1, 1, 1, 0, 0),
    29: (0, 0, 0, 1, 1, 1, 0, 1),
    30: (0, 0, 0, 1, 1, 1, 1, 0),
    31: (0, 0, 0, 1, 1, 1, 1, 1),
    32: (0, 0, 1, 0, 0, 0, 0, 0),
    33: (0, 0, 1, 0, 0, 0, 0, 1),
    34: (0, 0, 1, 0, 0, 0, 1, 0),
    35: (0, 0, 1, 0, 0, 0, 1, 1),
    36: (0, 0, 1, 0, 0, 1, 0, 0),
    37: (0, 0, 1, 0, 0, 1, 0, 1),
    38: (0, 0, 1, 0, 0, 1, 1, 0),
    39: (0, 0, 1, 0, 0, 1, 1, 1),
    40: (0, 0, 1, 0, 1, 0, 0, 0),
    41: (0, 0, 1, 0, 1, 0, 0, 1),
    42: (0, 0, 1, 0, 1, 0, 1, 0),
    43: (0, 0, 1, 0, 1, 0, 1, 1),
    44: (0, 0, 1, 0, 1, 1, 0, 0),
    45: (0, 0, 1, 0, 1, 1, 0, 1),
    46: (0, 0, 1, 0, 1, 1, 1, 0),
    47: (0, 0, 1, 0, 1, 1, 1, 1),
    48: (0, 0, 1, 1, 0, 0, 0, 0),
    49: (0, 0, 1, 1, 0, 0, 0, 1),
    50: (0, 0, 1, 1, 0, 0, 1, 0),
    51: (0, 0, 1, 1, 0, 0, 1, 1),
    52: (0, 0, 1, 1, 0, 1, 0, 0),
    53: (0, 0, 1, 1, 0, 1, 0, 1),
    54: (0, 0, 1, 1, 0, 1, 1, 0),
    55: (0, 0, 1, 1, 0, 1, 1, 1),
    56: (0, 0, 1, 1, 1, 0, 0, 0),
    57: (0, 0, 1, 1, 1, 0, 0, 1),
    58: (0, 0, 1, 1, 1, 0, 1, 0),
    59: (0, 0, 1, 1, 1, 0, 1, 1),
    60: (0, 0, 1, 1, 1, 1, 0, 0),
    61: (0, 0, 1, 1, 1, 1, 0, 1),
    62: (0, 0, 1, 1, 1, 1, 1, 0),
    63: (0, 0, 1, 1, 1, 1, 1, 1),
    64: (0, 1, 0, 0, 0, 0, 0, 0),
    65: (0, 1, 0, 0, 0, 0, 0, 1),
    66: (0, 1, 0, 0, 0, 0, 1, 0),
    67: (0, 1, 0, 0, 0, 0, 1, 1),
    68: (0, 1, 0, 0, 0, 1, 0, 0),
    69: (0, 1, 0, 0, 0, 1, 0, 1),
    70: (0, 1, 0, 0, 0, 1, 1, 0),
    71: (0, 1, 0, 0, 0, 1, 1, 1),
    72: (0, 1, 0, 0, 1, 0, 0, 0),
    73: (0, 1, 0, 0, 1, 0, 0, 1),
    74: (0, 1, 0, 0, 1, 0, 1, 0),
    75: (0, 1, 0, 0, 1, 0, 1, 1),
    76: (0, 1, 0, 0, 1, 1, 0, 0),
    77: (0, 1, 0, 0, 1, 1, 0, 1),
    78: (0, 1, 0, 0, 1, 1, 1, 0),
    79: (0, 1, 0, 0, 1, 1, 1, 1),
    80: (0, 1, 0, 1, 0, 0, 0, 0),
    81: (0, 1, 0, 1, 0, 0, 0, 1),
    82: (0, 1, 0, 1, 0, 0, 1, 0),
    83: (0, 1, 0, 1, 0, 0, 1, 1),
    84: (0, 1, 0, 1, 0, 1, 0, 0),
    85: (0, 1, 0, 1, 0, 1, 0, 1),
    86: (0, 1, 0, 1, 0, 1, 1, 0),
    87: (0, 1, 0, 1, 0, 1, 1, 1),
    88: (0, 1, 0, 1, 1, 0, 0, 0),
    89: (0, 1, 0, 1, 1, 0, 0, 1),
    90: (0, 1, 0, 1, 1, 0, 1, 0),
    91: (0, 1, 0, 1, 1, 0, 1, 1),
    92: (0, 1, 0, 1, 1, 1, 0, 0),
    93: (0, 1, 0, 1, 1, 1, 0, 1),
    94: (0, 1, 0, 1, 1, 1, 1, 0),
    95: (0, 1, 0, 1, 1, 1, 1, 1),
    96: (0, 1, 1, 0, 0, 0, 0, 0),
    97: (0, 1, 1, 0, 0, 0, 0, 1),
    98: (0, 1, 1, 0, 0, 0, 1, 0),
    99: (0, 1, 1, 0, 0, 0, 1, 1),
    100: (0, 1, 1, 0, 0, 1, 0, 0),
    101: (0, 1, 1, 0, 0, 1, 0, 1),
    102: (0, 1, 1, 0, 0, 1, 1, 0),
    103: (0, 1, 1, 0, 0, 1, 1, 1),
    104: (0, 1, 1, 0, 1, 0, 0, 0),
    105: (0, 1, 1, 0, 1, 0, 0, 1),
    106: (0, 1, 1, 0, 1, 0, 1, 0),
    107: (0, 1, 1, 0, 1, 0, 1, 1),
    108: (0, 1, 1, 0, 1, 1, 0, 0),
    109: (0, 1, 1, 0, 1, 1, 0, 1),
    110: (0, 1, 1, 0, 1, 1, 1, 0),
    111: (0, 1, 1, 0, 1, 1, 1, 1),
    112: (0, 1, 1, 1, 0, 0, 0, 0),
    113: (0, 1, 1, 1, 0, 0, 0, 1),
    114: (0, 1, 1, 1, 0, 0, 1, 0),
    115: (0, 1, 1, 1, 0, 0, 1, 1),
    116: (0, 1, 1, 1, 0, 1, 0, 0),
    117: (0, 1, 1, 1, 0, 1, 0, 1),
    118: (0, 1, 1, 1, 0, 1, 1, 0),
    119: (0, 1, 1, 1, 0, 1, 1, 1),
    120: (0, 1, 1, 1, 1, 0, 0, 0),
    121: (0, 1, 1, 1, 1, 0, 0, 1),
    122: (0, 1, 1, 1, 1, 0, 1, 0),
    123: (0, 1, 1, 1, 1, 0, 1, 1),
    124: (0, 1, 1, 1, 1, 1, 0, 0),
    125: (0, 1, 1, 1, 1, 1, 0, 1),
    126: (0, 1, 1, 1, 1, 1, 1, 0),
    127: (0, 1, 1, 1, 1, 1, 1, 1),
    128: (1, 0, 0, 0, 0, 0, 0, 0),
    129: (1, 0, 0, 0, 0, 0, 0, 1),
    130: (1, 0, 0, 0, 0, 0, 1, 0),
    131: (1, 0, 0, 0, 0, 0, 1, 1),
    132: (1, 0, 0, 0, 0, 1, 0, 0),
    133: (1, 0, 0, 0, 0, 1, 0, 1),
    134: (1, 0, 0, 0, 0, 1, 1, 0),
    135: (1, 0, 0, 0, 0, 1, 1, 1),
    136: (1, 0, 0, 0, 1, 0, 0, 0),
    137: (1, 0, 0, 0, 1, 0, 0, 1),
    138: (1, 0, 0, 0, 1, 0, 1, 0),
    139: (1, 0, 0, 0, 1, 0, 1, 1),
    140: (1, 0, 0, 0, 1, 1, 0, 0),
    141: (1, 0, 0, 0, 1, 1, 0, 1),
    142: (1, 0, 0, 0, 1, 1, 1, 0),
    143: (1, 0, 0, 0, 1, 1, 1, 1),
    144: (1, 0, 0, 1, 0, 0, 0, 0),
    145: (1, 0, 0, 1, 0, 0, 0, 1),
    146: (1, 0, 0, 1, 0, 0, 1, 0),
    147: (1, 0, 0, 1, 0, 0, 1, 1),
    148: (1, 0, 0, 1, 0, 1, 0, 0),
    149: (1, 0, 0, 1, 0, 1, 0, 1),
    150: (1, 0, 0, 1, 0, 1, 1, 0),
    151: (1, 0, 0, 1, 0, 1, 1, 1),
    152: (1, 0, 0, 1, 1, 0, 0, 0),
    153: (1, 0, 0, 1, 1, 0, 0, 1),
    154: (1, 0, 0, 1, 1, 0, 1, 0),
    155: (1, 0, 0, 1, 1, 0, 1, 1),
    156: (1, 0, 0, 1, 1, 1, 0, 0),
    157: (1, 0, 0, 1, 1, 1, 0, 1),
    158: (1, 0, 0, 1, 1, 1, 1, 0),
    159: (1, 0, 0, 1, 1, 1, 1, 1),
    160: (1, 0, 1, 0, 0, 0, 0, 0),
    161: (1, 0, 1, 0, 0, 0, 0, 1),
    162: (1, 0, 1, 0, 0, 0, 1, 0),
    163: (1, 0, 1, 0, 0, 0, 1, 1),
    164: (1, 0, 1, 0, 0, 1, 0, 0),
    165: (1, 0, 1, 0, 0, 1, 0, 1),
    166: (1, 0, 1, 0, 0, 1, 1, 0),
    167: (1, 0, 1, 0, 0, 1, 1, 1),
    168: (1, 0, 1, 0, 1, 0, 0, 0),
    169: (1, 0, 1, 0, 1, 0, 0, 1),
    170: (1, 0, 1, 0, 1, 0, 1, 0),
    171: (1, 0, 1, 0, 1, 0, 1, 1),
    172: (1, 0, 1, 0, 1, 1, 0, 0),
    173: (1, 0, 1, 0, 1, 1, 0, 1),
    174: (1, 0, 1, 0, 1, 1, 1, 0),
    175: (1, 0, 1, 0, 1, 1, 1, 1),
    176: (1, 0, 1, 1, 0, 0, 0, 0),
    177: (1, 0, 1, 1, 0, 0, 0, 1),
    178: (1, 0, 1, 1, 0, 0, 1, 0),
    179: (1, 0, 1, 1, 0, 0, 1, 1),
    180: (1, 0, 1, 1, 0, 1, 0, 0),
    181: (1, 0, 1, 1, 0, 1, 0, 1),
    182: (1, 0, 1, 1, 0, 1, 1, 0),
    183: (1, 0, 1, 1, 0, 1, 1, 1),
    184: (1, 0, 1, 1, 1, 0, 0, 0),
    185: (1, 0, 1, 1, 1, 0, 0, 1),
    186: (1, 0, 1, 1, 1, 0, 1, 0),
    187: (1, 0, 1, 1, 1, 0, 1, 1),
    188: (1, 0, 1, 1, 1, 1, 0, 0),
    189: (1, 0, 1, 1, 1, 1, 0, 1),
    190: (1, 0, 1, 1, 1, 1, 1, 0),
    191: (1, 0, 1, 1, 1, 1, 1, 1),
    192: (1, 1, 0, 0, 0, 0, 0, 0),
    193: (1, 1, 0, 0, 0, 0, 0, 1),
    194: (1, 1, 0, 0, 0, 0, 1, 0),
    195: (1, 1, 0, 0, 0, 0, 1, 1),
    196: (1, 1, 0, 0, 0, 1, 0, 0),
    197: (1, 1, 0, 0, 0, 1, 0, 1),
    198: (1, 1, 0, 0, 0, 1, 1, 0),
    199: (1, 1, 0, 0, 0, 1, 1, 1),
    200: (1, 1, 0, 0, 1, 0, 0, 0),
    201: (1, 1, 0, 0, 1, 0, 0, 1),
    202: (1, 1, 0, 0, 1, 0, 1, 0),
    203: (1, 1, 0, 0, 1, 0, 1, 1),
    204: (1, 1, 0, 0, 1, 1, 0, 0),
    205: (1, 1, 0, 0, 1, 1, 0, 1),
    206: (1, 1, 0, 0, 1, 1, 1, 0),
    207: (1, 1, 0, 0, 1, 1, 1, 1),
    208: (1, 1, 0, 1, 0, 0, 0, 0),
    209: (1, 1, 0, 1, 0, 0, 0, 1),
    210: (1, 1, 0, 1, 0, 0, 1, 0),
    211: (1, 1, 0, 1, 0, 0, 1, 1),
    212: (1, 1, 0, 1, 0, 1, 0, 0),
    213: (1, 1, 0, 1, 0, 1, 0, 1),
    214: (1, 1, 0, 1, 0, 1, 1, 0),
    215: (1, 1, 0, 1, 0, 1, 1, 1),
    216: (1, 1, 0, 1, 1, 0, 0, 0),
    217: (1, 1, 0, 1, 1, 0, 0, 1),
    218: (1, 1, 0, 1, 1, 0, 1, 0),
    219: (1, 1, 0, 1, 1, 0, 1, 1),
    220: (1, 1, 0, 1, 1, 1, 0, 0),
    221: (1, 1, 0, 1, 1, 1, 0, 1),
    222: (1, 1, 0, 1, 1, 1, 1, 0),
    223: (1, 1, 0, 1, 1, 1, 1, 1),
    224: (1, 1, 1, 0, 0, 0, 0, 0),
    225: (1, 1, 1, 0, 0, 0, 0, 1),
    226: (1, 1, 1, 0, 0, 0, 1, 0),
    227: (1, 1, 1, 0, 0, 0, 1, 1),
    228: (1, 1, 1, 0, 0, 1, 0, 0),
    229: (1, 1, 1, 0, 0, 1, 0, 1),
    230: (1, 1, 1, 0, 0, 1, 1, 0),
    231: (1, 1, 1, 0, 0, 1, 1, 1),
    232: (1, 1, 1, 0, 1, 0, 0, 0),
    233: (1, 1, 1, 0, 1, 0, 0, 1),
    234: (1, 1, 1, 0, 1, 0, 1, 0),
    235: (1, 1, 1, 0, 1, 0, 1, 1),
    236: (1, 1, 1, 0, 1, 1, 0, 0),
    237: (1, 1, 1, 0, 1, 1, 0, 1),
    238: (1, 1, 1, 0, 1, 1, 1, 0),
    239: (1, 1, 1, 0, 1, 1, 1, 1),
    240: (1, 1, 1, 1, 0, 0, 0, 0),
    241: (1, 1, 1, 1, 0, 0, 0, 1),
    242: (1, 1, 1, 1, 0, 0, 1, 0),
    243: (1, 1, 1, 1, 0, 0, 1, 1),
    244: (1, 1, 1, 1, 0, 1, 0, 0),
    245: (1, 1, 1, 1, 0, 1, 0, 1),
    246: (1, 1, 1, 1, 0, 1, 1, 0),
    247: (1, 1, 1, 1, 0, 1, 1, 1),
    248: (1, 1, 1, 1, 1, 0, 0, 0),
    249: (1, 1, 1, 1, 1, 0, 0, 1),
    250: (1, 1, 1, 1, 1, 0, 1, 0),
    251: (1, 1, 1, 1, 1, 0, 1, 1),
    252: (1, 1, 1, 1, 1, 1, 0, 0),
    253: (1, 1, 1, 1, 1, 1, 0, 1),
    254: (1, 1, 1, 1, 1, 1, 1, 0),
    255: (1, 1, 1, 1, 1, 1, 1, 1)
    }

BYTETOBIT_LUT = {
    b'\x00': (0, 0, 0, 0, 0, 0, 0, 0),
    b'\x01': (0, 0, 0, 0, 0, 0, 0, 1),
    b'\x02': (0, 0, 0, 0, 0, 0, 1, 0),
    b'\x03': (0, 0, 0, 0, 0, 0, 1, 1),
    b'\x04': (0, 0, 0, 0, 0, 1, 0, 0),
    b'\x05': (0, 0, 0, 0, 0, 1, 0, 1),
    b'\x06': (0, 0, 0, 0, 0, 1, 1, 0),
    b'\x07': (0, 0, 0, 0, 0, 1, 1, 1),
    b'\x08': (0, 0, 0, 0, 1, 0, 0, 0),
    b'\t': (0, 0, 0, 0, 1, 0, 0, 1),
    b'\n': (0, 0, 0, 0, 1, 0, 1, 0),
    b'\x0b': (0, 0, 0, 0, 1, 0, 1, 1),
    b'\x0c': (0, 0, 0, 0, 1, 1, 0, 0),
    b'\r': (0, 0, 0, 0, 1, 1, 0, 1),
    b'\x0e': (0, 0, 0, 0, 1, 1, 1, 0),
    b'\x0f': (0, 0, 0, 0, 1, 1, 1, 1),
    b'\x10': (0, 0, 0, 1, 0, 0, 0, 0),
    b'\x11': (0, 0, 0, 1, 0, 0, 0, 1),
    b'\x12': (0, 0, 0, 1, 0, 0, 1, 0),
    b'\x13': (0, 0, 0, 1, 0, 0, 1, 1),
    b'\x14': (0, 0, 0, 1, 0, 1, 0, 0),
    b'\x15': (0, 0, 0, 1, 0, 1, 0, 1),
    b'\x16': (0, 0, 0, 1, 0, 1, 1, 0),
    b'\x17': (0, 0, 0, 1, 0, 1, 1, 1),
    b'\x18': (0, 0, 0, 1, 1, 0, 0, 0),
    b'\x19': (0, 0, 0, 1, 1, 0, 0, 1),
    b'\x1a': (0, 0, 0, 1, 1, 0, 1, 0),
    b'\x1b': (0, 0, 0, 1, 1, 0, 1, 1),
    b'\x1c': (0, 0, 0, 1, 1, 1, 0, 0),
    b'\x1d': (0, 0, 0, 1, 1, 1, 0, 1),
    b'\x1e': (0, 0, 0, 1, 1, 1, 1, 0),
    b'\x1f': (0, 0, 0, 1, 1, 1, 1, 1),
    b' ': (0, 0, 1, 0, 0, 0, 0, 0),
    b'!': (0, 0, 1, 0, 0, 0, 0, 1),
    b'"': (0, 0, 1, 0, 0, 0, 1, 0),
    b'#': (0, 0, 1, 0, 0, 0, 1, 1),
    b'$': (0, 0, 1, 0, 0, 1, 0, 0),
    b'%': (0, 0, 1, 0, 0, 1, 0, 1),
    b'&': (0, 0, 1, 0, 0, 1, 1, 0),
    b"'": (0, 0, 1, 0, 0, 1, 1, 1),
    b'(': (0, 0, 1, 0, 1, 0, 0, 0),
    b')': (0, 0, 1, 0, 1, 0, 0, 1),
    b'*': (0, 0, 1, 0, 1, 0, 1, 0),
    b'+': (0, 0, 1, 0, 1, 0, 1, 1),
    b',': (0, 0, 1, 0, 1, 1, 0, 0),
    b'-': (0, 0, 1, 0, 1, 1, 0, 1),
    b'.': (0, 0, 1, 0, 1, 1, 1, 0),
    b'/': (0, 0, 1, 0, 1, 1, 1, 1),
    b'0': (0, 0, 1, 1, 0, 0, 0, 0),
    b'1': (0, 0, 1, 1, 0, 0, 0, 1),
    b'2': (0, 0, 1, 1, 0, 0, 1, 0),
    b'3': (0, 0, 1, 1, 0, 0, 1, 1),
    b'4': (0, 0, 1, 1, 0, 1, 0, 0),
    b'5': (0, 0, 1, 1, 0, 1, 0, 1),
    b'6': (0, 0, 1, 1, 0, 1, 1, 0),
    b'7': (0, 0, 1, 1, 0, 1, 1, 1),
    b'8': (0, 0, 1, 1, 1, 0, 0, 0),
    b'9': (0, 0, 1, 1, 1, 0, 0, 1),
    b':': (0, 0, 1, 1, 1, 0, 1, 0),
    b';': (0, 0, 1, 1, 1, 0, 1, 1),
    b'<': (0, 0, 1, 1, 1, 1, 0, 0),
    b'=': (0, 0, 1, 1, 1, 1, 0, 1),
    b'>': (0, 0, 1, 1, 1, 1, 1, 0),
    b'?': (0, 0, 1, 1, 1, 1, 1, 1),
    b'@': (0, 1, 0, 0, 0, 0, 0, 0),
    b'A': (0, 1, 0, 0, 0, 0, 0, 1),
    b'B': (0, 1, 0, 0, 0, 0, 1, 0),
    b'C': (0, 1, 0, 0, 0, 0, 1, 1),
    b'D': (0, 1, 0, 0, 0, 1, 0, 0),
    b'E': (0, 1, 0, 0, 0, 1, 0, 1),
    b'F': (0, 1, 0, 0, 0, 1, 1, 0),
    b'G': (0, 1, 0, 0, 0, 1, 1, 1),
    b'H': (0, 1, 0, 0, 1, 0, 0, 0),
    b'I': (0, 1, 0, 0, 1, 0, 0, 1),
    b'J': (0, 1, 0, 0, 1, 0, 1, 0),
    b'K': (0, 1, 0, 0, 1, 0, 1, 1),
    b'L': (0, 1, 0, 0, 1, 1, 0, 0),
    b'M': (0, 1, 0, 0, 1, 1, 0, 1),
    b'N': (0, 1, 0, 0, 1, 1, 1, 0),
    b'O': (0, 1, 0, 0, 1, 1, 1, 1),
    b'P': (0, 1, 0, 1, 0, 0, 0, 0),
    b'Q': (0, 1, 0, 1, 0, 0, 0, 1),
    b'R': (0, 1, 0, 1, 0, 0, 1, 0),
    b'S': (0, 1, 0, 1, 0, 0, 1, 1),
    b'T': (0, 1, 0, 1, 0, 1, 0, 0),
    b'U': (0, 1, 0, 1, 0, 1, 0, 1),
    b'V': (0, 1, 0, 1, 0, 1, 1, 0),
    b'W': (0, 1, 0, 1, 0, 1, 1, 1),
    b'X': (0, 1, 0, 1, 1, 0, 0, 0),
    b'Y': (0, 1, 0, 1, 1, 0, 0, 1),
    b'Z': (0, 1, 0, 1, 1, 0, 1, 0),
    b'[': (0, 1, 0, 1, 1, 0, 1, 1),
    b'\\': (0, 1, 0, 1, 1, 1, 0, 0),
    b']': (0, 1, 0, 1, 1, 1, 0, 1),
    b'^': (0, 1, 0, 1, 1, 1, 1, 0),
    b'_': (0, 1, 0, 1, 1, 1, 1, 1),
    b'`': (0, 1, 1, 0, 0, 0, 0, 0),
    b'a': (0, 1, 1, 0, 0, 0, 0, 1),
    b'b': (0, 1, 1, 0, 0, 0, 1, 0),
    b'c': (0, 1, 1, 0, 0, 0, 1, 1),
    b'd': (0, 1, 1, 0, 0, 1, 0, 0),
    b'e': (0, 1, 1, 0, 0, 1, 0, 1),
    b'f': (0, 1, 1, 0, 0, 1, 1, 0),
    b'g': (0, 1, 1, 0, 0, 1, 1, 1),
    b'h': (0, 1, 1, 0, 1, 0, 0, 0),
    b'i': (0, 1, 1, 0, 1, 0, 0, 1),
    b'j': (0, 1, 1, 0, 1, 0, 1, 0),
    b'k': (0, 1, 1, 0, 1, 0, 1, 1),
    b'l': (0, 1, 1, 0, 1, 1, 0, 0),
    b'm': (0, 1, 1, 0, 1, 1, 0, 1),
    b'n': (0, 1, 1, 0, 1, 1, 1, 0),
    b'o': (0, 1, 1, 0, 1, 1, 1, 1),
    b'p': (0, 1, 1, 1, 0, 0, 0, 0),
    b'q': (0, 1, 1, 1, 0, 0, 0, 1),
    b'r': (0, 1, 1, 1, 0, 0, 1, 0),
    b's': (0, 1, 1, 1, 0, 0, 1, 1),
    b't': (0, 1, 1, 1, 0, 1, 0, 0),
    b'u': (0, 1, 1, 1, 0, 1, 0, 1),
    b'v': (0, 1, 1, 1, 0, 1, 1, 0),
    b'w': (0, 1, 1, 1, 0, 1, 1, 1),
    b'x': (0, 1, 1, 1, 1, 0, 0, 0),
    b'y': (0, 1, 1, 1, 1, 0, 0, 1),
    b'z': (0, 1, 1, 1, 1, 0, 1, 0),
    b'{': (0, 1, 1, 1, 1, 0, 1, 1),
    b'|': (0, 1, 1, 1, 1, 1, 0, 0),
    b'}': (0, 1, 1, 1, 1, 1, 0, 1),
    b'~': (0, 1, 1, 1, 1, 1, 1, 0),
    b'\x7f': (0, 1, 1, 1, 1, 1, 1, 1),
    b'\x80': (1, 0, 0, 0, 0, 0, 0, 0),
    b'\x81': (1, 0, 0, 0, 0, 0, 0, 1),
    b'\x82': (1, 0, 0, 0, 0, 0, 1, 0),
    b'\x83': (1, 0, 0, 0, 0, 0, 1, 1),
    b'\x84': (1, 0, 0, 0, 0, 1, 0, 0),
    b'\x85': (1, 0, 0, 0, 0, 1, 0, 1),
    b'\x86': (1, 0, 0, 0, 0, 1, 1, 0),
    b'\x87': (1, 0, 0, 0, 0, 1, 1, 1),
    b'\x88': (1, 0, 0, 0, 1, 0, 0, 0),
    b'\x89': (1, 0, 0, 0, 1, 0, 0, 1),
    b'\x8a': (1, 0, 0, 0, 1, 0, 1, 0),
    b'\x8b': (1, 0, 0, 0, 1, 0, 1, 1),
    b'\x8c': (1, 0, 0, 0, 1, 1, 0, 0),
    b'\x8d': (1, 0, 0, 0, 1, 1, 0, 1),
    b'\x8e': (1, 0, 0, 0, 1, 1, 1, 0),
    b'\x8f': (1, 0, 0, 0, 1, 1, 1, 1),
    b'\x90': (1, 0, 0, 1, 0, 0, 0, 0),
    b'\x91': (1, 0, 0, 1, 0, 0, 0, 1),
    b'\x92': (1, 0, 0, 1, 0, 0, 1, 0),
    b'\x93': (1, 0, 0, 1, 0, 0, 1, 1),
    b'\x94': (1, 0, 0, 1, 0, 1, 0, 0),
    b'\x95': (1, 0, 0, 1, 0, 1, 0, 1),
    b'\x96': (1, 0, 0, 1, 0, 1, 1, 0),
    b'\x97': (1, 0, 0, 1, 0, 1, 1, 1),
    b'\x98': (1, 0, 0, 1, 1, 0, 0, 0),
    b'\x99': (1, 0, 0, 1, 1, 0, 0, 1),
    b'\x9a': (1, 0, 0, 1, 1, 0, 1, 0),
    b'\x9b': (1, 0, 0, 1, 1, 0, 1, 1),
    b'\x9c': (1, 0, 0, 1, 1, 1, 0, 0),
    b'\x9d': (1, 0, 0, 1, 1, 1, 0, 1),
    b'\x9e': (1, 0, 0, 1, 1, 1, 1, 0),
    b'\x9f': (1, 0, 0, 1, 1, 1, 1, 1),
    b'\xa0': (1, 0, 1, 0, 0, 0, 0, 0),
    b'\xa1': (1, 0, 1, 0, 0, 0, 0, 1),
    b'\xa2': (1, 0, 1, 0, 0, 0, 1, 0),
    b'\xa3': (1, 0, 1, 0, 0, 0, 1, 1),
    b'\xa4': (1, 0, 1, 0, 0, 1, 0, 0),
    b'\xa5': (1, 0, 1, 0, 0, 1, 0, 1),
    b'\xa6': (1, 0, 1, 0, 0, 1, 1, 0),
    b'\xa7': (1, 0, 1, 0, 0, 1, 1, 1),
    b'\xa8': (1, 0, 1, 0, 1, 0, 0, 0),
    b'\xa9': (1, 0, 1, 0, 1, 0, 0, 1),
    b'\xaa': (1, 0, 1, 0, 1, 0, 1, 0),
    b'\xab': (1, 0, 1, 0, 1, 0, 1, 1),
    b'\xac': (1, 0, 1, 0, 1, 1, 0, 0),
    b'\xad': (1, 0, 1, 0, 1, 1, 0, 1),
    b'\xae': (1, 0, 1, 0, 1, 1, 1, 0),
    b'\xaf': (1, 0, 1, 0, 1, 1, 1, 1),
    b'\xb0': (1, 0, 1, 1, 0, 0, 0, 0),
    b'\xb1': (1, 0, 1, 1, 0, 0, 0, 1),
    b'\xb2': (1, 0, 1, 1, 0, 0, 1, 0),
    b'\xb3': (1, 0, 1, 1, 0, 0, 1, 1),
    b'\xb4': (1, 0, 1, 1, 0, 1, 0, 0),
    b'\xb5': (1, 0, 1, 1, 0, 1, 0, 1),
    b'\xb6': (1, 0, 1, 1, 0, 1, 1, 0),
    b'\xb7': (1, 0, 1, 1, 0, 1, 1, 1),
    b'\xb8': (1, 0, 1, 1, 1, 0, 0, 0),
    b'\xb9': (1, 0, 1, 1, 1, 0, 0, 1),
    b'\xba': (1, 0, 1, 1, 1, 0, 1, 0),
    b'\xbb': (1, 0, 1, 1, 1, 0, 1, 1),
    b'\xbc': (1, 0, 1, 1, 1, 1, 0, 0),
    b'\xbd': (1, 0, 1, 1, 1, 1, 0, 1),
    b'\xbe': (1, 0, 1, 1, 1, 1, 1, 0),
    b'\xbf': (1, 0, 1, 1, 1, 1, 1, 1),
    b'\xc0': (1, 1, 0, 0, 0, 0, 0, 0),
    b'\xc1': (1, 1, 0, 0, 0, 0, 0, 1),
    b'\xc2': (1, 1, 0, 0, 0, 0, 1, 0),
    b'\xc3': (1, 1, 0, 0, 0, 0, 1, 1),
    b'\xc4': (1, 1, 0, 0, 0, 1, 0, 0),
    b'\xc5': (1, 1, 0, 0, 0, 1, 0, 1),
    b'\xc6': (1, 1, 0, 0, 0, 1, 1, 0),
    b'\xc7': (1, 1, 0, 0, 0, 1, 1, 1),
    b'\xc8': (1, 1, 0, 0, 1, 0, 0, 0),
    b'\xc9': (1, 1, 0, 0, 1, 0, 0, 1),
    b'\xca': (1, 1, 0, 0, 1, 0, 1, 0),
    b'\xcb': (1, 1, 0, 0, 1, 0, 1, 1),
    b'\xcc': (1, 1, 0, 0, 1, 1, 0, 0),
    b'\xcd': (1, 1, 0, 0, 1, 1, 0, 1),
    b'\xce': (1, 1, 0, 0, 1, 1, 1, 0),
    b'\xcf': (1, 1, 0, 0, 1, 1, 1, 1),
    b'\xd0': (1, 1, 0, 1, 0, 0, 0, 0),
    b'\xd1': (1, 1, 0, 1, 0, 0, 0, 1),
    b'\xd2': (1, 1, 0, 1, 0, 0, 1, 0),
    b'\xd3': (1, 1, 0, 1, 0, 0, 1, 1),
    b'\xd4': (1, 1, 0, 1, 0, 1, 0, 0),
    b'\xd5': (1, 1, 0, 1, 0, 1, 0, 1),
    b'\xd6': (1, 1, 0, 1, 0, 1, 1, 0),
    b'\xd7': (1, 1, 0, 1, 0, 1, 1, 1),
    b'\xd8': (1, 1, 0, 1, 1, 0, 0, 0),
    b'\xd9': (1, 1, 0, 1, 1, 0, 0, 1),
    b'\xda': (1, 1, 0, 1, 1, 0, 1, 0),
    b'\xdb': (1, 1, 0, 1, 1, 0, 1, 1),
    b'\xdc': (1, 1, 0, 1, 1, 1, 0, 0),
    b'\xdd': (1, 1, 0, 1, 1, 1, 0, 1),
    b'\xde': (1, 1, 0, 1, 1, 1, 1, 0),
    b'\xdf': (1, 1, 0, 1, 1, 1, 1, 1),
    b'\xe0': (1, 1, 1, 0, 0, 0, 0, 0),
    b'\xe1': (1, 1, 1, 0, 0, 0, 0, 1),
    b'\xe2': (1, 1, 1, 0, 0, 0, 1, 0),
    b'\xe3': (1, 1, 1, 0, 0, 0, 1, 1),
    b'\xe4': (1, 1, 1, 0, 0, 1, 0, 0),
    b'\xe5': (1, 1, 1, 0, 0, 1, 0, 1),
    b'\xe6': (1, 1, 1, 0, 0, 1, 1, 0),
    b'\xe7': (1, 1, 1, 0, 0, 1, 1, 1),
    b'\xe8': (1, 1, 1, 0, 1, 0, 0, 0),
    b'\xe9': (1, 1, 1, 0, 1, 0, 0, 1),
    b'\xea': (1, 1, 1, 0, 1, 0, 1, 0),
    b'\xeb': (1, 1, 1, 0, 1, 0, 1, 1),
    b'\xec': (1, 1, 1, 0, 1, 1, 0, 0),
    b'\xed': (1, 1, 1, 0, 1, 1, 0, 1),
    b'\xee': (1, 1, 1, 0, 1, 1, 1, 0),
    b'\xef': (1, 1, 1, 0, 1, 1, 1, 1),
    b'\xf0': (1, 1, 1, 1, 0, 0, 0, 0),
    b'\xf1': (1, 1, 1, 1, 0, 0, 0, 1),
    b'\xf2': (1, 1, 1, 1, 0, 0, 1, 0),
    b'\xf3': (1, 1, 1, 1, 0, 0, 1, 1),
    b'\xf4': (1, 1, 1, 1, 0, 1, 0, 0),
    b'\xf5': (1, 1, 1, 1, 0, 1, 0, 1),
    b'\xf6': (1, 1, 1, 1, 0, 1, 1, 0),
    b'\xf7': (1, 1, 1, 1, 0, 1, 1, 1),
    b'\xf8': (1, 1, 1, 1, 1, 0, 0, 0),
    b'\xf9': (1, 1, 1, 1, 1, 0, 0, 1),
    b'\xfa': (1, 1, 1, 1, 1, 0, 1, 0),
    b'\xfb': (1, 1, 1, 1, 1, 0, 1, 1),
    b'\xfc': (1, 1, 1, 1, 1, 1, 0, 0),
    b'\xfd': (1, 1, 1, 1, 1, 1, 0, 1),
    b'\xfe': (1, 1, 1, 1, 1, 1, 1, 0),
    b'\xff': (1, 1, 1, 1, 1, 1, 1, 1)
    }

BITTOARR_LUT = {
    (0, 0, 0, 0, 0, 0, 0, 0) : 0,
    (0, 0, 0, 0, 0, 0, 0, 1) : 1,
    (0, 0, 0, 0, 0, 0, 1, 0) : 2,
    (0, 0, 0, 0, 0, 0, 1, 1) : 3,
    (0, 0, 0, 0, 0, 1, 0, 0) : 4,
    (0, 0, 0, 0, 0, 1, 0, 1) : 5,
    (0, 0, 0, 0, 0, 1, 1, 0) : 6,
    (0, 0, 0, 0, 0, 1, 1, 1) : 7,
    (0, 0, 0, 0, 1, 0, 0, 0) : 8,
    (0, 0, 0, 0, 1, 0, 0, 1) : 9,
    (0, 0, 0, 0, 1, 0, 1, 0) : 10,
    (0, 0, 0, 0, 1, 0, 1, 1) : 11,
    (0, 0, 0, 0, 1, 1, 0, 0) : 12,
    (0, 0, 0, 0, 1, 1, 0, 1) : 13,
    (0, 0, 0, 0, 1, 1, 1, 0) : 14,
    (0, 0, 0, 0, 1, 1, 1, 1) : 15,
    (0, 0, 0, 1, 0, 0, 0, 0) : 16,
    (0, 0, 0, 1, 0, 0, 0, 1) : 17,
    (0, 0, 0, 1, 0, 0, 1, 0) : 18,
    (0, 0, 0, 1, 0, 0, 1, 1) : 19,
    (0, 0, 0, 1, 0, 1, 0, 0) : 20,
    (0, 0, 0, 1, 0, 1, 0, 1) : 21,
    (0, 0, 0, 1, 0, 1, 1, 0) : 22,
    (0, 0, 0, 1, 0, 1, 1, 1) : 23,
    (0, 0, 0, 1, 1, 0, 0, 0) : 24,
    (0, 0, 0, 1, 1, 0, 0, 1) : 25,
    (0, 0, 0, 1, 1, 0, 1, 0) : 26,
    (0, 0, 0, 1, 1, 0, 1, 1) : 27,
    (0, 0, 0, 1, 1, 1, 0, 0) : 28,
    (0, 0, 0, 1, 1, 1, 0, 1) : 29,
    (0, 0, 0, 1, 1, 1, 1, 0) : 30,
    (0, 0, 0, 1, 1, 1, 1, 1) : 31,
    (0, 0, 1, 0, 0, 0, 0, 0) : 32,
    (0, 0, 1, 0, 0, 0, 0, 1) : 33,
    (0, 0, 1, 0, 0, 0, 1, 0) : 34,
    (0, 0, 1, 0, 0, 0, 1, 1) : 35,
    (0, 0, 1, 0, 0, 1, 0, 0) : 36,
    (0, 0, 1, 0, 0, 1, 0, 1) : 37,
    (0, 0, 1, 0, 0, 1, 1, 0) : 38,
    (0, 0, 1, 0, 0, 1, 1, 1) : 39,
    (0, 0, 1, 0, 1, 0, 0, 0) : 40,
    (0, 0, 1, 0, 1, 0, 0, 1) : 41,
    (0, 0, 1, 0, 1, 0, 1, 0) : 42,
    (0, 0, 1, 0, 1, 0, 1, 1) : 43,
    (0, 0, 1, 0, 1, 1, 0, 0) : 44,
    (0, 0, 1, 0, 1, 1, 0, 1) : 45,
    (0, 0, 1, 0, 1, 1, 1, 0) : 46,
    (0, 0, 1, 0, 1, 1, 1, 1) : 47,
    (0, 0, 1, 1, 0, 0, 0, 0) : 48,
    (0, 0, 1, 1, 0, 0, 0, 1) : 49,
    (0, 0, 1, 1, 0, 0, 1, 0) : 50,
    (0, 0, 1, 1, 0, 0, 1, 1) : 51,
    (0, 0, 1, 1, 0, 1, 0, 0) : 52,
    (0, 0, 1, 1, 0, 1, 0, 1) : 53,
    (0, 0, 1, 1, 0, 1, 1, 0) : 54,
    (0, 0, 1, 1, 0, 1, 1, 1) : 55,
    (0, 0, 1, 1, 1, 0, 0, 0) : 56,
    (0, 0, 1, 1, 1, 0, 0, 1) : 57,
    (0, 0, 1, 1, 1, 0, 1, 0) : 58,
    (0, 0, 1, 1, 1, 0, 1, 1) : 59,
    (0, 0, 1, 1, 1, 1, 0, 0) : 60,
    (0, 0, 1, 1, 1, 1, 0, 1) : 61,
    (0, 0, 1, 1, 1, 1, 1, 0) : 62,
    (0, 0, 1, 1, 1, 1, 1, 1) : 63,
    (0, 1, 0, 0, 0, 0, 0, 0) : 64,
    (0, 1, 0, 0, 0, 0, 0, 1) : 65,
    (0, 1, 0, 0, 0, 0, 1, 0) : 66,
    (0, 1, 0, 0, 0, 0, 1, 1) : 67,
    (0, 1, 0, 0, 0, 1, 0, 0) : 68,
    (0, 1, 0, 0, 0, 1, 0, 1) : 69,
    (0, 1, 0, 0, 0, 1, 1, 0) : 70,
    (0, 1, 0, 0, 0, 1, 1, 1) : 71,
    (0, 1, 0, 0, 1, 0, 0, 0) : 72,
    (0, 1, 0, 0, 1, 0, 0, 1) : 73,
    (0, 1, 0, 0, 1, 0, 1, 0) : 74,
    (0, 1, 0, 0, 1, 0, 1, 1) : 75,
    (0, 1, 0, 0, 1, 1, 0, 0) : 76,
    (0, 1, 0, 0, 1, 1, 0, 1) : 77,
    (0, 1, 0, 0, 1, 1, 1, 0) : 78,
    (0, 1, 0, 0, 1, 1, 1, 1) : 79,
    (0, 1, 0, 1, 0, 0, 0, 0) : 80,
    (0, 1, 0, 1, 0, 0, 0, 1) : 81,
    (0, 1, 0, 1, 0, 0, 1, 0) : 82,
    (0, 1, 0, 1, 0, 0, 1, 1) : 83,
    (0, 1, 0, 1, 0, 1, 0, 0) : 84,
    (0, 1, 0, 1, 0, 1, 0, 1) : 85,
    (0, 1, 0, 1, 0, 1, 1, 0) : 86,
    (0, 1, 0, 1, 0, 1, 1, 1) : 87,
    (0, 1, 0, 1, 1, 0, 0, 0) : 88,
    (0, 1, 0, 1, 1, 0, 0, 1) : 89,
    (0, 1, 0, 1, 1, 0, 1, 0) : 90,
    (0, 1, 0, 1, 1, 0, 1, 1) : 91,
    (0, 1, 0, 1, 1, 1, 0, 0) : 92,
    (0, 1, 0, 1, 1, 1, 0, 1) : 93,
    (0, 1, 0, 1, 1, 1, 1, 0) : 94,
    (0, 1, 0, 1, 1, 1, 1, 1) : 95,
    (0, 1, 1, 0, 0, 0, 0, 0) : 96,
    (0, 1, 1, 0, 0, 0, 0, 1) : 97,
    (0, 1, 1, 0, 0, 0, 1, 0) : 98,
    (0, 1, 1, 0, 0, 0, 1, 1) : 99,
    (0, 1, 1, 0, 0, 1, 0, 0) : 100,
    (0, 1, 1, 0, 0, 1, 0, 1) : 101,
    (0, 1, 1, 0, 0, 1, 1, 0) : 102,
    (0, 1, 1, 0, 0, 1, 1, 1) : 103,
    (0, 1, 1, 0, 1, 0, 0, 0) : 104,
    (0, 1, 1, 0, 1, 0, 0, 1) : 105,
    (0, 1, 1, 0, 1, 0, 1, 0) : 106,
    (0, 1, 1, 0, 1, 0, 1, 1) : 107,
    (0, 1, 1, 0, 1, 1, 0, 0) : 108,
    (0, 1, 1, 0, 1, 1, 0, 1) : 109,
    (0, 1, 1, 0, 1, 1, 1, 0) : 110,
    (0, 1, 1, 0, 1, 1, 1, 1) : 111,
    (0, 1, 1, 1, 0, 0, 0, 0) : 112,
    (0, 1, 1, 1, 0, 0, 0, 1) : 113,
    (0, 1, 1, 1, 0, 0, 1, 0) : 114,
    (0, 1, 1, 1, 0, 0, 1, 1) : 115,
    (0, 1, 1, 1, 0, 1, 0, 0) : 116,
    (0, 1, 1, 1, 0, 1, 0, 1) : 117,
    (0, 1, 1, 1, 0, 1, 1, 0) : 118,
    (0, 1, 1, 1, 0, 1, 1, 1) : 119,
    (0, 1, 1, 1, 1, 0, 0, 0) : 120,
    (0, 1, 1, 1, 1, 0, 0, 1) : 121,
    (0, 1, 1, 1, 1, 0, 1, 0) : 122,
    (0, 1, 1, 1, 1, 0, 1, 1) : 123,
    (0, 1, 1, 1, 1, 1, 0, 0) : 124,
    (0, 1, 1, 1, 1, 1, 0, 1) : 125,
    (0, 1, 1, 1, 1, 1, 1, 0) : 126,
    (0, 1, 1, 1, 1, 1, 1, 1) : 127,
    (1, 0, 0, 0, 0, 0, 0, 0) : 128,
    (1, 0, 0, 0, 0, 0, 0, 1) : 129,
    (1, 0, 0, 0, 0, 0, 1, 0) : 130,
    (1, 0, 0, 0, 0, 0, 1, 1) : 131,
    (1, 0, 0, 0, 0, 1, 0, 0) : 132,
    (1, 0, 0, 0, 0, 1, 0, 1) : 133,
    (1, 0, 0, 0, 0, 1, 1, 0) : 134,
    (1, 0, 0, 0, 0, 1, 1, 1) : 135,
    (1, 0, 0, 0, 1, 0, 0, 0) : 136,
    (1, 0, 0, 0, 1, 0, 0, 1) : 137,
    (1, 0, 0, 0, 1, 0, 1, 0) : 138,
    (1, 0, 0, 0, 1, 0, 1, 1) : 139,
    (1, 0, 0, 0, 1, 1, 0, 0) : 140,
    (1, 0, 0, 0, 1, 1, 0, 1) : 141,
    (1, 0, 0, 0, 1, 1, 1, 0) : 142,
    (1, 0, 0, 0, 1, 1, 1, 1) : 143,
    (1, 0, 0, 1, 0, 0, 0, 0) : 144,
    (1, 0, 0, 1, 0, 0, 0, 1) : 145,
    (1, 0, 0, 1, 0, 0, 1, 0) : 146,
    (1, 0, 0, 1, 0, 0, 1, 1) : 147,
    (1, 0, 0, 1, 0, 1, 0, 0) : 148,
    (1, 0, 0, 1, 0, 1, 0, 1) : 149,
    (1, 0, 0, 1, 0, 1, 1, 0) : 150,
    (1, 0, 0, 1, 0, 1, 1, 1) : 151,
    (1, 0, 0, 1, 1, 0, 0, 0) : 152,
    (1, 0, 0, 1, 1, 0, 0, 1) : 153,
    (1, 0, 0, 1, 1, 0, 1, 0) : 154,
    (1, 0, 0, 1, 1, 0, 1, 1) : 155,
    (1, 0, 0, 1, 1, 1, 0, 0) : 156,
    (1, 0, 0, 1, 1, 1, 0, 1) : 157,
    (1, 0, 0, 1, 1, 1, 1, 0) : 158,
    (1, 0, 0, 1, 1, 1, 1, 1) : 159,
    (1, 0, 1, 0, 0, 0, 0, 0) : 160,
    (1, 0, 1, 0, 0, 0, 0, 1) : 161,
    (1, 0, 1, 0, 0, 0, 1, 0) : 162,
    (1, 0, 1, 0, 0, 0, 1, 1) : 163,
    (1, 0, 1, 0, 0, 1, 0, 0) : 164,
    (1, 0, 1, 0, 0, 1, 0, 1) : 165,
    (1, 0, 1, 0, 0, 1, 1, 0) : 166,
    (1, 0, 1, 0, 0, 1, 1, 1) : 167,
    (1, 0, 1, 0, 1, 0, 0, 0) : 168,
    (1, 0, 1, 0, 1, 0, 0, 1) : 169,
    (1, 0, 1, 0, 1, 0, 1, 0) : 170,
    (1, 0, 1, 0, 1, 0, 1, 1) : 171,
    (1, 0, 1, 0, 1, 1, 0, 0) : 172,
    (1, 0, 1, 0, 1, 1, 0, 1) : 173,
    (1, 0, 1, 0, 1, 1, 1, 0) : 174,
    (1, 0, 1, 0, 1, 1, 1, 1) : 175,
    (1, 0, 1, 1, 0, 0, 0, 0) : 176,
    (1, 0, 1, 1, 0, 0, 0, 1) : 177,
    (1, 0, 1, 1, 0, 0, 1, 0) : 178,
    (1, 0, 1, 1, 0, 0, 1, 1) : 179,
    (1, 0, 1, 1, 0, 1, 0, 0) : 180,
    (1, 0, 1, 1, 0, 1, 0, 1) : 181,
    (1, 0, 1, 1, 0, 1, 1, 0) : 182,
    (1, 0, 1, 1, 0, 1, 1, 1) : 183,
    (1, 0, 1, 1, 1, 0, 0, 0) : 184,
    (1, 0, 1, 1, 1, 0, 0, 1) : 185,
    (1, 0, 1, 1, 1, 0, 1, 0) : 186,
    (1, 0, 1, 1, 1, 0, 1, 1) : 187,
    (1, 0, 1, 1, 1, 1, 0, 0) : 188,
    (1, 0, 1, 1, 1, 1, 0, 1) : 189,
    (1, 0, 1, 1, 1, 1, 1, 0) : 190,
    (1, 0, 1, 1, 1, 1, 1, 1) : 191,
    (1, 1, 0, 0, 0, 0, 0, 0) : 192,
    (1, 1, 0, 0, 0, 0, 0, 1) : 193,
    (1, 1, 0, 0, 0, 0, 1, 0) : 194,
    (1, 1, 0, 0, 0, 0, 1, 1) : 195,
    (1, 1, 0, 0, 0, 1, 0, 0) : 196,
    (1, 1, 0, 0, 0, 1, 0, 1) : 197,
    (1, 1, 0, 0, 0, 1, 1, 0) : 198,
    (1, 1, 0, 0, 0, 1, 1, 1) : 199,
    (1, 1, 0, 0, 1, 0, 0, 0) : 200,
    (1, 1, 0, 0, 1, 0, 0, 1) : 201,
    (1, 1, 0, 0, 1, 0, 1, 0) : 202,
    (1, 1, 0, 0, 1, 0, 1, 1) : 203,
    (1, 1, 0, 0, 1, 1, 0, 0) : 204,
    (1, 1, 0, 0, 1, 1, 0, 1) : 205,
    (1, 1, 0, 0, 1, 1, 1, 0) : 206,
    (1, 1, 0, 0, 1, 1, 1, 1) : 207,
    (1, 1, 0, 1, 0, 0, 0, 0) : 208,
    (1, 1, 0, 1, 0, 0, 0, 1) : 209,
    (1, 1, 0, 1, 0, 0, 1, 0) : 210,
    (1, 1, 0, 1, 0, 0, 1, 1) : 211,
    (1, 1, 0, 1, 0, 1, 0, 0) : 212,
    (1, 1, 0, 1, 0, 1, 0, 1) : 213,
    (1, 1, 0, 1, 0, 1, 1, 0) : 214,
    (1, 1, 0, 1, 0, 1, 1, 1) : 215,
    (1, 1, 0, 1, 1, 0, 0, 0) : 216,
    (1, 1, 0, 1, 1, 0, 0, 1) : 217,
    (1, 1, 0, 1, 1, 0, 1, 0) : 218,
    (1, 1, 0, 1, 1, 0, 1, 1) : 219,
    (1, 1, 0, 1, 1, 1, 0, 0) : 220,
    (1, 1, 0, 1, 1, 1, 0, 1) : 221,
    (1, 1, 0, 1, 1, 1, 1, 0) : 222,
    (1, 1, 0, 1, 1, 1, 1, 1) : 223,
    (1, 1, 1, 0, 0, 0, 0, 0) : 224,
    (1, 1, 1, 0, 0, 0, 0, 1) : 225,
    (1, 1, 1, 0, 0, 0, 1, 0) : 226,
    (1, 1, 1, 0, 0, 0, 1, 1) : 227,
    (1, 1, 1, 0, 0, 1, 0, 0) : 228,
    (1, 1, 1, 0, 0, 1, 0, 1) : 229,
    (1, 1, 1, 0, 0, 1, 1, 0) : 230,
    (1, 1, 1, 0, 0, 1, 1, 1) : 231,
    (1, 1, 1, 0, 1, 0, 0, 0) : 232,
    (1, 1, 1, 0, 1, 0, 0, 1) : 233,
    (1, 1, 1, 0, 1, 0, 1, 0) : 234,
    (1, 1, 1, 0, 1, 0, 1, 1) : 235,
    (1, 1, 1, 0, 1, 1, 0, 0) : 236,
    (1, 1, 1, 0, 1, 1, 0, 1) : 237,
    (1, 1, 1, 0, 1, 1, 1, 0) : 238,
    (1, 1, 1, 0, 1, 1, 1, 1) : 239,
    (1, 1, 1, 1, 0, 0, 0, 0) : 240,
    (1, 1, 1, 1, 0, 0, 0, 1) : 241,
    (1, 1, 1, 1, 0, 0, 1, 0) : 242,
    (1, 1, 1, 1, 0, 0, 1, 1) : 243,
    (1, 1, 1, 1, 0, 1, 0, 0) : 244,
    (1, 1, 1, 1, 0, 1, 0, 1) : 245,
    (1, 1, 1, 1, 0, 1, 1, 0) : 246,
    (1, 1, 1, 1, 0, 1, 1, 1) : 247,
    (1, 1, 1, 1, 1, 0, 0, 0) : 248,
    (1, 1, 1, 1, 1, 0, 0, 1) : 249,
    (1, 1, 1, 1, 1, 0, 1, 0) : 250,
    (1, 1, 1, 1, 1, 0, 1, 1) : 251,
    (1, 1, 1, 1, 1, 1, 0, 0) : 252,
    (1, 1, 1, 1, 1, 1, 0, 1) : 253,
    (1, 1, 1, 1, 1, 1, 1, 0) : 254,
    (1, 1, 1, 1, 1, 1, 1, 1) : 255
    }

BITTOBYTE_LUT = {
    (0, 0, 0, 0, 0, 0, 0, 0): b'\x00',
    (0, 0, 0, 0, 0, 0, 0, 1): b'\x01',
    (0, 0, 0, 0, 0, 0, 1, 0): b'\x02',
    (0, 0, 0, 0, 0, 0, 1, 1): b'\x03',
    (0, 0, 0, 0, 0, 1, 0, 0): b'\x04',
    (0, 0, 0, 0, 0, 1, 0, 1): b'\x05',
    (0, 0, 0, 0, 0, 1, 1, 0): b'\x06',
    (0, 0, 0, 0, 0, 1, 1, 1): b'\x07',
    (0, 0, 0, 0, 1, 0, 0, 0): b'\x08',
    (0, 0, 0, 0, 1, 0, 0, 1): b'\t',
    (0, 0, 0, 0, 1, 0, 1, 0): b'\n',
    (0, 0, 0, 0, 1, 0, 1, 1): b'\x0b',
    (0, 0, 0, 0, 1, 1, 0, 0): b'\x0c',
    (0, 0, 0, 0, 1, 1, 0, 1): b'\r',
    (0, 0, 0, 0, 1, 1, 1, 0): b'\x0e',
    (0, 0, 0, 0, 1, 1, 1, 1): b'\x0f',
    (0, 0, 0, 1, 0, 0, 0, 0): b'\x10',
    (0, 0, 0, 1, 0, 0, 0, 1): b'\x11',
    (0, 0, 0, 1, 0, 0, 1, 0): b'\x12',
    (0, 0, 0, 1, 0, 0, 1, 1): b'\x13',
    (0, 0, 0, 1, 0, 1, 0, 0): b'\x14',
    (0, 0, 0, 1, 0, 1, 0, 1): b'\x15',
    (0, 0, 0, 1, 0, 1, 1, 0): b'\x16',
    (0, 0, 0, 1, 0, 1, 1, 1): b'\x17',
    (0, 0, 0, 1, 1, 0, 0, 0): b'\x18',
    (0, 0, 0, 1, 1, 0, 0, 1): b'\x19',
    (0, 0, 0, 1, 1, 0, 1, 0): b'\x1a',
    (0, 0, 0, 1, 1, 0, 1, 1): b'\x1b',
    (0, 0, 0, 1, 1, 1, 0, 0): b'\x1c',
    (0, 0, 0, 1, 1, 1, 0, 1): b'\x1d',
    (0, 0, 0, 1, 1, 1, 1, 0): b'\x1e',
    (0, 0, 0, 1, 1, 1, 1, 1): b'\x1f',
    (0, 0, 1, 0, 0, 0, 0, 0): b' ',
    (0, 0, 1, 0, 0, 0, 0, 1): b'!',
    (0, 0, 1, 0, 0, 0, 1, 0): b'"',
    (0, 0, 1, 0, 0, 0, 1, 1): b'#',
    (0, 0, 1, 0, 0, 1, 0, 0): b'$',
    (0, 0, 1, 0, 0, 1, 0, 1): b'%',
    (0, 0, 1, 0, 0, 1, 1, 0): b'&',
    (0, 0, 1, 0, 0, 1, 1, 1): b"'",
    (0, 0, 1, 0, 1, 0, 0, 0): b'(',
    (0, 0, 1, 0, 1, 0, 0, 1): b')',
    (0, 0, 1, 0, 1, 0, 1, 0): b'*',
    (0, 0, 1, 0, 1, 0, 1, 1): b'+',
    (0, 0, 1, 0, 1, 1, 0, 0): b',',
    (0, 0, 1, 0, 1, 1, 0, 1): b'-',
    (0, 0, 1, 0, 1, 1, 1, 0): b'.',
    (0, 0, 1, 0, 1, 1, 1, 1): b'/',
    (0, 0, 1, 1, 0, 0, 0, 0): b'0',
    (0, 0, 1, 1, 0, 0, 0, 1): b'1',
    (0, 0, 1, 1, 0, 0, 1, 0): b'2',
    (0, 0, 1, 1, 0, 0, 1, 1): b'3',
    (0, 0, 1, 1, 0, 1, 0, 0): b'4',
    (0, 0, 1, 1, 0, 1, 0, 1): b'5',
    (0, 0, 1, 1, 0, 1, 1, 0): b'6',
    (0, 0, 1, 1, 0, 1, 1, 1): b'7',
    (0, 0, 1, 1, 1, 0, 0, 0): b'8',
    (0, 0, 1, 1, 1, 0, 0, 1): b'9',
    (0, 0, 1, 1, 1, 0, 1, 0): b':',
    (0, 0, 1, 1, 1, 0, 1, 1): b';',
    (0, 0, 1, 1, 1, 1, 0, 0): b'<',
    (0, 0, 1, 1, 1, 1, 0, 1): b'=',
    (0, 0, 1, 1, 1, 1, 1, 0): b'>',
    (0, 0, 1, 1, 1, 1, 1, 1): b'?',
    (0, 1, 0, 0, 0, 0, 0, 0): b'@',
    (0, 1, 0, 0, 0, 0, 0, 1): b'A',
    (0, 1, 0, 0, 0, 0, 1, 0): b'B',
    (0, 1, 0, 0, 0, 0, 1, 1): b'C',
    (0, 1, 0, 0, 0, 1, 0, 0): b'D',
    (0, 1, 0, 0, 0, 1, 0, 1): b'E',
    (0, 1, 0, 0, 0, 1, 1, 0): b'F',
    (0, 1, 0, 0, 0, 1, 1, 1): b'G',
    (0, 1, 0, 0, 1, 0, 0, 0): b'H',
    (0, 1, 0, 0, 1, 0, 0, 1): b'I',
    (0, 1, 0, 0, 1, 0, 1, 0): b'J',
    (0, 1, 0, 0, 1, 0, 1, 1): b'K',
    (0, 1, 0, 0, 1, 1, 0, 0): b'L',
    (0, 1, 0, 0, 1, 1, 0, 1): b'M',
    (0, 1, 0, 0, 1, 1, 1, 0): b'N',
    (0, 1, 0, 0, 1, 1, 1, 1): b'O',
    (0, 1, 0, 1, 0, 0, 0, 0): b'P',
    (0, 1, 0, 1, 0, 0, 0, 1): b'Q',
    (0, 1, 0, 1, 0, 0, 1, 0): b'R',
    (0, 1, 0, 1, 0, 0, 1, 1): b'S',
    (0, 1, 0, 1, 0, 1, 0, 0): b'T',
    (0, 1, 0, 1, 0, 1, 0, 1): b'U',
    (0, 1, 0, 1, 0, 1, 1, 0): b'V',
    (0, 1, 0, 1, 0, 1, 1, 1): b'W',
    (0, 1, 0, 1, 1, 0, 0, 0): b'X',
    (0, 1, 0, 1, 1, 0, 0, 1): b'Y',
    (0, 1, 0, 1, 1, 0, 1, 0): b'Z',
    (0, 1, 0, 1, 1, 0, 1, 1): b'[',
    (0, 1, 0, 1, 1, 1, 0, 0): b'\\',
    (0, 1, 0, 1, 1, 1, 0, 1): b']',
    (0, 1, 0, 1, 1, 1, 1, 0): b'^',
    (0, 1, 0, 1, 1, 1, 1, 1): b'_',
    (0, 1, 1, 0, 0, 0, 0, 0): b'`',
    (0, 1, 1, 0, 0, 0, 0, 1): b'a',
    (0, 1, 1, 0, 0, 0, 1, 0): b'b',
    (0, 1, 1, 0, 0, 0, 1, 1): b'c',
    (0, 1, 1, 0, 0, 1, 0, 0): b'd',
    (0, 1, 1, 0, 0, 1, 0, 1): b'e',
    (0, 1, 1, 0, 0, 1, 1, 0): b'f',
    (0, 1, 1, 0, 0, 1, 1, 1): b'g',
    (0, 1, 1, 0, 1, 0, 0, 0): b'h',
    (0, 1, 1, 0, 1, 0, 0, 1): b'i',
    (0, 1, 1, 0, 1, 0, 1, 0): b'j',
    (0, 1, 1, 0, 1, 0, 1, 1): b'k',
    (0, 1, 1, 0, 1, 1, 0, 0): b'l',
    (0, 1, 1, 0, 1, 1, 0, 1): b'm',
    (0, 1, 1, 0, 1, 1, 1, 0): b'n',
    (0, 1, 1, 0, 1, 1, 1, 1): b'o',
    (0, 1, 1, 1, 0, 0, 0, 0): b'p',
    (0, 1, 1, 1, 0, 0, 0, 1): b'q',
    (0, 1, 1, 1, 0, 0, 1, 0): b'r',
    (0, 1, 1, 1, 0, 0, 1, 1): b's',
    (0, 1, 1, 1, 0, 1, 0, 0): b't',
    (0, 1, 1, 1, 0, 1, 0, 1): b'u',
    (0, 1, 1, 1, 0, 1, 1, 0): b'v',
    (0, 1, 1, 1, 0, 1, 1, 1): b'w',
    (0, 1, 1, 1, 1, 0, 0, 0): b'x',
    (0, 1, 1, 1, 1, 0, 0, 1): b'y',
    (0, 1, 1, 1, 1, 0, 1, 0): b'z',
    (0, 1, 1, 1, 1, 0, 1, 1): b'{',
    (0, 1, 1, 1, 1, 1, 0, 0): b'|',
    (0, 1, 1, 1, 1, 1, 0, 1): b'}',
    (0, 1, 1, 1, 1, 1, 1, 0): b'~',
    (0, 1, 1, 1, 1, 1, 1, 1): b'\x7f',
    (1, 0, 0, 0, 0, 0, 0, 0): b'\x80',
    (1, 0, 0, 0, 0, 0, 0, 1): b'\x81',
    (1, 0, 0, 0, 0, 0, 1, 0): b'\x82',
    (1, 0, 0, 0, 0, 0, 1, 1): b'\x83',
    (1, 0, 0, 0, 0, 1, 0, 0): b'\x84',
    (1, 0, 0, 0, 0, 1, 0, 1): b'\x85',
    (1, 0, 0, 0, 0, 1, 1, 0): b'\x86',
    (1, 0, 0, 0, 0, 1, 1, 1): b'\x87',
    (1, 0, 0, 0, 1, 0, 0, 0): b'\x88',
    (1, 0, 0, 0, 1, 0, 0, 1): b'\x89',
    (1, 0, 0, 0, 1, 0, 1, 0): b'\x8a',
    (1, 0, 0, 0, 1, 0, 1, 1): b'\x8b',
    (1, 0, 0, 0, 1, 1, 0, 0): b'\x8c',
    (1, 0, 0, 0, 1, 1, 0, 1): b'\x8d',
    (1, 0, 0, 0, 1, 1, 1, 0): b'\x8e',
    (1, 0, 0, 0, 1, 1, 1, 1): b'\x8f',
    (1, 0, 0, 1, 0, 0, 0, 0): b'\x90',
    (1, 0, 0, 1, 0, 0, 0, 1): b'\x91',
    (1, 0, 0, 1, 0, 0, 1, 0): b'\x92',
    (1, 0, 0, 1, 0, 0, 1, 1): b'\x93',
    (1, 0, 0, 1, 0, 1, 0, 0): b'\x94',
    (1, 0, 0, 1, 0, 1, 0, 1): b'\x95',
    (1, 0, 0, 1, 0, 1, 1, 0): b'\x96',
    (1, 0, 0, 1, 0, 1, 1, 1): b'\x97',
    (1, 0, 0, 1, 1, 0, 0, 0): b'\x98',
    (1, 0, 0, 1, 1, 0, 0, 1): b'\x99',
    (1, 0, 0, 1, 1, 0, 1, 0): b'\x9a',
    (1, 0, 0, 1, 1, 0, 1, 1): b'\x9b',
    (1, 0, 0, 1, 1, 1, 0, 0): b'\x9c',
    (1, 0, 0, 1, 1, 1, 0, 1): b'\x9d',
    (1, 0, 0, 1, 1, 1, 1, 0): b'\x9e',
    (1, 0, 0, 1, 1, 1, 1, 1): b'\x9f',
    (1, 0, 1, 0, 0, 0, 0, 0): b'\xa0',
    (1, 0, 1, 0, 0, 0, 0, 1): b'\xa1',
    (1, 0, 1, 0, 0, 0, 1, 0): b'\xa2',
    (1, 0, 1, 0, 0, 0, 1, 1): b'\xa3',
    (1, 0, 1, 0, 0, 1, 0, 0): b'\xa4',
    (1, 0, 1, 0, 0, 1, 0, 1): b'\xa5',
    (1, 0, 1, 0, 0, 1, 1, 0): b'\xa6',
    (1, 0, 1, 0, 0, 1, 1, 1): b'\xa7',
    (1, 0, 1, 0, 1, 0, 0, 0): b'\xa8',
    (1, 0, 1, 0, 1, 0, 0, 1): b'\xa9',
    (1, 0, 1, 0, 1, 0, 1, 0): b'\xaa',
    (1, 0, 1, 0, 1, 0, 1, 1): b'\xab',
    (1, 0, 1, 0, 1, 1, 0, 0): b'\xac',
    (1, 0, 1, 0, 1, 1, 0, 1): b'\xad',
    (1, 0, 1, 0, 1, 1, 1, 0): b'\xae',
    (1, 0, 1, 0, 1, 1, 1, 1): b'\xaf',
    (1, 0, 1, 1, 0, 0, 0, 0): b'\xb0',
    (1, 0, 1, 1, 0, 0, 0, 1): b'\xb1',
    (1, 0, 1, 1, 0, 0, 1, 0): b'\xb2',
    (1, 0, 1, 1, 0, 0, 1, 1): b'\xb3',
    (1, 0, 1, 1, 0, 1, 0, 0): b'\xb4',
    (1, 0, 1, 1, 0, 1, 0, 1): b'\xb5',
    (1, 0, 1, 1, 0, 1, 1, 0): b'\xb6',
    (1, 0, 1, 1, 0, 1, 1, 1): b'\xb7',
    (1, 0, 1, 1, 1, 0, 0, 0): b'\xb8',
    (1, 0, 1, 1, 1, 0, 0, 1): b'\xb9',
    (1, 0, 1, 1, 1, 0, 1, 0): b'\xba',
    (1, 0, 1, 1, 1, 0, 1, 1): b'\xbb',
    (1, 0, 1, 1, 1, 1, 0, 0): b'\xbc',
    (1, 0, 1, 1, 1, 1, 0, 1): b'\xbd',
    (1, 0, 1, 1, 1, 1, 1, 0): b'\xbe',
    (1, 0, 1, 1, 1, 1, 1, 1): b'\xbf',
    (1, 1, 0, 0, 0, 0, 0, 0): b'\xc0',
    (1, 1, 0, 0, 0, 0, 0, 1): b'\xc1',
    (1, 1, 0, 0, 0, 0, 1, 0): b'\xc2',
    (1, 1, 0, 0, 0, 0, 1, 1): b'\xc3',
    (1, 1, 0, 0, 0, 1, 0, 0): b'\xc4',
    (1, 1, 0, 0, 0, 1, 0, 1): b'\xc5',
    (1, 1, 0, 0, 0, 1, 1, 0): b'\xc6',
    (1, 1, 0, 0, 0, 1, 1, 1): b'\xc7',
    (1, 1, 0, 0, 1, 0, 0, 0): b'\xc8',
    (1, 1, 0, 0, 1, 0, 0, 1): b'\xc9',
    (1, 1, 0, 0, 1, 0, 1, 0): b'\xca',
    (1, 1, 0, 0, 1, 0, 1, 1): b'\xcb',
    (1, 1, 0, 0, 1, 1, 0, 0): b'\xcc',
    (1, 1, 0, 0, 1, 1, 0, 1): b'\xcd',
    (1, 1, 0, 0, 1, 1, 1, 0): b'\xce',
    (1, 1, 0, 0, 1, 1, 1, 1): b'\xcf',
    (1, 1, 0, 1, 0, 0, 0, 0): b'\xd0',
    (1, 1, 0, 1, 0, 0, 0, 1): b'\xd1',
    (1, 1, 0, 1, 0, 0, 1, 0): b'\xd2',
    (1, 1, 0, 1, 0, 0, 1, 1): b'\xd3',
    (1, 1, 0, 1, 0, 1, 0, 0): b'\xd4',
    (1, 1, 0, 1, 0, 1, 0, 1): b'\xd5',
    (1, 1, 0, 1, 0, 1, 1, 0): b'\xd6',
    (1, 1, 0, 1, 0, 1, 1, 1): b'\xd7',
    (1, 1, 0, 1, 1, 0, 0, 0): b'\xd8',
    (1, 1, 0, 1, 1, 0, 0, 1): b'\xd9',
    (1, 1, 0, 1, 1, 0, 1, 0): b'\xda',
    (1, 1, 0, 1, 1, 0, 1, 1): b'\xdb',
    (1, 1, 0, 1, 1, 1, 0, 0): b'\xdc',
    (1, 1, 0, 1, 1, 1, 0, 1): b'\xdd',
    (1, 1, 0, 1, 1, 1, 1, 0): b'\xde',
    (1, 1, 0, 1, 1, 1, 1, 1): b'\xdf',
    (1, 1, 1, 0, 0, 0, 0, 0): b'\xe0',
    (1, 1, 1, 0, 0, 0, 0, 1): b'\xe1',
    (1, 1, 1, 0, 0, 0, 1, 0): b'\xe2',
    (1, 1, 1, 0, 0, 0, 1, 1): b'\xe3',
    (1, 1, 1, 0, 0, 1, 0, 0): b'\xe4',
    (1, 1, 1, 0, 0, 1, 0, 1): b'\xe5',
    (1, 1, 1, 0, 0, 1, 1, 0): b'\xe6',
    (1, 1, 1, 0, 0, 1, 1, 1): b'\xe7',
    (1, 1, 1, 0, 1, 0, 0, 0): b'\xe8',
    (1, 1, 1, 0, 1, 0, 0, 1): b'\xe9',
    (1, 1, 1, 0, 1, 0, 1, 0): b'\xea',
    (1, 1, 1, 0, 1, 0, 1, 1): b'\xeb',
    (1, 1, 1, 0, 1, 1, 0, 0): b'\xec',
    (1, 1, 1, 0, 1, 1, 0, 1): b'\xed',
    (1, 1, 1, 0, 1, 1, 1, 0): b'\xee',
    (1, 1, 1, 0, 1, 1, 1, 1): b'\xef',
    (1, 1, 1, 1, 0, 0, 0, 0): b'\xf0',
    (1, 1, 1, 1, 0, 0, 0, 1): b'\xf1',
    (1, 1, 1, 1, 0, 0, 1, 0): b'\xf2',
    (1, 1, 1, 1, 0, 0, 1, 1): b'\xf3',
    (1, 1, 1, 1, 0, 1, 0, 0): b'\xf4',
    (1, 1, 1, 1, 0, 1, 0, 1): b'\xf5',
    (1, 1, 1, 1, 0, 1, 1, 0): b'\xf6',
    (1, 1, 1, 1, 0, 1, 1, 1): b'\xf7',
    (1, 1, 1, 1, 1, 0, 0, 0): b'\xf8',
    (1, 1, 1, 1, 1, 0, 0, 1): b'\xf9',
    (1, 1, 1, 1, 1, 0, 1, 0): b'\xfa',
    (1, 1, 1, 1, 1, 0, 1, 1): b'\xfb',
    (1, 1, 1, 1, 1, 1, 0, 0): b'\xfc',
    (1, 1, 1, 1, 1, 1, 0, 1): b'\xfd',
    (1, 1, 1, 1, 1, 1, 1, 0): b'\xfe',
    (1, 1, 1, 1, 1, 1, 1, 1): b'\xff'
    }

def bytes_to_bitlist(buf):
    """Convert a bytes string to a list of bits -0 or 1-

    Args:
        buf (bytes) : bytes string

    Returns:
        bitlist (list of integer) : list of 0 and 1

    Raises:
        KeyError : if `s' is not bytes
    """
    bitlist = []
    [bitlist.extend(ARRTOBIT_LUT[val]) for val in buf]
    return bitlist

def bitlist_to_bytes(bitlist):
    """Convert an iterable of bits -0 or 1- to a bytes string

    Args:
        bitlist (iterable of integer) : iterable of 0 and 1

    Returns:
        buf (bytes) : bytes string

    Raises:
        KeyError : if bitlist contains invalid values
    """
    buf = []
    # cast the iterable to a tuple for dict LU
    bitlist = tuple(bitlist)
    trail = len(bitlist) % 8
    if trail:
        [buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
            for i in range(0, len(bitlist)-trail, 8)]
        buf.append(BITTOARR_LUT[bitlist[-trail:] + (8-trail) * (0, )] )
        return bytes(buf)
    else:
        [buf.append(BITTOARR_LUT[bitlist[i:i+8]]) \
            for i in range(0, len(bitlist), 8)]
        return bytes(buf)

#------------------------------------------------------------------------------#
# bytes buffer functions
#------------------------------------------------------------------------------#

def bytes_lshift(buf=b'', bitlen=0):
    """Shift left a bytes buffer of `bitlen' bits

    Args:
        buf (bytes) : bytes string
        bitlen (int) : length in bits

    Returns:
        buf_sh (bytes) : shifted bytes string
    """
    if bitlen > 8*len(buf):
        bitlen = 8*len(buf)
    byte_len, bit_len = bitlen>>3, bitlen%8
    # full byte shifting
    buf_sh = buf[byte_len:]
    bl = 8 * len(buf_sh)
    # bit shifting
    if bitlen:
        return uint_to_bytes((bytes_to_uint(buf_sh, bl) << bit_len) & \
                             ((1<<bl)-1), bl)
    else:
        return buf_sh

def bytes_zero_last_bits(buf, bitlen=1):
    """Zero the `bitlen' last bits of the bytes buffer `buf'

    Args:
        buf (bytes) : bytes string
        bitlen (integer) : length in bits

    Returns:
        buf_z (bytes) : bytes buffer with last bits set to zero

    Raises:
        PycrateErr : if `bitlen' is not between 1 and 7 inclusive
    """
    if not 0 < bitlen < 8:
        raise(PycrateErr('bitlen must be between 0 and 8, not inclusive'))
    return buf[:-1] + bytes( (buf[-1] & (0x100-(1<<bitlen)), ) )

def bytes_to_bytelist(buf):
    """Convert a bytes buffer to a list of bytes -uint8-

    Args:
        buf (bytes) : bytes string

    Returns:
        bytelist (list of integers) : list of uint8 values (0<=X<=255)
    """
    return list(buf)

def bytelist_to_bytes(bytelist):
    """Convert a list of bytes -uint8- to a bytes buffer

    Args:
        bytelist (list of integer) : list of uint8 values (0<=X<=255)

    Returns:
        buf (bytes) : bytes string
    """
    return bytes(bytelist)

#------------------------------------------------------------------------------#
# bytelist functions
#------------------------------------------------------------------------------#

def bytelist_lshift(bytelist, bitlen=0):
    """Shift left a byte list of `bitlen' bits

    Args:
        bytelist (iterable of integer) : iterable of uint8
        bitlen (integer) : length in bits

    Returns:
        bytelist_sh (list of integer) : list of uint8
    """
    return list(bytes_lshift(bytes(bytelist), bitlen))

def uint_to_bytelist(val, bitlen=1):
    """Convert an unsigned integer to a bytelist of `bitlen' length in bits,
    uint with most significant bit leftmost

    Args:
        val (integer) : unsigned integer
        bitlen (integer) : length in bits

    Returns:
        bytelist (list of integer) : list of uint8 values (0<=X<=255)

    Raises:
        PycrateErr : if `bitlen' is not strictly positive
    """
    return list(uint_to_bytes(val, bitlen))

def bytelist_to_uint(bytelist, bitlen=1):
    """Convert bytelist to an unsigned integer of `bitlen' length in bits,
    uint with most significant bit leftmost

    Args:
        val (integer) : unsigned integer
        bitlen (integer) : length in bits

    Returns:
        bytelist (list of integer) : list of uint8 values (0<=X<=255)

    Raises:
        PycrateErr : if `bitlen' is not strictly positive
    """
    return bytes_to_uint(bytes(bytelist), bitlen)

#------------------------------------------------------------------------------#
# integer functions
#------------------------------------------------------------------------------#

def bytes_to_uint(buf, bitlen=1):
    """Convert the leftmost bits of a bytes buffer to an unsigned integer,
    uint with most significant bit leftmost

    Args:
        buf (bytes) : bytes string
        bitlen (integer) : length in bits

    Returns:
        uint (integer) : unsigned integer value

    Raises:
        PycrateErr : if `bitlen' is not strictly positive or if `buf' is not
        long enough
    """
    # leverage Python3 built-in conversion: int.from_bytes()
    if bitlen <= 0:
        raise(PycrateErr('bitlen must be strictly positive'))
    len_byte, len_bit = bitlen>>3, bitlen%8
    if len_bit:
        if len(buf) < len_byte + 1:
            raise(PycrateErr('bytes buffer not long enough'))
        else:
            return int.from_bytes(buf[:len_byte+1], 'big') >> (8-len_bit)
    else:
        if len(buf) < len_byte:
            raise(PycrateErr('bytes buffer not long enough'))
        elif len_byte == 1:
            return buf[0]
        else:
            return int.from_bytes(buf[:len_byte], 'big')

def uint_to_bytes(val, bitlen=1):
    """Convert an unsigned integer to a bytes buffer of given length in bits,
    uint with most significant bit leftmost

    Args:
        val (integer) : unsigned integer
        bitlen (integer) : length in bits

    Returns:
        buf (bytes) : bytes string

    Raises:
        PycrateErr : if `bitlen' is not strictly positive
    """
    # Python3 built-in conversion: int.to_bytes()
    if bitlen <= 0:
        raise(PycrateErr('bitlen must be strictly positive'))
    len_byte, len_bit = bitlen>>3, bitlen % 8
    # if len_bit, need padding bits appended rightmost
    if val >= (1<<bitlen):
        if len_bit:
            return len_byte * b'\xff' + bchr(0x100-(1<<(8-len_bit)))
        else:
            return len_byte * b'\xff'
    elif len_bit == 0:
        if len_byte == 1:
            return bchr(val)
        else:
            if _WITH_MPZ and isinstance(val, _MPZ_T):
                return int(val).to_bytes(len_byte, 'big')
            else:
                return val.to_bytes(len_byte, 'big')
    else:
        if _WITH_MPZ and isinstance(val, _MPZ_T):
            return int(val<<(8-len_bit)).to_bytes(len_byte+1, 'big')
        else:
            return (val<<(8-len_bit)).to_bytes(len_byte+1, 'big')

def bytes_to_uint_le(buf, bitlen=8):
    """Convert the leftmost bits of a bytes buffer to an unsigned integer in
    little endian format (least significant byte leftmost)

    Args:
        buf (bytes) : bytes string
        bitlen (integer) : length in bits, must be a multiple of 8

    Returns:
        uint (integer) : unsigned integer value

    Raises:
        PycrateErr : if `bitlen' is not strictly positive or not byte-aligned
            or if `buf' is not long enough
    """
    # leverage Python3 built-in conversion: int.from_bytes()
    if bitlen <= 0 or bitlen%8:
        raise(PycrateErr('invalid bitlen for little endian uint: {0}'\
                         .format(bitlen)))
    len_byte = bitlen>>3
    #
    if len(buf) < len_byte:
        raise(PycrateErr('bytes buffer not long enough'))
    elif len_byte == 1:
        return buf[0]
    else:
        return int.from_bytes(buf[:len_byte], 'little')

def uint_le_to_bytes(val, bitlen=8):
    """Convert an unsigned integer to a bytes buffer of given length in bits,
    uint in little endian format (least significant byte leftmost)

    Args:
        val (integer) : unsigned integer
        bitlen (integer) : length in bits, must be a multiple of 8

    Returns:
        buf (bytes) : bytes string

    Raises:
        PycrateErr : if `bitlen' is not strictly positive or not byte-aligned
    """
    # Python3 built-in conversion: int.to_bytes()
    if bitlen <= 0 or bitlen%8:
        raise(PycrateErr('invalid bitlen for little endian uint: {0}'\
                         .format(bitlen)))
    len_byte = bitlen>>3
    #
    if val >= (1<<bitlen):
        return len_byte * b'\xff'
    elif len_byte == 1:
        return bchr(val)
    else:
        if _WITH_MPZ and isinstance(val, _MPZ_T):
            return int(val).to_bytes(len_byte, 'little')
        else:
            return val.to_bytes(len_byte, 'little')

def decompose_uint(mul=0x100, val=0):
    """Decompose a value in a list of factors of `mul'

    decompose_uint(1<<X, Y) -> [a, b, c, d ...]
        where Y = a + (b << X) + (c << 2X) + (d << 3X) ...
    or
    decompose_uint(X', Y) -> [a, b, c, d ...]
        where Y = a + b * X' + c * X'^2 + d*X'^3 ...

    Args:
        mul (integer) : unsigned integer used as factor
        val (integer) : unsigned integer to be factored

    Returns:
        dec (list of integers) : list of factors
    """
    # benefit from Python built-in int() which is pretty fast
    if mul == 2:
        dec = list(map(int, bin(val)[2:]))
        dec.reverse()
        return dec
    elif mul == 16 and val >= 10000000:
        h = hex(val)[2:]
        dec = list(map(int, h, len(h)*[16]))
        dec.reverse()
        return dec
    # decompose simply by iterative division
    else:
        dec = [ int(val % mul) ]
        while val >= mul:
            val //= mul
            dec.append( int(val % mul) )
        return dec

def swap_uint(uint, bitlen):
    """Swap the endianness of the unsigned integer uint of length bitlen

    Args:
        uint (unsigned integer)
        bitlen (unsigned integer)

    Returns:
        uint (unsigned integer)
    """
    if bitlen < 0 or bitlen % 8:
        raise(PycrateErr('invalid bitlen of little endian uint: {0}'\
              .format(bitlen)))
    len_byte = bitlen>>3
    return int.from_bytes(uint.to_bytes(len_byte, byteorder='little'), byteorder='big')

#------------------------------------------------------------------------------#
# concatenation
#------------------------------------------------------------------------------#

def bytes_lshift_bnd(buf, buflen=8, shlen=1):
    """Shift left of `shlen' bits the bytes buffer `buf' of length in bits
    `buflen' with 0 < shlen < 8

    provide the heading value of `shlen' bits that leaves the buffer
            the shifted buffer, fully byte-aligned (can be of size 0)
            the trailing value of remaining bits (can be None)

    Args:
        buf (bytes) : bytes string
        buflen (integer) : length in bits of the bytes buffer
        shlen (integer) : value of the shift, between 1 and 7

    Returns:
        tuple of (integer, bytes, integer or None)
    """
    if buflen <= shlen:
        # only heading bits
        head = (buf[0] & (0x100 - (1<<(8-buflen)))) >> (8-shlen)
        return head, b'', None
    elif buflen < 8 + shlen:
        # only heading and trailing bits
        head = buf[0] >> (8-shlen)
        buf = bytes_lshift(buf, shlen)
        trail = buf[0] & (0x100 - (1<<(8-buflen+shlen)))
        return head, b'', trail
    #
    head = buf[0]>>(8-shlen)
    buf = bytes_lshift(buf, shlen)
    restlen = buflen % 8
    if restlen == 0:
        trail = buf[-1]
        buf = buf[:-1]
    elif restlen < shlen:
        trail = buf[-2] & (0x100 - (1<<(shlen-restlen)))
        buf = buf[:-2]
    elif restlen == shlen:
        trail = None
        buf = buf[:-1]
    else:
        trail = buf[-1] & (0x100 - (1<<(8+shlen-restlen)))
        buf = buf[:-1]
    return head, buf, trail

TYPE_BYTES  = 1
TYPE_UINT = 2
TYPE_INT  = 3
TYPE_UINT_LE = 12
TYPE_INT_LE = 13
#
FMT_INT   = {
    8 : 'b',
    16: 'h',
    32: 'i',
    64: 'q'
    }
FMT_UINT  = {
    8 : 'B',
    16: 'H',
    32: 'I',
    64: 'Q'
    }
FMT_LUT   = {
    2: FMT_UINT,
    3: FMT_INT,
    12: FMT_UINT,
    13: FMT_INT
    }
#
PACK_FMT_BE = 0
PACK_FMT_LE = 1

def pack_val(*val):
    """Packs heterogenous bytes buffer and (un)signed integers, all with a given
    length in bits, to a resulting bytes buffer

    Args:
        val (tuple) : tuple of (type, value, bitlen)
            type must be TYPE_BYTES, TYPE_UINT, TYPE_UINT_LE, TYPE_INT or TYPE_INT_LE
            value must be a bytes string or an integer, according to type
            bitlen must be an integer over 0

            warning: for TYPE_UINT_LE and TYPE_INT_LE, bitlen must be a multiple
            of 8 (hence the value will be byte-aligned)

    Returns:
        buf (tuple of (bytes, integer)) : a tuple containing the actual
            resulting bytes string and the length in bits

    Example:
        pack_val( (TYPE_BYTES, b'AAAA\xC0', 34),
                  (TYPE_UINT, 2500, 32),
                  (TYPE_UINT, 10000000000, 64),
                  (TYPE_INT, -1, 8),
                  (TYPE_BYTES, b'bbbbbb', 48),
                  (TYPE_INT, -2000, 54),
                  (TYPE_UINT, 1, 2),
                  (TYPE_BYTES, b'\0', 7) )
            -> (b'AAAA\xc0\x00\x02q\x00\x00\x00\x00\x95\x02\xf9\x00?'\
                '\xd8\x98\x98\x98\x98\x98?\xff\xff\xff\xff\xf80@\x00',
                249)
    """
    # global resulting byte buffer
    concat, len_bit = [], 0
    # junction byte when unaligned values are concatenated
    junc = None
    # cumulative processing for int / uint
    pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0

    for v in val:
        #print('val     : {0}, {1}, {2}'.format(*v))
        #print('pack    : fmt {0}, val {1}'.format(pack_fmt, pack_val))
        #print('junc    : {0}'.format(junc))
        #print('len_bit : {0}'.format(len_bit))
        #print('concat  : {0}'.format(concat))
        #print('')
        #
        rest_bit = len_bit%8
        #
        # 0) bypass null field
        if v[2] == 0:
            pass
        #
        # 1) cumulative processing for 8/16/32/64 bits big endian (u)int
        elif v[0] in (TYPE_INT, TYPE_UINT) and v[2] in (8, 16, 32, 64):
            if pack_end == PACK_FMT_LE and pack_fmt is not None:
                # a) append previous integers that were little endian
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
                    # complete the junction byte and append it
                    # with the shifted buffer
                    len_bit += pack_len
                    if buf:
                        # heading bits, buffer and potential trailing bits
                        concat.extend( (bchr(junc + head), buf) )
                        junc = trail
                    elif trail is not None:
                        # heading bits and potential trailing bits
                        concat.append( bchr(junc + head) )
                        junc = trail
                    elif not len_bit % 8:
                        # heading bits only
                        concat.append( bchr(junc + head) )
                        junc = None
                    else:
                        # no buf and no trailing bits
                        junc += head
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) accumulate value into pack_val
            if pack_fmt is None:
                pack_end = PACK_FMT_BE
                pack_fmt = ['>', FMT_LUT[v[0]][v[2]]]
                pack_val = [v[1]]
            else:
                pack_fmt.append( FMT_LUT[v[0]][v[2]] )
                pack_val.append( v[1] )
            pack_len += v[2]
        #
        # 2) cumulative processing for 8/16/32/64 bits little endian (u)int
        elif v[0] in (TYPE_INT_LE, TYPE_UINT_LE) and v[2] in (8, 16, 32, 64):
            # a) append previous integers if were big endian
            if pack_end == PACK_FMT_BE and pack_fmt is not None:
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
                    # complete the junction byte and append it
                    # with the shifted buffer
                    len_bit += pack_len
                    if buf:
                        # heading bits, buffer and potential trailing bits
                        concat.extend( (bchr(junc + head), buf) )
                        junc = trail
                    elif trail is not None:
                        # heading bits and potential trailing bits
                        concat.append( bchr(junc + head) )
                        junc = trail
                    elif not len_bit % 8:
                        # heading bits only
                        concat.append( bchr(junc + head) )
                        junc = None
                    else:
                        # no buf and no trailing bits
                        junc += head
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) accumulate value into pack_val
            if pack_fmt is None:
                pack_end = PACK_FMT_LE
                pack_fmt = ['<', FMT_LUT[v[0]][v[2]]]
                pack_val = [v[1]]
            else:
                pack_fmt.append( FMT_LUT[v[0]][v[2]] )
                pack_val.append( v[1] )
            pack_len += v[2]
        #
        # 3) standard processing for bytes buffer
        elif v[0] == TYPE_BYTES:
            # a) append pack_val first, if exist
            if pack_fmt is not None:
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                    #
                    concat.append(v[1][:v[2]>>3])
                    if v[2]%8:
                        # remaining bits goes to junction byte
                        junc = (v[1][v[2]>>3]) & (0x100 - (1<<(8-v[2]%8)))
                    len_bit += v[2]
                #
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    if v[2] % 8:
                        buf = pack_buf + v[1][:1+(v[2]>>3)]
                    else:
                        buf = pack_buf + v[1][:v[2]>>3]
                    buflen = pack_len + v[2]
                    head, buf, trail = bytes_lshift_bnd(buf, buflen, 8-rest_bit)
                    # complete the junction byte and append it
                    # with the shifted buffer
                    len_bit += buflen
                    if buf:
                        # heading bits, buffer and potential trailing bits
                        concat.extend( (bchr(junc + head), buf) )
                        junc = trail
                    elif trail is not None:
                        # heading bits and potential trailing bits
                        concat.append( bchr(junc + head) )
                        junc = trail
                    elif not len_bit % 8:
                        # heading bits only
                        concat.append( bchr(junc + head) )
                        junc = None
                    else:
                        # no buf and no trailing bits
                        junc += head
                #
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) nothing to pack
            elif rest_bit == 0:
                # b.a) aligned access
                assert( junc is None )
                if v[2] < 8:
                    junc = v[1][0] & (0x100 - (1<<(8-v[2])))
                else:
                    concat.append( v[1][:v[2]>>3] )
                    if v[2] % 8:
                        # remaining bits goes to junction byte
                        junc = (v[1][v[2]>>3]) & (0x100 - (1<<(8-v[2]%8)))
                len_bit += v[2]
            #
            else:
                # b.b) unaligned access
                assert( 0 <= junc < 256 )
                if v[2] % 8:
                    head, buf, trail = bytes_lshift_bnd(v[1][:1+(v[2]>>3)],
                                                        v[2], 8-rest_bit)
                else:
                    head, buf, trail = bytes_lshift_bnd(v[1][:v[2]>>3],
                                                        v[2], 8-rest_bit)
                # complete the junction byte and append it
                # with the shifted buffer
                len_bit += v[2]
                if buf:
                    # heading bits, buffer and potential trailing bits
                    concat.extend( (bchr(junc + head), buf) )
                    junc = trail
                elif trail is not None:
                    # heading bits and potential trailing bits
                    concat.append( bchr(junc + head) )
                    junc = trail
                elif not len_bit % 8:
                    # heading bits only
                    concat.append( bchr(junc + head) )
                    junc = None
                else:
                    # no buf and no trailing bits, only some more junction bits
                    junc += head
        #
        # 3) standard processing for uint
        elif v[0] == TYPE_UINT:
            # a) append pack_val first, if exist
            if pack_fmt is not None:
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                    #
                    buf = uint_to_bytes(v[1], v[2])
                    concat.append(buf[:v[2]>>3])
                    if v[2]%8:
                        # remaining bits goes to junction byte
                        junc = buf[v[2]>>3]
                    len_bit += v[2]
                #
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    # first shift the existing packed buffer
                    # TODO: this may be faster to shift integer values before
                    # packing them; however, this will break their format and
                    # cause me more headache
                    head, buf, trail = bytes_lshift_bnd(pack_buf,
                                                        pack_len, 8-rest_bit)
                    if buf:
                        concat.extend( (bchr(junc + head), buf) )
                    else:
                        concat.append( bchr(junc + head) )
                    # pack_buf is always byte-aligned,
                    # so there are always trailing bits
                    junc = trail
                    u = v[1] & ((1<<v[2])-1)
                    # heading bits from the uint value to pack
                    if v[2] < 8-rest_bit:
                        junc += u << (8-rest_bit-v[2])
                    elif v[2] == 8-rest_bit:
                        concat.append( bchr(junc + u) )
                        junc = None
                    else:
                        lb = v[2]-8+rest_bit
                        concat.append( bchr(junc + (u>>lb)) )
                        if lb >= 8:
                            # body of the uint value
                            lt = lb%8
                            if lt == 0:
                                # no trailing bits
                                concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
                                junc = None
                            else:
                                # with trailing bits
                                concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
                                                             lb-lt) )
                                junc = (u&((1<<lt)-1))<<(8-lt)
                        else:
                            # no body, only trailing bits
                            junc = (u&((1<<lb)-1))<<(8-lb)
                    len_bit += pack_len + v[2]
                #
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) nothing to pack
            elif len_bit % 8 == 0:
                # b.a) aligned access
                assert( junc is None )
                if v[2] < 8:
                    if v[1] >= (1<<v[2]):
                        junc = 0x100 - (1<<(8-v[2]))
                    else:
                        junc = v[1] << (8-v[2])
                else:
                    buf = uint_to_bytes(v[1], v[2])
                    concat.append(buf[:v[2]>>3])
                    if v[2]%8:
                        # remaining bits goes to junction byte
                        junc = buf[v[2]>>3]
                len_bit += v[2]
            #
            else:
                # b.b) unaligned access
                assert( 0 <= junc < 256 )
                u = v[1] & ((1<<v[2])-1)
                # heading bits from the uint value to pack
                if v[2] < 8-rest_bit:
                    junc += u << (8-rest_bit-v[2])
                elif v[2] == 8-rest_bit:
                    concat.append( bchr(junc + u) )
                    junc = None
                else:
                    lb = v[2]-8+rest_bit
                    concat.append( bchr(junc + (u>>lb)) )
                    if lb >= 8:
                        #  body of the uint value
                        lt = lb%8
                        if lt == 0:
                            # no trailing bits
                            concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
                            junc = None
                        else:
                            # with trailing bits
                            concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
                                                         lb-lt) )
                            junc = (u&((1<<lt)-1))<<(8-lt)
                    else:
                        # no body, only trailing bits
                        junc = (u&((1<<lb)-1))<<(8-lb)
                len_bit += v[2]
        #
        # 4) standard processing for int
        elif v[0] == TYPE_INT:
            #
            if v[1] >= 0:
                u = v[1]&((1<<v[2]-1)-1)
            else:
                # take 2's complement, so we only manipulate uint
                u = v[1]+(1<<v[2])
                if u < (1<<(v[2]-1)):
                    u = 1<<(v[2]-1)
            #
            # a) append pack_val first, if exist
            if pack_fmt is not None:
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                    #
                    buf = uint_to_bytes(u, v[2])
                    concat.append(buf[:v[2]>>3])
                    if v[2]%8:
                        # remaining bits goes to junction byte
                        junc = buf[v[2]>>3]
                    len_bit += v[2]
                #
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    # first shift the existing packed buffer
                    # TODO: this may be faster to shift integer values before
                    # packing them; however, this will break their format and
                    # cause me more headache
                    head, buf, trail = bytes_lshift_bnd(pack_buf,
                                                        pack_len, 8-rest_bit)
                    if buf:
                        concat.extend( (bchr(junc + head), buf) )
                    else:
                        concat.append( bchr(junc + head) )
                    # pack_buf is always byte-aligned,
                    # so there are always trailing bits
                    junc = trail
                    #
                    # heading bits from the uint value to pack
                    if v[2] < 8-rest_bit:
                        junc += u << (8-rest_bit-v[2])
                    elif v[2] == 8-rest_bit:
                        concat.append( bchr(junc + u) )
                        junc = None
                    else:
                        lb = v[2]-8+rest_bit
                        concat.append( bchr(junc + (u>>lb)) )
                        if lb >= 8:
                            # body of the uint value
                            lt = lb%8
                            if lt == 0:
                                # no trailing bits
                                concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
                                junc = None
                            else:
                                # with trailing bits
                                concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
                                                           lb-lt) )
                                junc = (u&((1<<lt)-1))<<(8-lt)
                        else:
                            # no body, only trailing bits
                            junc = (u&((1<<lb)-1))<<(8-lb)
                    len_bit += pack_len + v[2]
                #
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) nothing to pack
            elif len_bit % 8 == 0:
                # b.a) aligned access
                assert( junc is None )
                if v[2] < 8:
                    junc = u << (8-v[2])
                else:
                    buf = uint_to_bytes(u, v[2])
                    concat.append(buf[:v[2]>>3])
                    if v[2]%8:
                        # remaining bits goes to junction byte
                        junc = buf[v[2]>>3]
                len_bit += v[2]
            #
            else:
                # b.b) unaligned access
                assert( 0 <= junc < 256 )
                # heading bits from the uint value to pack
                if v[2] < 8-rest_bit:
                    junc += u << (8-rest_bit-v[2])
                elif v[2] == 8-rest_bit:
                    concat.append( bchr(junc + u) )
                    junc = None
                else:
                    lb = v[2]-8+rest_bit
                    concat.append( bchr(junc + (u>>lb)) )
                    if lb >= 8:
                        #  body of the uint value
                        lt = lb%8
                        if lt == 0:
                            # no trailing bits
                            concat.append( uint_to_bytes(u&((1<<lb)-1), lb) )
                            junc = None
                        else:
                            # with trailing bits
                            concat.append( uint_to_bytes((u&((1<<lb)-1))>>lt,
                                                         lb-lt) )
                            junc = (u&((1<<lt)-1))<<(8-lt)
                    else:
                        # no body, only trailing bits
                        junc = (u&((1<<lb)-1))<<(8-lb)
                len_bit += v[2]
        #
        # 5) standard processing for little-endian integers
        elif v[0] in (TYPE_UINT_LE, TYPE_INT_LE):
            if v[0] == TYPE_UINT_LE:
                v_bytes = uint_le_to_bytes(v[1], v[2])
            else:
                if v[1] >= 0:
                    u = v[1]&((1<<v[2]-1)-1)
                else:
                    # take 2's complement, so we only manipulate uint
                    u = v[1]+(1<<v[2])
                    if u < (1<<(v[2]-1)):
                        u = 1<<(v[2]-1)
                v_bytes = uint_le_to_bytes(u, v[2])
            # a) append pack_val first, if exist
            if pack_fmt is not None:
                pack_buf = pack(''.join(pack_fmt), *pack_val)
                if rest_bit == 0:
                    # a.a) aligned access
                    assert( junc is None )
                    concat.append(pack_buf)
                    len_bit += pack_len
                    #
                    concat.append(v_bytes)
                    len_bit += v[2]
                #
                else:
                    # a.b) unaligned access
                    assert( 0 <= junc < 256 )
                    buf = pack_buf + v_bytes
                    buflen = pack_len + v[2]
                    head, buf, trail = bytes_lshift_bnd(buf, buflen, 8-rest_bit)
                    # complete the junction byte and append it
                    # with the shifted buffer
                    len_bit += buflen
                    if buf:
                        # heading bits, buffer and potential trailing bits
                        concat.extend( (bchr(junc + head), buf) )
                        junc = trail
                    elif trail is not None:
                        # heading bits and potential trailing bits
                        concat.append( bchr(junc + head) )
                        junc = trail
                    elif not len_bit % 8:
                        # heading bits only
                        concat.append( bchr(junc + head) )
                        junc = None
                    else:
                        # no buf and no trailing bits
                        junc += head
                #
                pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
            #
            # b) nothing to pack
            elif rest_bit == 0:
                # b.a) aligned access
                assert( junc is None )
                concat.append(v_bytes)
                len_bit += v[2]
            #
            else:
                # b.b) unaligned access
                assert( 0 <= junc < 256 )
                head, buf, trail = bytes_lshift_bnd(v_bytes, v[2], 8-rest_bit)
                # complete the junction byte and append it
                # with the shifted buffer
                len_bit += v[2]
                if buf:
                    # heading bits, buffer and potential trailing bits
                    concat.extend( (bchr(junc + head), buf) )
                    junc = trail
                elif trail is not None:
                    # heading bits and potential trailing bits
                    concat.append( bchr(junc + head) )
                    junc = trail
                elif not len_bit % 8:
                    # heading bits only
                    concat.append( bchr(junc + head) )
                    junc = None
                else:
                    # no buf and no trailing bits
                    junc += head
        #
        else:
            raise(PycrateErr('invalid type for packing: {0}'.format(v[0])))
    #
    #print('pack    : fmt {0}, val {1}'.format(pack_fmt, pack_val))
    #print('junc    : {0}'.format(junc))
    #print('len_bit : {0}'.format(len_bit))
    #print('concat  : {0}'.format(concat))
    #print('')
    #
    # 5) in case some integers to pack remains
    if pack_val is not None:
        rest_bit = len_bit%8
        pack_buf = pack(''.join(pack_fmt), *pack_val)
        if rest_bit == 0:
            # a) aligned access
            assert( junc is None )
            concat.append(pack_buf)
            len_bit += pack_len
        else:
            # b) unaligned access
            assert( 0 <= junc < 256 )
            # TODO: again, this may be faster to shift integer values before
            # packing them...
            head, buf, trail = bytes_lshift_bnd(pack_buf, pack_len, 8-rest_bit)
            # complete the junction byte and append it
            # with the shifted buffer
            if buf:
                concat.extend( (bchr(junc + head), buf) )
                junc = trail
            else:
                concat.append( bchr(junc + head) )
                junc = trail
            len_bit += pack_len
        #
        #pack_fmt, pack_val, pack_end, pack_len = None, None, PACK_FMT_BE, 0
    #
    #print('junc    : {0}'.format(junc))
    #print('len_bit : {0}'.format(len_bit))
    #print('concat  : {0}'.format(concat))
    #print('')
    #
    # 6) pack the remaining junction byte
    if junc is not None:
        concat.append( bchr(junc) )
    #
    # 7) return the length in bits and bytes buffer
    return b''.join(concat), len_bit


/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.lucene.search;

import java.io.IOException;

import org.apache.lucene.index.PostingsEnum;

/**
 * A {@link MatchesIterator} over a single term's postings list
 */
class TermMatchesIterator implements MatchesIterator {

  private int upto;
  private int pos;
  private final PostingsEnum pe;
  private final Query query;

  /**
   * Create a new {@link TermMatchesIterator} for the given term and postings list
   */
  TermMatchesIterator(Query query, PostingsEnum pe) throws IOException {
    this.pe = pe;
    this.query = query;
    this.upto = pe.freq();
  }

  @Override
  public boolean next() throws IOException {
    if (upto-- > 0) {
      pos = pe.nextPosition();
      return true;
    }
    return false;
  }

  @Override
  public int startPosition() {
    return pos;
  }

  @Override
  public int endPosition() {
    return pos;
  }

  @Override
  public int startOffset() throws IOException {
    return pe.startOffset();
  }

  @Override
  public int endOffset() throws IOException {
    return pe.endOffset();
  }

  @Override
  public MatchesIterator getSubMatches() throws IOException {
    return null;
  }

  @Override
  public Query getQuery() {
    return query;
  }
}


import * as fs from 'fs-extra';
import {
    Clients,
    CompiledFiles,
    JavaScript,
    TypeScript,
    Transformer,
    CustomHTTPHeaders,
    HTTPHeaders,
    FileContentsResult,
    TSCOptions
} from '../index.d';
import * as chokidar from 'chokidar';
import * as WebSocket from 'ws';
import * as tsc from 'typescript';
import * as babel from '@babel/core';
import { resolveBareSpecifiers } from './babel-plugins/babel-plugin-transform-resolve-bare-specifiers.js';
import { resolveImportPathExtensions } from './babel-plugins/babel-plugin-transform-resolve-import-path-extensions.js';

export async function getFileContents(params: {
    url: string;
    compiledFiles: CompiledFiles;
    disableSpa: boolean;
    watchFiles: boolean;
    clients: Clients;
    transformer: Transformer | 'NOT_SET';
    spaRoot: string | undefined;
}): Promise<Readonly<FileContentsResult>> {

    const cachedFileContents: Readonly<Buffer> | null | undefined = await returnFileContentsFromCache({
        url: params.url,
        compiledFiles: params.compiledFiles
    });

    if (
        cachedFileContents !== null &&
        cachedFileContents !== undefined
    ) {
        return {
            fileContents: cachedFileContents
        };
    }
    else {

        if (await (fs.exists as any)(params.url)) {
            const fileContents: Readonly<Buffer> = await fs.readFile(params.url);

            const transformedFileContents: Readonly<Buffer> = params.transformer === 'NOT_SET' ? fileContents : Buffer.from(await params.transformer({
                sourceString: fileContents.toString(),
                sourceBuffer: fileContents
            }));

            params.compiledFiles[params.url] = transformedFileContents;

            watchFileAndInvalidateFile({
                filePath: params.url,
                watchFiles: params.watchFiles,
                clients: params.clients,
                compiledFiles: params.compiledFiles
            });

            return {
                fileContents: transformedFileContents
            };
        }

        if (!params.disableSpa) {
            const indexFileContents: Readonly<Buffer> = await fs.readFile(params.spaRoot === undefined ? `./index.html` : `./${params.spaRoot}`);

            return {
                fileContents: indexFileContents
            };
        }
        else {
            return 'FILE_NOT_FOUND';
        }

    }
}

async function returnFileContentsFromCache(params: {
    url: string;
    compiledFiles: CompiledFiles;
}): Promise<Readonly<Buffer> | null | undefined> {

    const cachedFileContents: Readonly<Buffer> | null | undefined = params.compiledFiles[params.url];

    return cachedFileContents;
}

export function watchFileAndInvalidateFile(params: {
    filePath: string;
    watchFiles: boolean;
    clients: Clients;
    compiledFiles: CompiledFiles;
}) {
    if (params.watchFiles) {
        chokidar.watch(params.filePath).on('change', () => {
            params.compiledFiles[params.filePath] = null;
            reloadClients(params.clients);
        });
    }
}

export function watchFileAndInvalidateAllFiles(params: {
    filePath: string;
    watchFiles: boolean;
    clients: Clients;
    compiledFiles: CompiledFiles;
}) {
    if (params.watchFiles) {
        chokidar.watch(params.filePath).on('change', () => {
            Object.keys(params.compiledFiles).forEach((key: string) => {
                params.compiledFiles[key] = null;
            });

            reloadClients(params.clients);
        });
    }
}

function reloadClients(clients: Clients): void {
    Object.values(clients).forEach((client: Readonly<WebSocket>) => {
        try {
            client.send('RELOAD_MESSAGE');
        }
        catch(error) {
            //TODO something should be done about this. What's happening I believe is that if two files are changed in a very short period of time, one file will start the browser reloading, and the other file will try to send a message to the browser while it is reloading, and thus the websocket connection will not be established with the browser. This is a temporary solution
            console.log(error);
        }
    });
}

export function addGlobals(params: {
    source: JavaScript;
    wsPort: number;
}): JavaScript {
    return `
        var process = self.process;
        if (!self.ZWITTERION_SOCKET && self.location.host.includes('localhost:')) {
            self.ZWITTERION_SOCKET = new WebSocket('ws://127.0.0.1:${params.wsPort}');
            self.ZWITTERION_SOCKET.addEventListener('message', (message) => {
                self.location.reload();
            });
        }
        ${params.source}
    `;
}

export function compileToJs(params: {
    source: JavaScript | TypeScript;
    filePath: string;
    tscOptions: Readonly<TSCOptions>;
}): JavaScript {

    const typeScriptTranspileOutput: Readonly<tsc.TranspileOutput> = tsc.transpileModule(params.source, {
        compilerOptions: params.tscOptions
    });

    const babelFileResult: Readonly<babel.BabelFileResult> | null = babel.transform(typeScriptTranspileOutput.outputText, {
        'plugins': [
            require('@babel/plugin-syntax-dynamic-import'),
            resolveBareSpecifiers(params.filePath, false),
            resolveImportPathExtensions(params.filePath)
        ]
    });

    if (
        babelFileResult === null ||
        babelFileResult.code === null ||
        babelFileResult.code === undefined
    ) {
        throw new Error(`Compilation error`);
    }

    return babelFileResult.code;
}

export async function getCustomHTTPHeaders(params: {
    headersFilePath: string | undefined;
    clients: Clients;
    compiledFiles: CompiledFiles;
    watchFiles: boolean;
}): Promise<Readonly<CustomHTTPHeaders>> {
    if (params.headersFilePath === undefined) {
        return {};
    }
    else {
        watchFileAndInvalidateAllFiles({
            filePath: params.headersFilePath,
            watchFiles: params.watchFiles,
            clients: params.clients,
            compiledFiles: params.compiledFiles
        });

        const headersFile: Readonly<Buffer> = await fs.readFile(params.headersFilePath);
        return JSON.parse(headersFile.toString());
    }
}

export async function getCompilerOptionsFromFile(params: {
    compilerOptionsFilePath: string | undefined;
    clients: Clients;
    compiledFiles: CompiledFiles;
    watchFiles: boolean;
    defaultCompilerOptions: any;
}): Promise<any> {
    if (params.compilerOptionsFilePath === undefined) {
        return params.defaultCompilerOptions;
    } {
        watchFileAndInvalidateAllFiles({
            filePath: params.compilerOptionsFilePath,
            watchFiles: params.watchFiles,
            clients: params.clients,
            compiledFiles: params.compiledFiles
        });

        const compilerOptionsFile: Readonly<Buffer> = await fs.readFile(params.compilerOptionsFilePath);
        return JSON.parse(compilerOptionsFile.toString());
    }
}

export function getCustomHTTPHeadersForURL(params: {
    customHTTPHeaders: Readonly<CustomHTTPHeaders>;
    url: string;
    defaultHTTPHeaders: Readonly<HTTPHeaders>;
}): Readonly<HTTPHeaders> {
    return Object.keys(params.customHTTPHeaders).reduce((result: Readonly<HTTPHeaders>, customHTTPHeaderRegex: string) => {

        if (params.url.match(customHTTPHeaderRegex)) {
            return {
                ...result,
                ...params.customHTTPHeaders[customHTTPHeaderRegex]
            };
        }

        return result;
    }, params.defaultHTTPHeaders);
}


/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2011 Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef GRUB_ARC_HEADER
#define GRUB_ARC_HEADER	1

#include <grub/types.h>
#include <grub/symbol.h>

typedef unsigned grub_arc_enum_t;
typedef grub_uint64_t grub_arc_ularge_t;
typedef unsigned long grub_arc_ulong_t;
typedef long grub_arc_long_t;
typedef unsigned short grub_arc_ushort_t;
typedef unsigned char grub_arc_uchar_t;

typedef grub_arc_long_t grub_arc_err_t;
typedef grub_arc_ulong_t grub_arc_fileno_t;

struct grub_arc_memory_descriptor
{
  grub_arc_enum_t type;
  grub_arc_ulong_t start_page;
  grub_arc_ulong_t num_pages;
};

enum grub_arc_memory_type
  {
    GRUB_ARC_MEMORY_EXCEPTION_BLOCK,
    GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK,
#ifdef GRUB_CPU_WORDS_BIGENDIAN
    GRUB_ARC_MEMORY_FREE_CONTIGUOUS,
#endif
    GRUB_ARC_MEMORY_FREE,
    GRUB_ARC_MEMORY_BADRAM,
    GRUB_ARC_MEMORY_LOADED,    GRUB_ARC_MEMORY_FW_TEMPORARY,
    GRUB_ARC_MEMORY_FW_PERMANENT,
#ifndef GRUB_CPU_WORDS_BIGENDIAN
    GRUB_ARC_MEMORY_FREE_CONTIGUOUS,
#endif
  } grub_arc_memory_type_t;

struct grub_arc_timeinfo
{
  grub_arc_ushort_t y;
  grub_arc_ushort_t m;
  grub_arc_ushort_t d;
  grub_arc_ushort_t h;
  grub_arc_ushort_t min;
  grub_arc_ushort_t s;
  grub_arc_ushort_t ms;
};

struct grub_arc_display_status
{
  grub_arc_ushort_t x;
  grub_arc_ushort_t y;
  grub_arc_ushort_t w;
  grub_arc_ushort_t h;
  grub_arc_uchar_t fgcolor;
  grub_arc_uchar_t bgcolor;
  grub_arc_uchar_t high_intensity;
  grub_arc_uchar_t underscored;
  grub_arc_uchar_t reverse_video;
};

enum
  {
    GRUB_ARC_COMPONENT_FLAG_OUT = 0x40,
    GRUB_ARC_COMPONENT_FLAG_IN = 0x20,
  };

struct grub_arc_component
{
  grub_arc_enum_t class;
  grub_arc_enum_t type;
  grub_arc_enum_t flags;
  grub_arc_ushort_t version;
  grub_arc_ushort_t rev;
  grub_arc_ulong_t key;
  grub_arc_ulong_t affinity;
  grub_arc_ulong_t configdatasize;
  grub_arc_ulong_t idlen;
  const char *idstr;
};

enum
  {
#ifdef GRUB_CPU_WORDS_BIGENDIAN
    GRUB_ARC_COMPONENT_TYPE_ARC = 1,
#else
    GRUB_ARC_COMPONENT_TYPE_ARC,
#endif
    GRUB_ARC_COMPONENT_TYPE_CPU,
    GRUB_ARC_COMPONENT_TYPE_FPU,
    GRUB_ARC_COMPONENT_TYPE_PRI_I_CACHE,
    GRUB_ARC_COMPONENT_TYPE_PRI_D_CACHE,
    GRUB_ARC_COMPONENT_TYPE_SEC_I_CACHE,
    GRUB_ARC_COMPONENT_TYPE_SEC_D_CACHE,
    GRUB_ARC_COMPONENT_TYPE_SEC_CACHE,
    GRUB_ARC_COMPONENT_TYPE_EISA,
    GRUB_ARC_COMPONENT_TYPE_TCA,
    GRUB_ARC_COMPONENT_TYPE_SCSI,
    GRUB_ARC_COMPONENT_TYPE_DTIA,
    GRUB_ARC_COMPONENT_TYPE_MULTIFUNC,
    GRUB_ARC_COMPONENT_TYPE_DISK_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_TAPE_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_CDROM_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_WORM_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_SERIAL_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_NET_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_DISPLAY_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_PARALLEL_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_POINTER_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_KBD_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_AUDIO_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_OTHER_CONTROLLER,
    GRUB_ARC_COMPONENT_TYPE_DISK,
    GRUB_ARC_COMPONENT_TYPE_FLOPPY,
    GRUB_ARC_COMPONENT_TYPE_TAPE,
    GRUB_ARC_COMPONENT_TYPE_MODEM,
    GRUB_ARC_COMPONENT_TYPE_MONITOR,
    GRUB_ARC_COMPONENT_TYPE_PRINTER,
    GRUB_ARC_COMPONENT_TYPE_POINTER,
    GRUB_ARC_COMPONENT_TYPE_KBD,
    GRUB_ARC_COMPONENT_TYPE_TERMINAL,
#ifndef GRUB_CPU_WORDS_BIGENDIAN
    GRUB_ARC_COMPONENT_TYPE_OTHER_PERIPHERAL,
#endif
    GRUB_ARC_COMPONENT_TYPE_LINE,
    GRUB_ARC_COMPONENT_TYPE_NET,
    GRUB_ARC_COMPONENT_TYPE_MEMORY_UNIT,
  };

enum grub_arc_file_access
  {
    GRUB_ARC_FILE_ACCESS_OPEN_RO,
    GRUB_ARC_FILE_ACCESS_OPEN_WO,
    GRUB_ARC_FILE_ACCESS_OPEN_RW,
  };

struct grub_arc_fileinfo
{
  grub_arc_ularge_t start;
  grub_arc_ularge_t end;
  grub_arc_ularge_t current;
  grub_arc_enum_t type;
  grub_arc_ulong_t fnamelength;
  grub_arc_uchar_t attr;
  char filename[32];
};

struct grub_arc_firmware_vector
{
  /* 0x00. */
  void *load;
  void *invoke;
  void *execute;
  void *halt;

  /* 0x10. */
  void (*powerdown) (void);
  void (*restart) (void);
  void (*reboot) (void);
  void (*exit) (void);

  /* 0x20. */
  void *reserved1;
  const struct grub_arc_component * (*getpeer) (const struct grub_arc_component *comp);
  const struct grub_arc_component * (*getchild) (const struct grub_arc_component *comp);
  void *getparent;

  /* 0x30. */
  void *getconfigurationdata;
  void *addchild;
  void *deletecomponent;
  void *getcomponent;

  /* 0x40. */
  void *saveconfiguration;
  void *getsystemid;
  struct grub_arc_memory_descriptor *(*getmemorydescriptor) (struct grub_arc_memory_descriptor *current);
  void *reserved2;

  /* 0x50. */
  struct grub_arc_timeinfo *(*gettime) (void);
  void *getrelativetime;
  void *getdirectoryentry;
  grub_arc_err_t (*open) (const char *path, grub_arc_enum_t mode,
			  grub_arc_fileno_t *fileno);

  /* 0x60. */
  grub_arc_err_t (*close) (grub_arc_fileno_t fileno);
  grub_arc_err_t (*read) (grub_arc_fileno_t fileno, void *buf,
			  grub_arc_ulong_t n,
			  grub_arc_ulong_t *count);
  grub_arc_err_t (*get_read_status) (grub_arc_fileno_t fileno);
  grub_arc_err_t (*write) (grub_arc_fileno_t fileno, const void *buf,
			   grub_arc_ulong_t n,
			   grub_arc_ulong_t *count);

  /* 0x70. */
  grub_arc_err_t (*seek) (grub_arc_fileno_t fileno,
			  grub_arc_ularge_t *pos, grub_arc_enum_t mode);
  void *mount;
  const char * (*getenvironmentvariable) (const char *name);
  void *setenvironmentvariable;

  /* 0x80. */
  grub_arc_err_t (*getfileinformation) (grub_arc_fileno_t fileno,
					struct grub_arc_fileinfo *info);
  void *setfileinformation;
  void *flushallcaches;
  void *testunicodecharacter;

  /* 0x90. */
  struct grub_arc_display_status * (*getdisplaystatus) (grub_arc_fileno_t fileno);
};

struct grub_arc_adapter
{
  grub_arc_ulong_t adapter_type;
  grub_arc_ulong_t adapter_vector_length;
  void *adapter_vector;
};

struct grub_arc_system_parameter_block
{
  grub_arc_ulong_t signature;
  grub_arc_ulong_t length;
  grub_arc_ushort_t version;
  grub_arc_ushort_t revision;
  void *restartblock;
  void *debugblock;
  void *gevector;
  void *utlbmissvector;
  grub_arc_ulong_t firmware_vector_length;
  struct grub_arc_firmware_vector *firmwarevector;
  grub_arc_ulong_t private_vector_length;
  void *private_vector;
  grub_arc_ulong_t adapter_count;
  struct grub_arc_adapter adapters[0];
};

#define GRUB_ARC_SYSTEM_PARAMETER_BLOCK ((struct grub_arc_system_parameter_block *) 0xa0001000)
#define GRUB_ARC_FIRMWARE_VECTOR (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmwarevector)
#define GRUB_ARC_STDIN 0
#define GRUB_ARC_STDOUT 1

typedef int (*grub_arc_iterate_devs_hook_t)
  (const char *name, const struct grub_arc_component *comp, void *data);

int EXPORT_FUNC (grub_arc_iterate_devs) (grub_arc_iterate_devs_hook_t hook,
					 void *hook_data,
					 int alt_names);

char *EXPORT_FUNC (grub_arc_alt_name_to_norm) (const char *name, const char *suffix);

int EXPORT_FUNC (grub_arc_is_device_serial) (const char *name, int alt_names);

#define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp))

extern void grub_arcdisk_init (void);
extern void grub_arcdisk_fini (void);

#endif


<?php

namespace SmallRuralDog\Admin\Auth\Database;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class OperationLog extends Model
{
    protected $fillable = ['user_id', 'path', 'method', 'ip', 'input'];

    public static $methodColors = [
        'GET'    => 'green',
        'POST'   => 'yellow',
        'PUT'    => 'blue',
        'DELETE' => 'red',
    ];

    public static $methods = [
        'GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH',
        'LINK', 'UNLINK', 'COPY', 'HEAD', 'PURGE',
    ];

    protected $casts = [
        'created_at'=>"timestamp:Y-m-d H:i:s",
        'updated_at'=>"timestamp:Y-m-d H:i:s",
    ];

    /**
     * Create a new Eloquent model instance.
     *
     * @param array $attributes
     */
    public function __construct(array $attributes = [])
    {
        $connection = config('admin.database.connection') ?: config('database.default');

        $this->setConnection($connection);

        $this->setTable(config('admin.database.operation_log_table'));

        parent::__construct($attributes);
    }

    /**
     * Log belongs to users.
     *
     * @return BelongsTo
     */
    public function user() : BelongsTo
    {
        return $this->belongsTo(Administrator::class);
    }
}


import React from 'react';
import PropTypes from 'prop-types';
import JsonForm from './JsonForm';
import {schema,uiSchema,formData} from '../json_schema/orderer'
import { injectIntl  } from 'react-intl';

class OrdererCard extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
           formData:{},
           formMode:"edit",
           schema:schema,
           isInit:false
        }
    }

    getData = () => {
        let that=this;
        var url = 'api/entity/organizations,consortiums';
        fetch(url,{
            method: 'get',
        }).then(response=>{
            return response.json();
        }).then(function(data) {

           let values = [];
           data.organizations.forEach(function (organization) {
                if(organization.MSPs){
                    organization.MSPs.forEach(
                        function (msp) {
                            if(msp.Type=="orderer"){
                                values.push(msp.Name);
                            }

                        }
                    )
                }
             });
            schema.properties.LocalMSPID.enum = values;
            values = [];
            data.consortiums.forEach(function (consortium) {
                values.push(consortium.Name);
            });
            schema.properties.Consortiums.items.enum = values;
            that.setState({schema:schema,isInit:true});
        }).catch(function(e) {
            console.log(e);
        });
    }

    componentWillMount = () => {
        this.getData();
        let that = this
        let data = JSON.parse(this.props.match.params.data);
        let {formMode,key} = data;

        if(key){
            var url = 'api/entity/orderers/'+key;
            fetch(url,{
                method: 'get',
            }).then(response=>{
                return response.json();
            }).then(function(data) {
                that.setState({formData:data,formMode:formMode});
            }).catch(function(e) {
                console.log("Oops, error");
            });
        }else {
            this.setState({formMode:formMode});
        }
    }

    render() {
        let that = this;
        const { intl } = this.props;
        const handleFormSubmit = ({formData}) => {
            var url = `api/entity/orderers/${formData.Name}`;
            fetch(url,{
                method: 'post',
                body:JSON.stringify(formData)
            }).then(function(response) {
                return response;
            }).then(function(data) {
                that.props.history.push({
                    pathname: '/orderer',
                  });
            }).catch(function(e) {
                console.log("Oops, error");
            });
        }
        return (

{this.state.formMode=="view"?intl.formatMessage({id:'view'}):intl.formatMessage({id:'add_orderer'}) }

                                { this.state.isInit && <JsonForm schema={this.state.schema} uiSchema={uiSchema} handleForm={handleFormSubmit} formData={this.state.formData} formMode={this.state.formMode} history={this.props.history}/>}

        )
    }
}

export default injectIntl(OrdererCard);