def decode(cls, encoded, taxonomy=None): """Decode a field from a byte array. Returns: (field, num_read). field: the field read from the byte array num_read: number of bytes this field took up Raises: Error: if there is not enough bytes in the array for the field. """ assert len(encoded) >= 2 # prefix pos = 0 fixedwidth, variablewidth, has_ordinal, has_name = \ prefix.decode_prefix(ord(encoded[pos])) pos += 1 type_id = ord(encoded[pos]) # TODO(jamesc) - need to handle user supplied registries field_type = DEFAULT_REGISTRY[type_id] pos += 1 # ordinal ordinal = None if has_ordinal: ordinal = codecs.dec_short(encoded[pos:]) pos += 2 # name name = None if has_name: name_len = ord(encoded[pos]) pos += 1 # length encoded as 1 byte name = codecs.dec_unicode(encoded[pos:pos + name_len]) pos += name_len elif has_ordinal and taxonomy: name = taxonomy.get_name(ordinal) # value if fixedwidth: value = field_type.decoder(encoded[pos:pos + field_type.fixed_size]) pos += field_type.fixed_size else: value_length = decode_value_length(encoded[pos:], variablewidth) pos += variablewidth if type_id == types.FUDGEMSG_TYPE_ID: value = fudgemsg.message.Message.decode( encoded[pos:pos + value_length], taxonomy) else: value = field_type.decoder(encoded[pos:pos + value_length]) pos += value_length field = Field(field_type, ordinal, name, value) return field, pos
def decode(cls, encoded, taxonomy=None): """Decode a field from a byte array. Returns: (field, num_read). field: the field read from the byte array num_read: number of bytes this field took up Raises: Error: if there is not enough bytes in the array for the field. """ assert len(encoded) >= 2 # prefix pos = 0 fixedwidth, variablewidth, has_ordinal, has_name = \ prefix.decode_prefix(ord(encoded[pos])) pos += 1 type_id = ord(encoded[pos]) # TODO(jamesc) - need to handle user supplied registries field_type = DEFAULT_REGISTRY[type_id] pos += 1 # ordinal ordinal = None if has_ordinal: ordinal = codecs.dec_short(encoded[pos:]) pos += 2 # name name = None if has_name: name_len = ord(encoded[pos]) pos += 1 # length encoded as 1 byte name = codecs.dec_unicode(encoded[pos:pos+name_len]) pos += name_len elif has_ordinal and taxonomy: name = taxonomy.get_name(ordinal) # value if fixedwidth: value = field_type.decoder(encoded[pos:pos+field_type.fixed_size]) pos += field_type.fixed_size else: value_length = decode_value_length(encoded[pos:], variablewidth) pos += variablewidth if type_id == types.FUDGEMSG_TYPE_ID: value = fudgemsg.message.Message.decode(encoded[pos:pos+value_length], taxonomy) else: value = field_type.decoder(encoded[pos:pos+value_length]) pos += value_length field = Field(field_type, ordinal, name, value) return field, pos
def decode_value_length(encoded, width): """Decode the length of a value from a var_width length. Arguments: encoded: The byte stream to read from width: The number of bytes to read (1, 2, 4) Return: The decoded value length """ assert width in (0, 1, 2, 4) if width == 0: return 0 elif width == 1: return codecs.dec_byte(encoded[0]) elif width == 2: return codecs.dec_short(encoded[0:2]) else: return codecs.dec_int(encoded[0:4])