def handle_dependencies(self, dependencies): if self.type_name in dependencies: self.enum_definition = dependencies[self.type_name] self.encoded_size = self.enum_definition.encoded_size else: # Conservative assumption self.encoded_size = EncodedSize(10)
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 __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 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 _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, numeric_type: Fixed32NumericType, ): super().__init__(field_options, identifier, numeric_type, 5) self.encoded_size = EncodedSize(4) self.bits = 32
def __init__( self, field_options: so.SystemFieldOptions, identifier: int, numeric_type: Fixed64NumericType, ): super().__init__(field_options, identifier, numeric_type, 1) self.encoded_size = EncodedSize(8) self.bits = 64 self.is_64bit = True
def get_encoded_size(self): """Return the maximum size that this message can take when encoded. If the size cannot be determined, returns None. """ size = EncodedSize(0) for field in self.fields: fsize = field.get_encoded_size() if fsize is None: return None size += fsize return size
def get_encoded_size_static_only(self): """Return the maximum size that this message can take when encoded. Only statically allocated parts are considered. """ size = EncodedSize(0) for field in self.fields: fsize = field.get_encoded_size() if fsize != None: size += fsize else: size += field.data_type.get_tag_size() return 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 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
class VarintProtoType(ProtoType): int_sizer = { NumericType.I32: { so.IS_8: NumericType.I8, so.IS_16: NumericType.I16, so.IS_32: NumericType.I32, }, NumericType.I64: { so.IS_8: NumericType.I8, so.IS_16: NumericType.I16, so.IS_32: NumericType.I32, so.IS_64: NumericType.I64, }, NumericType.S32: { so.IS_8: NumericType.S8, so.IS_16: NumericType.S16, so.IS_32: NumericType.S32, }, NumericType.S64: { so.IS_8: NumericType.S8, so.IS_16: NumericType.S16, so.IS_32: NumericType.S32, so.IS_64: NumericType.S64, }, NumericType.U32: { so.IS_8: NumericType.U8, so.IS_16: NumericType.U16, so.IS_32: NumericType.U32, }, NumericType.U64: { so.IS_8: NumericType.U8, so.IS_16: NumericType.U16, so.IS_32: NumericType.U32, so.IS_64: NumericType.U64, }, } def __init__( self, field_options: so.SystemFieldOptions, identifier: int, numeric_type: NumericType, ): super().__init__(field_options, identifier, False, 0) self.packable = True self.numeric_type = numeric_type self.min = None self.max = None self.scale = None self.is_64bit = numeric_type.name.endswith("64") int_size = field_options.int_size if int_size != so.IS_DEFAULT: try: self.numeric_type = self.int_sizer[numeric_type][int_size] except KeyError: pass except Exception: raise Exception( "Int size specified but something unknown went wrong") if numeric_type != NumericType.ENUM and numeric_type != NumericType.BOOL: self._check_int_support(field_options) def _read_min(self, field_options, raw_min): scale = float(self.scale) if self.scale is not None else None self.min = Support.scale_value(scale, raw_min) if field_options.min != 0 or field_options.force_min_max_usage: proposed_min = Support.get_int_reverse_scale( scale, field_options.min) if raw_min <= proposed_min: self.min = field_options.min else: allowed_str = ((f"{self.min}") if self.min == raw_min else f"{self.min} [{raw_min}]") raise Exception( f"Min value not supported by numeric type. " f"Allowed: {allowed_str}, proposed value: {field_options.min}" ) self.int_min = Support.get_int_reverse_scale(scale, self.min) def _read_max(self, field_options, raw_max): scale = float(self.scale) if self.scale is not None else None self.max = Support.scale_value(scale, raw_max) if field_options.max != 0 or field_options.force_min_max_usage: proposed_max = Support.get_int_reverse_scale( scale, field_options.max) if raw_max >= proposed_max: self.max = field_options.max else: allowed_str = (f"{self.max}" if self.max == raw_max else f"{self.max} [{raw_max}]") raise Exception( f"Max value not supported by numeric type. " f"Allowed: {allowed_str}, proposed value: {field_options.max}" ) self.int_max = Support.get_int_reverse_scale(scale, self.max) 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 _check_int_support(self, field_options): self.scale = get_scale(field_options) raw_min, raw_max = Support.get_numeric_range(self.numeric_type) self._read_min(field_options, raw_min) self._read_max(field_options, raw_max) if self.numeric_type.name.startswith("S"): raw_min = Support.svarint_convert(raw_min) raw_min = Support.svarint_convert(raw_max) self._calculate_encoded_size(raw_min, raw_max) def get_name(self): return self.numeric_type.name
def __init__(self, field_options: so.SystemFieldOptions, identifier: int): super().__init__(field_options, identifier, NumericType.BOOL) self.encoded_size = EncodedSize(1)