Пример #1
0
def _generate_service_stub(service: ProtoService, output: OutputFile,
                           unary_stub: StubFunction,
                           server_streaming_stub: StubFunction) -> None:
    output.write_line()
    output.write_line(
        f'class {service.name()} '
        f': public generated::{service.name()}<{service.name()}> {{')

    output.write_line(' public:')

    with output.indent():
        blank_line = False

        for method in service.methods():
            if blank_line:
                output.write_line()
            else:
                blank_line = True

            if method.type() is ProtoServiceMethod.Type.UNARY:
                unary_stub(method, output)
            elif method.type() is ProtoServiceMethod.Type.SERVER_STREAMING:
                server_streaming_stub(method, output)
            else:
                raise NotImplementedError(
                    'Client and bidirectional streaming not yet implemented')

    output.write_line('};\n')
Пример #2
0
def _generate_code_for_client(service: ProtoService, root: ProtoNode,
                              output: OutputFile) -> None:
    """Outputs client code for an RPC service."""

    output.write_line('namespace nanopb {')

    class_name = f'{service.cpp_namespace(root)}Client'
    output.write_line(f'\nclass {class_name} {{')
    output.write_line(' public:')

    with output.indent():
        output.write_line('template <typename T>')
        output.write_line(
            f'using NanopbClientCall = {RPC_NAMESPACE}::NanopbClientCall<T>;')

        output.write_line('')
        output.write_line(f'{class_name}() = delete;')

        for method in service.methods():
            _generate_code_for_client_method(method, output)

    service_name_hash = pw_rpc.ids.calculate(service.proto_path())
    output.write_line('\n private:')

    with output.indent():
        output.write_line(f'// Hash of "{service.proto_path()}".')
        output.write_line(
            f'static constexpr uint32_t kServiceId = 0x{service_name_hash:08x};'
        )

    output.write_line('};')

    output.write_line('\n}  // namespace nanopb\n')
Пример #3
0
def _method_lookup_table(service: ProtoService, output: OutputFile) -> None:
    """Generates array of method IDs for looking up methods at compile time."""
    output.write_line('static constexpr std::array<uint32_t, '
                      f'{len(service.methods())}> kMethodIds = {{')

    with output.indent(4):
        for method in service.methods():
            method_id = pw_rpc.ids.calculate(method.name())
            output.write_line(
                f'0x{method_id:08x},  // Hash of "{method.name()}"')

    output.write_line('};\n')
Пример #4
0
def _generate_service_stubs(service: ProtoService, output: OutputFile,
                            stub_generator: StubGenerator) -> None:
    output.write_line(f'// Method definitions for {service.proto_path()}.')

    blank_line = False

    for method in service.methods():
        if blank_line:
            output.write_line()
        else:
            blank_line = True

        signature, stub = _select_stub_methods(stub_generator, method)

        output.write_line(signature(method, f'{service.name()}::') + ' {')
        with output.indent():
            stub(method, output)
        output.write_line('}')
Пример #5
0
def _generate_service_class(service: ProtoService, output: OutputFile,
                            stub_generator: StubGenerator) -> None:
    output.write_line(f'// Implementation class for {service.proto_path()}.')
    output.write_line(
        f'class {service.name()} '
        f': public generated::{service.name()}<{service.name()}> {{')

    output.write_line(' public:')

    with output.indent():
        blank_line = False

        for method in service.methods():
            if blank_line:
                output.write_line()
            else:
                blank_line = True

            signature, _ = _select_stub_methods(stub_generator, method)

            output.write_line(signature(method, '') + ';')

    output.write_line('};\n')
Пример #6
0
def service_class(service: ProtoService, root: ProtoNode, output: OutputFile,
                  server_writer_alias: ServerWriterGenerator,
                  method_union: str,
                  method_descriptor: MethodGenerator) -> None:
    """Generates a C++ derived class for a nanopb RPC service."""

    output.write_line('namespace generated {')

    base_class = f'{RPC_NAMESPACE}::Service'
    output.write_line('\ntemplate <typename Implementation>')
    output.write_line(
        f'class {service.cpp_namespace(root)} : public {base_class} {{')
    output.write_line(' public:')

    with output.indent():
        output.write_line(
            f'using ServerContext = {RPC_NAMESPACE}::ServerContext;')
        server_writer_alias(output)
        output.write_line()

        output.write_line(f'constexpr {service.name()}()')
        output.write_line(f'    : {base_class}(kServiceId, kMethods) {{}}')

        output.write_line()
        output.write_line(
            f'{service.name()}(const {service.name()}&) = delete;')
        output.write_line(f'{service.name()}& operator='
                          f'(const {service.name()}&) = delete;')

        output.write_line()
        output.write_line(f'static constexpr const char* name() '
                          f'{{ return "{service.name()}"; }}')

        output.write_line()
        output.write_line(
            '// Used by MethodLookup to identify the generated service base.')
        output.write_line(
            'constexpr void _PwRpcInternalGeneratedBase() const {}')

    service_name_hash = pw_rpc.ids.calculate(service.proto_path())
    output.write_line('\n private:')

    with output.indent():
        output.write_line('friend class ::pw::rpc::internal::MethodLookup;\n')
        output.write_line(f'// Hash of "{service.proto_path()}".')
        output.write_line(
            f'static constexpr uint32_t kServiceId = 0x{service_name_hash:08x};'
        )

        output.write_line()

        # Generate the method table
        output.write_line('static constexpr std::array<'
                          f'{RPC_NAMESPACE}::internal::{method_union},'
                          f' {len(service.methods())}> kMethods = {{')

        with output.indent(4):
            for method in service.methods():
                method_descriptor(method, pw_rpc.ids.calculate(method.name()),
                                  output)

        output.write_line('};\n')

        # Generate the method lookup table
        _method_lookup_table(service, output)

    output.write_line('};')

    output.write_line('\n}  // namespace generated\n')