def get_option_value_or_raise(self, name: str, value_type: T[V]) -> V: """Obtain an option and returns its value. :param value_type: The expecting type of the value. """ option = self.get_option_or_raise(name) value = option.value if isinstance(value, value_type): return value raise InternalError(f"option value not {value_type}")
def format_bp_type(self, t: Type, d: Optional[Definition] = None) -> str: if isinstance(t, Bool): return self.format_bp_bool() if isinstance(t, Int): return self.format_bp_int(t) if isinstance(t, Uint): return self.format_bp_uint(t) if isinstance(t, Byte): return self.format_bp_byte() if isinstance(t, Enum): return self.format_bp_enum(t) if isinstance(t, Alias): return self.format_bp_alias(t) if isinstance(t, Message): return self.format_bp_message(t) if isinstance(t, Array): assert d is not None, InternalError( "format_bp_array requires defintion") return self.format_bp_array(t, d) raise InternalError("format_bp_type got unexpected type")
def format_processor_alias(self, t: Alias) -> str: alias_name = self.format_alias_name(t) s: str if isinstance(t.type, Bool): s = f"{alias_name}(false)" elif isinstance(t.type, (Integer, Enum, Byte)): s = f"{alias_name}(0)" elif isinstance(t.type, Array): s = f"{alias_name}{{}}" else: raise InternalError("format_bp_alias got unexpected alias type") return f"({s}).BpProcessor()"
def render_string(self) -> str: """Render current proto to string.""" formatter = self.formatter() block = self.block() assert block is not None, InternalError("block() returns None") ctx = BlockRenderContext( formatter=formatter, bound=self.proto, optimization_mode_filter_messages=self. optimization_mode_filter_messages, ) block._render_with_ctx(ctx) return block._collect()
def format_op_mode_endecode_message_field(self, t: Type, chain: str, is_encode: bool, i: List[int]) -> List[str]: """Format the encoding (decoding) statements for a message field. This function will dispatch the formatting according to the field type. """ if isinstance(t, SingleType): return self.format_op_mode_endecode_single_type( t, chain, is_encode, i) elif isinstance(t, Message): return self.format_op_mode_endecode_message(t, chain, is_encode, i) elif isinstance(t, Array): return self.format_op_mode_endecode_array(t, chain, is_encode, i) elif isinstance(t, Alias): return self.format_op_mode_endecode_alias(t, chain, is_encode, i) raise InternalError("format_endecode_message_field got unknown type")
def format_default_value(self, t: Type) -> str: if isinstance(t, Bool): return self.format_default_value_bool() elif isinstance(t, Byte): return self.format_default_value_byte() elif isinstance(t, Uint): return self.format_default_value_uint() elif isinstance(t, Int): return self.format_default_value_int() elif isinstance(t, Array): return self.format_default_value_array(t) elif isinstance(t, Enum): return self.format_default_value_enum(t) elif isinstance(t, Message): return self.format_default_value_message(t) elif isinstance(t, Alias): return self.format_default_value_alias(t) raise InternalError(f"format_default_value got unexpected type {t}")
def format_processor(self, t: Type) -> str: if isinstance(t, Bool): return self.format_processor_bool() elif isinstance(t, Int): return self.format_processor_int(t) elif isinstance(t, Uint): return self.format_processor_uint(t) elif isinstance(t, Byte): return self.format_processor_byte() elif isinstance(t, Array): return self.format_processor_array(t) elif isinstance(t, Enum): return self.format_processor_enum(t) elif isinstance(t, Alias): return self.format_processor_alias(t) elif isinstance(t, Message): return self.format_processor_message(t) raise InternalError("format_bp_type got unexpected t")
def push_member(self, member: Definition, name: Optional[str] = None) -> None: """Push a definition `member`, and run hook functions around. Raises error if given member's name already taken by another member. :param member: The member parsed. :param name: Optional name declared in this scope (instead of member.name). """ if self.is_frozen(): raise InternalError("push on frozen scope.") if name is None: name = member.name if name in self.members: raise DuplicatedDefinition.from_token(token=member) self.validate_member_on_push(member, name) self.members[name] = member
def format_op_mode_endecode_alias(self, t: Alias, chain: str, is_encode: bool, i: List[int]) -> List[str]: """Format the encoding (decoding) statements for an alias type. This function dispatches the formatting process according to the type aliased. """ t_ = t.type if isinstance(t_, Array): return self.format_op_mode_endecode_array(t_, chain, is_encode, i) elif isinstance(t_, SingleType): return self.format_op_mode_endecode_single_type( # Note pass `t` instead of `t_`. # Because the type of this field is this alias itself. t, chain, is_encode, i, ) raise InternalError("format_endecode_alias got unknown aliased type")
def format_type(self, t: Type, name: Optional[str] = None) -> str: """Formats the string representation for given type. This is a default implementation. :param name: The name helps to build the type's representation. Currently, only `format_array_type` takes this argument forward. """ if isinstance(t, Bool): return self.format_bool_type() elif isinstance(t, Byte): return self.format_byte_type() elif isinstance(t, Uint): return self.format_uint_type(t) elif isinstance(t, Int): return self.format_int_type(t) elif isinstance(t, Array): return self.format_array_type(t, name=name) elif isinstance(t, Enum): return self.format_enum_type(t) elif isinstance(t, Message): return self.format_message_type(t) elif isinstance(t, Alias): return self.format_alias_type(t) raise InternalError("unknown type for format_type")
def format_case_style(self, s: str, class_: T[Definition]) -> str: """Format given string s by case converting of class_, using the case_style_mapping. """ mapping = self.case_style_mapping() v = mapping.get(class_, "keep") if isinstance(v, str): case_style_name = cast(str, v) case_style = CaseStyle.from_name(case_style_name) converter = case_style.converter() return converter(s) elif isinstance(v, tuple): case_style_names = cast(Tuple[str, ...], v) for case_style_name in case_style_names: case_style = CaseStyle.from_name(case_style_name) converter = case_style.converter() s = converter(s) return s elif callable(v): converter = cast(CaseStyleConverter, v) return converter(s) else: raise InternalError(f"invalid case_style mapping value {v}")
def message(self) -> "Message": scope = self.scope_stack[-1] if isinstance(scope, Message): return cast(Message, self.scope_stack[-1]) raise InternalError("message_field's last scope not message")
def current_filepath(self) -> str: assert self.filepath_stack, InternalError("Empty filepath_stack") return self.filepath_stack[-1]
def __init_subclass__(cls) -> None: """Assuming subclasses define a class-level `__option_descriptors__` attribute.""" if getattr(cls, "__option_descriptors__", None) is None: raise InternalError("no __option_descriptors__ defined")
def bound(self) -> "Proto": if self._bound: return self._bound raise InternalError("BoundDefinition got bound None")
def set_comment_block(self, comment_block: Tuple[Comment, ...]) -> None: if self.is_frozen(): raise InternalError("set_comment_block on frozen proto") self.comment_block = comment_block
def set_name(self, name: str) -> None: if self.is_frozen(): raise InternalError("set_name on frozen proto") self.name = name
def current_scope(self) -> Scope: assert self.scope_stack, InternalError("Empty scope_stack") return self.scope_stack[-1]
def current_proto(self) -> Proto: index = self.scope_stack_init_length assert index < len( self.scope_stack), InternalError("Determining current_proto") return cast(Proto, self.scope_stack[index])
def enum(self) -> "Enum": scope = self.scope_stack[-1] if isinstance(scope, Enum): return cast(Enum, self.scope_stack[-1]) raise InternalError("enum_field's last scope not enum")
def _get_ctx_or_raise(self) -> BlockRenderContext[F]: """Returns current render context, raise if None.""" assert self._ctx is not None, InternalError("block._ctx not set") return self._ctx