def forward_declare( node: ProtoNode, root: ProtoNode, output: OutputFile, ) -> None: """Generates code forward-declaring entities in a message's namespace.""" if node.type() != ProtoNode.Type.MESSAGE: return namespace = node.cpp_namespace(root) output.write_line() output.write_line(f'namespace {namespace} {{') # Define an enum defining each of the message's fields and their numbers. output.write_line('enum class Fields {') with output.indent(): for field in node.fields(): output.write_line(f'{field.enum_name()} = {field.number()},') output.write_line('};') # Declare the message's encoder class and all of its enums. output.write_line() output.write_line('class Encoder;') for child in node.children(): if child.type() == ProtoNode.Type.ENUM: output.write_line() generate_code_for_enum(child, node, output) output.write_line(f'}} // namespace {namespace}')
def generate_code_for_message( message: ProtoNode, root: ProtoNode, output: OutputFile, ) -> None: """Creates a C++ class for a protobuf message.""" assert message.type() == ProtoNode.Type.MESSAGE # Message classes inherit from the base proto message class in codegen.h # and use its constructor. base_class = f'{PROTOBUF_NAMESPACE}::{BASE_PROTO_CLASS}' output.write_line( f'class {message.cpp_namespace(root)}::Encoder : public {base_class} {{' ) output.write_line(' public:') with output.indent(): output.write_line(f'using {BASE_PROTO_CLASS}::{BASE_PROTO_CLASS};') # Generate methods for each of the message's fields. for field in message.fields(): for method_class in PROTO_FIELD_METHODS[field.type()]: method = method_class(field, message, root) if not method.should_appear(): continue output.write_line() method_signature = ( f'{method.return_type()} ' f'{method.name()}({method.param_string()})') if not method.in_class_definition(): # Method will be defined outside of the class at the end of # the file. output.write_line(f'{method_signature};') continue output.write_line(f'{method_signature} {{') with output.indent(): for line in method.body(): output.write_line(line) output.write_line('}') output.write_line('};')
def define_not_in_class_methods(message: ProtoNode, root: ProtoNode, output: OutputFile) -> None: """Defines methods for a message class that were previously declared.""" assert message.type() == ProtoNode.Type.MESSAGE for field in message.fields(): for method_class in PROTO_FIELD_METHODS[field.type()]: method = method_class(field, message, root) if not method.should_appear() or method.in_class_definition(): continue output.write_line() class_name = f'{message.cpp_namespace(root)}::Encoder' method_signature = ( f'inline {method.return_type(from_root=True)} ' f'{class_name}::{method.name()}({method.param_string()})') output.write_line(f'{method_signature} {{') with output.indent(): for line in method.body(): output.write_line(line) output.write_line('}')