예제 #1
0
 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)
예제 #2
0
    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
예제 #3
0
    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])
예제 #4
0
    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
예제 #5
0
    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))
예제 #6
0
 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
예제 #7
0
 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
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
 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}")
예제 #11
0
    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
예제 #12
0
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
예제 #13
0
 def __init__(self, field_options: so.SystemFieldOptions, identifier: int):
     super().__init__(field_options, identifier, NumericType.BOOL)
     self.encoded_size = EncodedSize(1)