def process(self, s, file_path='<string>', start_signature=MESSAGE_START_SIGNATURE, info_only=False, ignore_value_expectation=False, wire_template_data=True): """ Decoding the given message string. :param s: Message string that contains the BUFR Message :param file_path: The file where this string is read from. :param start_signature: Locate the starting position of the message string with the given signature. :param info_only: Only show information up to template data (exclusive) :param ignore_value_expectation: Do not validate the expected value :param wire_template_data: Whether to wire the template data to construct a fully hierarchical structure from the flat lists. Only takes effect when it is NOT info_only. :return: A BufrMessage object that contains the decoded information. """ idx = s.find(start_signature) if start_signature is not None else 0 if idx == -1: raise PyBufrKitError( 'Cannot find start signature: {}'.format(start_signature)) s = s[idx:] bit_reader = get_bit_reader(s) bufr_message = BufrMessage(file_path) configuration_transformers = ( self.section_configurer.info_configuration, ) if info_only else () if ignore_value_expectation: configuration_transformers += ( self.section_configurer.ignore_value_expectation, ) nbits_decoded = 0 section_index = 0 # Always start decoding from section 0 while True: section = self.section_configurer.configure_section( bufr_message, section_index, configuration_transformers) section_index += 1 if section is None: # when optional section is not present continue nbits_decoded += self.process_section(bufr_message, bit_reader, section) if section.end_of_message: break # The exact bytes that have been decoded bufr_message.serialized_bytes = s[:nbits_decoded // NBITS_PER_BYTE] if not info_only and wire_template_data: bufr_message.wire() return bufr_message
def process(self, s, file_path='<string>', wire_template_data=True): """ Entry point for the encoding process. The process encodes a JSON format message to BUFR message. :param s: A JSON or its string serialized form :param file_path: The file path to the JSON file. :param wire_template_data: Whether to wire the template data to construct a fully hierarchical structure from the flat lists. :return: A bitstring object of the encoded message. """ if isinstance(s, (six.binary_type, six.text_type)): # TODO: ensure all strings are loaded as plain ascii instead of unicode from JSON json_data = json.loads(s) if six.PY3 else json.loads(s, encoding='latin-1') else: json_data = s bit_writer = get_bit_writer() bufr_message = BufrMessage(filename=file_path) nbits_encoded = 0 section_index = 0 # When a section is not present in the json data. The index must not be # increase for the section. index_offset = 0 while True: section = self.section_configurer.configure_section_with_values( bufr_message, section_index, json_data[section_index - index_offset], self.overrides) section_index += 1 if section is None: # optional section is not present index_offset += 1 # This section should not be counted continue nbits_encoded += self.process_section(bufr_message, bit_writer, section) if section.end_of_message: break # A zero length means the actual length must be calculated # Fix is needed for both the message object and the serialized bits nbytes_write = bit_writer.get_pos() // NBITS_PER_BYTE if bufr_message.length.value == 0 or self.ignore_declared_length: bufr_message.length.value = nbytes_write section = bufr_message.length.parent bit_writer.set_uint( bufr_message.length.value, bufr_message.length.nbits, section.get_metadata(BITPOS_START) + section.get_parameter_offset('length') ) elif bufr_message.length.value != nbytes_write: raise PyBufrKitError('Write exceeds declared total length {} by {} bytes'.format( bufr_message.length.value, nbytes_write - bufr_message.length.value )) bufr_message.serialized_bytes = bit_writer.to_bytes() if wire_template_data: bufr_message.wire() return bufr_message