def _load_variant_member(self, variant: VariantAlias): var_type_enum = self._get_variant_type_enum() if var_type_enum: self.buffer.append( f"switch(static_cast<{var_type_enum.type_name}>(m.type))") else: self.buffer.append(f"switch(m.{variant.type_name}.index())") self.buffer.append('{') with IndentedBlock(self.buffer): for i, var_member in enumerate(variant.member_type_defs): self.buffer.append( f'case {self._get_variant_case_type_member(i)}:') self.buffer.append('{') with IndentedBlock(self.buffer): self._load_variant_member_case(variant, var_member) self.buffer.append('break;') self.buffer.append('}') # default case self.buffer.append('default:') self.buffer.append('{') with IndentedBlock(self.buffer): self.buffer.append( 'throw std::runtime_error(std::string() + "Unsupported variant type: " + ' 'std::to_string(m.content.index()));') self.buffer.append('}') self.buffer.append('}')
def _write_body(self): self.buffer.append('nlohmann::json res {') with IndentedBlock(self.buffer): for member_def in self.container_struct.members: self.member_to_json(member_def) self.buffer.append('};') self.buffer.append('return res;')
def write_function(self): self.buffer.append( f"void FromJson({self.container_struct.type_name}& m, nlohmann::json const& j)" ) self.buffer.append("{") with IndentedBlock(self.buffer): self._write_body() self.buffer.append("}")
def _write_body(self): self.buffer.append('nlohmann::json res {') with IndentedBlock(self.buffer): self.buffer.append('{ "type": m.index() },') self.buffer.append('};') self.buffer.append('auto& content = res["content"];') self.buffer.append('// TODO: load content') self.buffer.append('return res;')
def write_function(self): self.buffer.append( f"nlohmann::json ToJson({self.container_struct.type_name} const& m)" ) self.buffer.append("{") with IndentedBlock(self.buffer): self._write_body() self.buffer.append("}") self.buffer.new_line()
def _write_body(self): self.buffer.append( f'switch(j.at("type").get<{self.container_struct.type_name}::Type>())' ) self.buffer.append('{') with IndentedBlock(self.buffer): self.buffer.append('// TODO: add missing cases') self.buffer.append( 'default: throw std::runtime_error(std::string() + "Unexpected member type: " + j.at("type"))' ) self.buffer.append('}')
def write_header(self, buffer: LineBuffer, _type_registry: TypeRegistry) -> None: buffer.append( f"enum class {self.enum_name()} : {self.type_def.underlying_type}") buffer.append('{') with IndentedBlock(buffer): if self.type_def.members: enum_members = self.type_def.members for m, i in enum_members.items(): comment = f" //{self.type_def.comments[m]}" if m in self.type_def.comments else '' buffer.append(f"{m} = {i},{comment}") buffer.append('};')
def write_source(self, buffer: LineBuffer, type_registry: TypeRegistry): if self.type_def.namespaces: buffer.append('namespace ' + '::'.join(self.type_def.namespaces)) buffer.append('{') buffer.indent_up() # internal namespace buffer.append(f"namespace internal") buffer.append("{") with IndentedBlock(buffer): # internal ToJson tjw = ToJsonWriter(buffer, type_registry, self.type_def) tjw.write_function() # internal FromJson fjw = FromJsonWriter(buffer, type_registry, self.type_def) fjw.write_function() buffer.append("}") buffer.new_line() # public ToJson buffer.append(f"std::string {self.type_def.type_name}::ToJson() const") buffer.append("{") with IndentedBlock(buffer): buffer.append('return internal::ToJson(*this).dump();') buffer.append("}") buffer.new_line() # public FromJson buffer.append(f"void {self.type_def.type_name}::FromJson(std::string const& js)") buffer.append("{") with IndentedBlock(buffer): buffer.append('internal::FromJson(*this, nlohmann::json::parse(js));') buffer.append("}") if self.type_def.namespaces: buffer.indent_down() buffer.append('} // namespace ' + '::'.join(self.type_def.namespaces))
def get_type_header_buffer(self, namespaces: List[str]) -> LineBuffer: ns_key = self._make_ns_key(namespaces) if ns_key not in self.include_headers: raise NameError(f"No namespace type info: {ns_key}") buffer = LineBuffer(0) if self.include_headers[ns_key]: buffer.new_line() for include in self.include_headers[ns_key]: buffer.append(f"#include <{include}>") buffer.new_line() ns_str = "::".join(namespaces) buffer.append(f'namespace {ns_str}') buffer.append('{') with IndentedBlock(buffer): for buf in self.buffers[ns_key]: buffer.append_buffer(buf) buffer.append(f'}} // {ns_str}') return buffer
def write_source(self, buffer: LineBuffer, type_registry: TypeRegistry): if self.type_def.namespaces: buffer.append('namespace ' + '::'.join(self.type_def.namespaces)) buffer.append('{') buffer.indent_up() # internal namespace buffer.append(f"namespace internal") buffer.append("{") with IndentedBlock(buffer): fjw = FromJsonWriter(buffer, type_registry, self.type_def) fjw.write_function() tjw = ToJsonWriter(buffer, type_registry, self.type_def) tjw.write_function() buffer.append("}") buffer.new_line() if self.type_def.namespaces: buffer.indent_down() buffer.append('} // namespace ' + '::'.join(self.type_def.namespaces))
def write_header(self, buffer: LineBuffer, type_registry: TypeRegistry) -> None: var_buffer = LineBuffer(0) type_buffer = LineBuffer(0) for type_def in self.type_def.members: if isinstance(type_def, SimpleAlias): cpp_alias = CppSimpleAlias(type_def) var_buffer.append(f"{cpp_alias.actual_type()} {type_def.type_name};") self.header_includes.update(cpp_alias.get_include_headers(type_registry)) elif isinstance(type_def, ArrayAlias): cpp_array = CppArrayAlias(type_def) var_buffer.append(f"{cpp_array.actual_type(type_registry)} {type_def.type_name};") self.header_includes.update(cpp_array.get_include_headers(type_registry)) elif isinstance(type_def, VariantAlias): cpp_variant = CppVariantAlias(type_def) var_buffer.append(f"{cpp_variant.actual_type(type_registry)} {type_def.type_name};") self.header_includes.update(cpp_variant.get_include_headers(type_registry)) elif isinstance(type_def, EnumType): cpp_enum = CppEnum(type_def) cpp_enum.write_header(type_buffer, type_registry) type_buffer.new_line() elif isinstance(type_def, StructType): cpp_struct = CppStruct(type_def) cpp_struct.write_header(type_buffer, type_registry) type_buffer.new_line() self.header_includes.update(cpp_struct.header_includes) elif isinstance(type_def, ExtendedVariant): cpp_struct = CppExtendedVariant(type_def) cpp_struct.write_header(type_buffer, type_registry) type_buffer.new_line() self.header_includes.update(cpp_struct.header_includes) elif isinstance(type_def, RefType): cpp_ref_alias = CppRefAlias(type_def) var_buffer.append(f"{cpp_ref_alias.target_type(type_registry)} {type_def.type_name};") else: raise TypeError(f"Unsupported struct member type: [{type_def}]") # generate struct if self.type_def.namespaces: buffer.append('namespace ' + '::'.join(self.type_def.namespaces)) buffer.append('{') buffer.indent_up() if self.base_classes: suffix = ' : ' + ', '.join(self.base_classes) else: suffix = '' buffer.append(f"struct {self.type_def.type_name}{suffix}") buffer.append("{") if type_buffer: with IndentedBlock(buffer): buffer.append_buffer(type_buffer) if var_buffer: with IndentedBlock(buffer): buffer.append_buffer(var_buffer) buffer.new_line() # pre-defined methods with IndentedBlock(buffer): if self.member_methods: for method in self.member_methods: buffer.append(method) else: buffer.pop() buffer.append('};') if self.type_def.namespaces: buffer.indent_down() buffer.append('} // namespace ' + '::'.join(self.type_def.namespaces))
def write_header(self, buffer: LineBuffer, type_registry: TypeRegistry) -> None: # generate extended struct if self.type_def.namespaces: buffer.append('namespace ' + '::'.join(self.type_def.namespaces)) buffer.append('{') buffer.indent_up() if self.base_classes: suffix = ' : ' + ', '.join(self.base_classes) else: suffix = '' variant_members = ['std::monostate'] for member_type_def in self.type_def.content_variant.member_type_defs: if isinstance(member_type_def, SimpleAlias): cpp_alias = CppSimpleAlias(member_type_def) variant_members.append(cpp_alias.actual_type()) elif isinstance(member_type_def, ArrayAlias): cpp_array = CppArrayAlias(member_type_def) variant_members.append(cpp_array.actual_type(type_registry)) elif isinstance(member_type_def, StructType): # cpp_struct = CppStruct(member_type_def) # variant_members.append(cpp_struct.type_def.type_name) pass elif isinstance(member_type_def, RefType): # target_type = type_registry.get_ref_target(member_type_def.target_uri) # variant_members.append(target_type.type_name) pass else: raise TypeError(f"Unsupported struct member type: [{member_type_def}]") buffer.append(f"struct {self.type_def.type_name}{suffix} : std::variant<{','.join(variant_members)}>") buffer.append("{") with IndentedBlock(buffer): # write type enum cpp_enum = CppEnum(self.type_def.type_enum) cpp_enum.type_def.type_name = cpp_enum.type_def.type_name.capitalize() cpp_enum.write_header(buffer, type_registry) buffer.append('') cast_expr = f'static_cast<{self.type_def.type_enum.underlying_type}>(MemberType)' # write setter buffer.append('template <Type MemberType, typename T>') buffer.append(f'void SetAs(T value) ') buffer.extend_last('{ ') buffer.extend_last(f'emplace<{cast_expr}>(value);') buffer.extend_last(' }') buffer.new_line() # write non-const getter buffer.append('template <Type MemberType>') buffer.append(f'[[nodiscard]] auto& GetAs() ') buffer.extend_last('{ ') buffer.extend_last(f'return std::get<{cast_expr}>(*this);') buffer.extend_last(' }') buffer.new_line() # write const getter buffer.append('template <Type MemberType>') buffer.append(f'[[nodiscard]] auto const& GetAs() const ') buffer.extend_last('{ ') buffer.extend_last(f'return std::get<{cast_expr}>(*this);') buffer.extend_last(' }') # pre-defined methods with IndentedBlock(buffer): if self.member_methods: for method in self.member_methods: buffer.append(method) buffer.append('};') if self.type_def.namespaces: buffer.indent_down() buffer.append('} // namespace ' + '::'.join(self.type_def.namespaces))