def generate_encoded_size(self): result = "" msize = self.get_encoded_size() if msize is not None: submessage_exist = any( isinstance(x.data_type, MessageProtoType) for x in self.fields) if submessage_exist: msize = EncodedSize() for field in self.fields: fieldsize = field.get_encoded_size() if isinstance(field.data_type, MessageProtoType): msize += field.data_type.message.struct_name + "_size" msize += Support.varint_max_size(field.id << 3) msize += Support.varint_max_size( fieldsize.upperlimit()) else: msize += fieldsize identifier = f"{self.struct_name}_size" extra = " + PB_VARINT_MAX_ENCODED_SIZE" if submessage_exist else "" result += f"#define {identifier:<80} ({msize}{extra})\n" # PB_VARINT_MAX_ENCODED_SIZE is added since we shift the result when writing a message to # be able to go back and add the size else: identifier = f"{self.struct_name}_static_size" result += f"/* {identifier} depends on runtime parameters */\n" result += ( f"#define {identifier:<80} {self.get_encoded_size_static_only()}\n" ) return result
def pb_field_t(self, prev_field_name, union_index=None): """Return the pb_field_t initializer to use in the constant array. prev_field_name is the name of the previous field or None. """ tag = get_prototype_tag(self.data_type) result = " PB_FIELD(" result += f"{self.id:>3}, " result += f"{tag:<5}, " result += "{size:<5}, ".format(size=Support.varint_max_size(tag)) result += "{type:<8}, ".format(type=self.get_type(self.data_type)) result += "{}, ".format("REPEATED" if isinstance( self.data_type, ArrayProtoType) else "OPTIONAL") result += "{:<8}, ".format("STATIC" if self.data_type.allocation == Allocation.STATIC else "POINTER") if prev_field_name is None: result += "FIRST, " else: result += "OTHER, " result += f"{self.parent.struct_name}, " result += f"{self.entry_name}, " result += "{}, ".format(prev_field_name or self.entry_name) if isinstance(self.data_type, MessageProtoType): result += "&{name}_fields)".format( name=self.data_type.message.get_full_name().to_string("_")) else: result += "0)" return result
def html_table_row(self, enc_size_str): resolution, min_str, max_str = HtmlField.get_resolution_min_max( self.data_type) if self.unit != "": min_str = f"{min_str} {self.unit}" max_str = f"{max_str} {self.unit}" type_with_link = self.data_type.get_name() data_type = self.data_type if isinstance(data_type, ArrayProtoType): type_with_link += f"[{self.data_type.max_count}]" data_type = self.data_type.data_type # TODO: Think about adding link for external dependencies if isinstance(data_type, MessageProtoType) or isinstance( data_type, EnumProtoType): type_with_link = '<a href="#{name}">{type_name}</a>'.format( name=self.data_type.get_name(), type_name=type_with_link) return "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>\n".format( self.name, type_with_link, min_str, max_str, resolution, self.unit, enc_size_str, Support.varint_max_size(self.id << 3), self.description, )
def __init__( self, name: str, descriptor: descriptor.EnumDescriptorProto, parent: SppParentGuarantees, enum_options: descriptor.EnumOptions, ): self.name = name self.parent = parent self.description = None if enum_options.description != "": self.description = enum_options.description values_dict = {} for x in descriptor.value: values_dict[x.number] = self.create_enum_value(x.number, x.name) self.values = [values_dict[x] for x in sorted(values_dict)] self.encoded_size = EncodedSize( max([ Support.varint_max_size(enum_value.number) for enum_value in self.values ])) self.min_value = min([enum_value.number for enum_value in self.values]) self.max_value = max([enum_value.number for enum_value in self.values])
def _calculate_encoded_size(self, raw_min, raw_max): min_encoded = Support.varint_max_size(raw_min) max_encoded = Support.varint_max_size(raw_max) self.encoded_size = EncodedSize(max(min_encoded, max_encoded)) int_min = self.int_min int_max = self.int_max if self.numeric_type.name.startswith("S"): int_min = Support.svarint_convert(int_min) int_max = Support.svarint_convert(int_max) min_size = Support.varint_max_size(int_min) max_size = Support.varint_max_size(int_max) self.encoded_size.add_reduction(self.encoded_size.value - max(min_size, max_size))
def __init__( self, field_options: so.SystemFieldOptions, identifier: int, allow_pointer: bool, require_max_size: bool, ): super().__init__(field_options, identifier, allow_pointer, 2) self.name = None self.max_size = None if field_options.max_size != 0: self.max_size = field_options.max_size self.encoded_size = EncodedSize( Support.varint_max_size(self.max_size) + self.max_size) elif require_max_size and self.allocation == Allocation.STATIC: raise Exception(f"Missing max_size {self.id} {self.allocation}")
def html(self, proto_file): type_name = self.get_full_name().remove_from_beginning( self.get_package()) result = '<h2 id="{full_name}">{type_name} ({full_name})</h2>\n'.format( full_name=self.get_full_name(), type_name=type_name, ) if self.source: result += "Source: {name} ({source})\n<br>\n".format( name=ds._DATASOURCE.values_by_number[self.source].name, source=self.source, ) if self.identifier: result += f"Identifier: {self.identifier} ({self.identifier:0x})\n<br>\n" if self.version: result += f"Version: {self.version}\n<br>\n" if self.description: result += self.description + "\n<br>\n" result += '<table class="property-table">\n' result += HtmlField.html_table_header() total_enc_size = EncodedSize() total_tag_sizes = 0 for field in self.fields: enc_size_str = "" encsize = field.get_encoded_size() if encsize is not None: if isinstance(encsize, EncodedSize): enc_size_str = encsize.string_with_reduction() else: raise Exception("TODO: Fix it") # TODO: Remove total_enc_size += encsize total_tag_sizes += Support.varint_max_size(field.id << 3) default = field.html_table_row(enc_size_str) if default is not None: result += default total_enc_size_str = "" if total_enc_size is not None: if isinstance(total_enc_size, EncodedSize): total_enc_size_str = total_enc_size.string_with_reduction() else: total_enc_size_str = str(total_enc_size) result += HtmlField.html_table_summary(total_enc_size_str, total_tag_sizes) result += "</table>\n" return result
def handle_dependencies(self, dependencies): if not self.dependencies_handled: if self.message_type in dependencies: self.message = dependencies[self.message_type] self.message.handle_dependencies(dependencies) self.encoded_size = self.message.get_encoded_size() if self.encoded_size is not None: # Include submessage length prefix self.encoded_size += Support.varint_max_size( self.encoded_size.upperlimit()) else: # Submessage or its size cannot be found. # This can occur if submessage is defined in different # file, and it or its .options could not be found. # Instead of direct numeric value, reference the size that # has been #defined in the other file. self.encoded_size = EncodedSize(self.message.type_name + "size") # We will have to make a conservative assumption on the length # prefix size, though. self.encoded_size += 5 self.dependencies_handled = True
def get_tag_size(self): return Support.varint_max_size(self.id << 3)