def from_bytes(bytes_rep, offset=0):
     required_size = 1 + 8
     if not required_size + offset <= len(bytes_rep):
         error_msg = 'Byte array too small to hold a float'
         raise BinsonException(error_msg)
     float_val, = struct.unpack_from('<d', bytes_rep, offset + 1)
     return BinsonFloat(float_val), 9
Exemple #2
0
 def __get(self, field, expected_type):
     """
     :param field:
     :param expected_type:
     :return:
     """
     if field not in self.value:
         raise BinsonException(
             'Binson object does not contain field name "%s"' % field)
     value = self.value[field]
     if not isinstance(value, expected_type):
         raise BinsonException(
             'Field name "%s" does not contain expected field' % field)
     if not isinstance(value, (BinsonArray, BinsonObject)):
         value = value.get_value()
     return value
 def from_bytes(bytes_rep, offset=0):
     if not bytes_rep[offset] in BinsonString.identifiers():
         error_msg = 'Expected string length identifier'
         error_msg += ' (0x14, 0x15, 0x16)'
         error_msg += ' but got {}'.format(bytes_rep[offset])
         raise BinsonException(error_msg)
     bytes_rep, consumed = from_bytes_with_identifier(
         bytes_rep, offset, bytes_rep[offset] + 0x04)
     str_val = bytes_rep.decode('utf8')
     return BinsonString(str_val), consumed
Exemple #4
0
    def from_bytes(bytes_rep, offset=0):
        from pybinson.binson_values import get_parser
        if not offset < len(bytes_rep):
            error_msg = 'Byte array too small to hold a binson object.'
            raise BinsonException(error_msg)
        orig_offset = offset
        if not bytes_rep[offset] in BinsonObject.identifiers():
            raise BinsonException('Unexpected start of binson object.')
        offset += 1
        dict_rep = {}
        prev_name = ''
        length = len(bytes_rep)
        while offset < length:

            # End of object
            if bytes_rep[offset] == 0x41:
                offset += 1
                consumed = offset - orig_offset
                return pybinson.binson.Binson(dict_rep), consumed

            # Parse field name (BinsonString)
            name, consumed = BinsonString.from_bytes(bytes_rep, offset)
            name = name.get_value()
            offset += consumed

            if name <= prev_name:
                error_msg = 'Fields names not in lexicographical order'
                error_msg += ' when parsing. Current: {}'.format(name)
                error_msg += ', previous: {}'.format(prev_name)
                raise BinsonException(error_msg)

            if not offset < length:
                break

            identifier = bytes_rep[offset]
            parser = get_parser(identifier)
            binson_value, consumed = parser(bytes_rep, offset)
            offset += consumed
            dict_rep[name] = binson_value
            prev_name = name

        # We should never end ep here if it is a valid binson object
        raise BinsonException('Unexpected end of byte array')
Exemple #5
0
 def from_bytes_with_identifier(bytes_rep, offset, forced_identifier):
     """
     :param bytes_rep:
     :param offset:
     :param forced_identifier:
     :return:
     """
     identifier = forced_identifier
     storage_size = (1 << (identifier & 0x0F))
     required_size = 1 + storage_size
     if not required_size + offset <= len(bytes_rep):
         raise BinsonException('Byte array too small to hold integer.')
     unpack = BinsonInteger.UNPACK_VALUES[identifier]
     int_val, = struct.unpack_from(unpack, bytes_rep, offset + 1)
     expected_size = BinsonInteger.int_size(int_val)
     if not expected_size == storage_size:
         error_msg = 'Expected storage size {}'.format(expected_size)
         error_msg += ' but got storage size {}.'.format(storage_size)
         raise BinsonException(error_msg)
     return BinsonInteger(int_val), required_size
 def __init__(self, array=None):
     from pybinson.binson_values import binsonify_value
     if not array:
         array = []
     if not isinstance(array, list):
         error_msg = 'Value of type {}'.format(type(array))
         error_msg += ' cannot be represented as binson.'
         raise BinsonException(error_msg)
     super(BinsonArray, self).__init__(array)
     for i in range(0, len(self.value)):
         self.value[i] = binsonify_value(self.value[i])
Exemple #7
0
 def deserialize(bytes_rep, offset=0, check_trailing_garbage=True):
     """
     :param bytes_rep:
     :param offset:
     :param check_trailing_garbage:
     :return:
     """
     binson, consumed = pybinson.binson.Binson.from_bytes(bytes_rep, offset)
     if check_trailing_garbage:
         if not offset + consumed == len(bytes_rep):
             error_msg = 'Detected garbage after object end.'
             raise BinsonException(error_msg)
     return binson
Exemple #8
0
def from_bytes_with_identifier(bytes_rep, offset, forced_identifier):
    """
    :param bytes_rep:
    :param offset:
    :param forced_identifier:
    :return:
    """
    identifier = forced_identifier
    # First we have the length of the byte representation
    forced_identifier = identifier - 0x08
    length, consumed = BinsonInteger.from_bytes_with_identifier(
        bytes_rep, offset, forced_identifier)
    length = length.get_value()
    if not length >= 0:
        error_msg = 'A byte array cannot have negative length'
        raise BinsonException(error_msg)
    required_size = consumed + length
    if not required_size + offset <= len(bytes_rep):
        error_msg = 'Buffer too small for specified length'
        raise BinsonException(error_msg)
    bytes_val = bytes_rep[offset + consumed:offset + consumed + length]
    return bytes_val, required_size
Exemple #9
0
 def int_size(int_val):
     """
     :param int_val:
     :return:
     """
     if -2**7 <= int_val < 2**7:
         return 1
     if -2**15 <= int_val < 2**15:
         return 2
     if -2**31 <= int_val < 2**31:
         return 4
     if -2**63 <= int_val < 2**63:
         return 8
     raise BinsonException('Integer too large to fit in 8 bytes.')
Exemple #10
0
def get_parser(identifier):
    """
    :param identifier:
    :return:
    """
    ret_parser = None
    for parser in BINSON_VALUES:
        if identifier in parser.identifiers():
            ret_parser = parser.from_bytes
            break
    if not ret_parser:
        error_msg = 'Value 0x%02x' % identifier
        error_msg += ' is not a valid binson identifier.'
        raise BinsonException(error_msg)
    return ret_parser
Exemple #11
0
def binsonify_value(value):
    """
    :param value:
    :return:
    """
    binson_rep = None
    if isinstance(value, BinsonValue):
        binson_rep = value
    else:
        for binson_value in BINSON_VALUES:
            if isinstance(value, binson_value.instances()):
                binson_rep = binson_value(value)
                break
    if not binson_rep:
        error_msg = 'Value of type {}'.format(type(value))
        error_msg += ' cannot be represented as binson.'
        raise BinsonException(error_msg)
    return binson_rep
    def from_bytes(bytes_rep, offset=0):
        from pybinson import binson_values
        orig_offset = offset
        offset += 1
        array = []
        while offset < len(bytes_rep):

            # End array
            if bytes_rep[offset] == 0x43:
                offset += 1
                consumed = offset - orig_offset
                return BinsonArray(array), consumed

            identifier = bytes_rep[offset]
            parser = binson_values.get_parser(identifier)
            binson_value, consumed = parser(bytes_rep, offset)
            array.append(binson_value)
            offset += consumed

        raise BinsonException('Unexpected end of byte array')