Google-ProtocolBuffers-Dynamic

 view release on metacpan or  search on metacpan

lib/Google/ProtocolBuffers/Dynamic.pm  view on Meta::CPAN

implementation, but supports generating a gRPC client using
L<Grpc::XS> (other implementations might be provided in the future).

In addition, there is a C<noop> service mapping mode that exposes
introspection information to simplify the mapping of external RPC
implementation on top of C<Google::ProtocolBuffers::Dynamic>.

The exact interface of mapped methods depends on the underlying RPC
implementation (for example, for L<Grpc::XS>, the return value is a
subclass of L<Grpc::Client::AbstractCall>) and whether the method uses
client/server streaming.

=head2 INTROSPECTION

All mapped entities provide access to an introspection object that
describes the Protocol Buffers object definition.

Each mapped message has a C<message_descriptor> class method returning a L<MessageDef|Google::ProtocolBuffers::Dynamic::Introspection/Google::ProtocolBuffers::Dynamic::MessageDef> object.

Each mapped enum has an C<enum_descriptor> class method returning an L<EnumDef|Google::ProtocolBuffers::Dynamic::Introspection/Google::ProtocolBuffers::Dynamic::EnumDef> object.

lib/Google/ProtocolBuffers/Dynamic/Introspection.pod  view on Meta::CPAN

    $message_def = $method_def->input_type;

Input type for the method.

=head2 output_type

    $message_def = $method_def->output_type;

Output type for the method.

=head2 client_streaming

    $is_streaming_client = $method_def->client_streaming.

True if the service accepts streaming input (i.e. the input type has
the C<stream> annotation in the method definition).

=head2 server_streaming

    $is_streaming_server = $method_def->server_streaming.

True if the service produces streaming output (i.e. the output type has
the C<stream> annotation in the method definition).

=head2 file

    $file_def = $method_def->file;

Returns the file this method was defined in.

=head2 options

src/dynamic.cpp  view on Meta::CPAN

    }

    void push_method_def(ServiceDef *service_def, const MethodDescriptor *descriptor, const MessageDef *input_message, const MessageDef *output_message) {
        service_def->add_method(
            MethodDef(
                descriptor->name(),
                descriptor->full_name(),
                service_def,
                input_message,
                output_message,
                descriptor->client_streaming(),
                descriptor->server_streaming()
            )
        );
    }
}

void Dynamic::map_message(pTHX_ const string &message, const string &perl_package, const MappingOptions &options) {
    const DescriptorPool *pool = descriptor_loader.pool();
    const Descriptor *descriptor = pool->FindMessageTypeByName(message);

    if (descriptor == NULL) {

src/dynamic.cpp  view on Meta::CPAN

    SvREFCNT_inc(base_stub_package);
    av_push(isa, base_stub_package);
    load_module(PERL_LOADMOD_NOIMPORT, base_stub_package, NULL);

    for (int i = 0, max = descriptor->method_count(); i < max; ++i) {
        const MethodDescriptor *method = descriptor->method(i);
        string full_method = "/" + descriptor->full_name() + "/" + method->name().c_str();
        const Descriptor *input = method->input_type(), *output = method->output_type();
        const MessageDef *input_def = def_builder.GetMessageDef(input);
        const MessageDef *output_def = def_builder.GetMessageDef(output);
        MethodMapper *mapper = new MethodMapper(aTHX_ this, full_method, input_def, output_def, method->client_streaming(), method->server_streaming());

        copy_and_bind(aTHX_ "grpc_xs_call_service_passthrough", method->name().c_str(), perl_package, mapper);

        pending_methods.push_back(mapper);
        push_method_def(service_def, method, input_def, output_def);
    }
}

void Dynamic::resolve_references() {
    for (std::vector<Mapper *>::iterator it = pending.begin(), en = pending.end(); it != en; ++it)

src/mapper.cpp  view on Meta::CPAN

        SvROK_on(field_ref);
    } else {
        if (!SvROK(field_ref))
            croak("Value of field '%s' is not a reference", field->full_name().c_str());
        SvREFCNT_dec(SvRV(field_ref));
    }
    SvRV_set(field_ref, SvRV(ref));
    SvREFCNT_inc(SvRV(field_ref));
}

MethodMapper::MethodMapper(pTHX_ Dynamic *_registry, const string &method, const MessageDef *_input_def, const MessageDef *_output_def, bool client_streaming, bool server_streaming) :
        registry(_registry),
        input_def(_input_def),
        output_def(_output_def) {
    SET_THX_MEMBER;

    registry->ref();

    method_name_key_sv = newSVpvs_share("method");
    serialize_key_sv = newSVpvs_share("serialize");
    deserialize_key_sv = newSVpvs_share("deserialize");
    method_name_sv = newSVpvn_share(method.data(), method.length(), 0);
    serialize_sv = NULL;
    deserialize_sv = NULL;

    const char *grpc_name;
    if (client_streaming) {
        if (server_streaming) {
            grpc_name = "Grpc::Client::BaseStub::_bidiRequest";
        } else {
            grpc_name = "Grpc::Client::BaseStub::_clientStreamRequest";
        }
    } else {
        if (server_streaming) {
            grpc_name = "Grpc::Client::BaseStub::_serverStreamRequest";
        } else {
            grpc_name = "Grpc::Client::BaseStub::_simpleRequest";
        }
    }

    grpc_call_sv = get_cv(grpc_name, 0);
    if (grpc_call_sv == NULL)
        croak("Unable to resolve function '%s'", grpc_name);
}

src/mapper.h  view on Meta::CPAN

    void copy_default(SV *target);
    void copy_value(SV *target, SV *value);
    void clear_oneof(HV *self);

    const Mapper::Field *field;
    const Mapper *mapper;
};

class MethodMapper : public Refcounted {
public:
    MethodMapper(pTHX_ Dynamic *registry, const std::string &method, const upb::MessageDef *input_def, const upb::MessageDef *output_def, bool client_streaming, bool server_streaming);
    ~MethodMapper();

    SV *method_name_key() const { return method_name_key_sv; }
    SV *serialize_key() const { return serialize_key_sv; }
    SV *deserialize_key() const { return deserialize_key_sv; }

    SV *method_name() const { return method_name_sv; }
    SV *serialize() const { return serialize_sv; }
    SV *deserialize() const { return deserialize_sv; }
    SV *grpc_call() const { return (SV *) grpc_call_sv; }

src/servicedef.h  view on Meta::CPAN

// is much quicker than implementing it in uPB
namespace gpd {
    struct ServiceDef;

    struct MethodDef {
        MethodDef(const std::string &name,
                  const std::string &full_name,
                  const ServiceDef *containing_service,
                  const upb::MessageDef *input_type,
                  const upb::MessageDef *output_type,
                  bool client_streaming,
                  bool server_streaming) :
            _name(name),
            _full_name(full_name),
            _containing_service(containing_service),
            _input_type(input_type),
            _output_type(output_type),
            _client_streaming(client_streaming),
            _server_streaming(server_streaming)
        { }

        const std::string &name() const { return _name; }
        const std::string &full_name() const { return _full_name; }
        const ServiceDef *containing_service() const { return _containing_service; }
        const upb::MessageDef *input_type() const { return _input_type; }
        const upb::MessageDef *output_type() const { return _output_type; }
        bool client_streaming() const { return _client_streaming; }
        bool server_streaming() const { return _server_streaming; }

    private:
        std::string _name;
        std::string _full_name;

        const ServiceDef *_containing_service;
        const upb::MessageDef *_input_type;
        const upb::MessageDef *_output_type;

        bool _client_streaming, _server_streaming;
    };

    struct ServiceDef {
        ServiceDef(const std::string &full_name) :
            _full_name(full_name)
        { }

        void add_method(const MethodDef &method) {
            _methods.push_back(method);
        }

t/357_service_introspection.t  view on Meta::CPAN

    my $service = $package->service_descriptor;
    my $methods = $service->methods;

    note("Testing mapping for '$type'");
    is($service->full_name, 'helloworld.Greeter');
    is(scalar @$methods, 4);

    my @methods = sort { $a->name cmp $b->name } @$methods;

    eq_or_diff(method_attrs($methods[0]), {
        client_streaming    => true,
        server_streaming    => false,
        name                => 'JoinedHello',
        service             => 'helloworld.Greeter',
        full_name           => 'helloworld.Greeter.JoinedHello',
        input               => 'helloworld.HelloRequest',
        output              => 'helloworld.HelloReply',
    });

    eq_or_diff(method_attrs($methods[1]), {
        client_streaming    => false,
        server_streaming    => false,
        name                => 'SayHello',
        service             => 'helloworld.Greeter',
        full_name           => 'helloworld.Greeter.SayHello',
        input               => 'helloworld.HelloRequest',
        output              => 'helloworld.HelloReply',
    });

    eq_or_diff(method_attrs($methods[2]), {
        client_streaming    => false,
        server_streaming    => true,
        name                => 'SplitHello',
        service             => 'helloworld.Greeter',
        full_name           => 'helloworld.Greeter.SplitHello',
        input               => 'helloworld.HelloRequest',
        output              => 'helloworld.HelloReply',
    });

    eq_or_diff(method_attrs($methods[3]), {
        client_streaming    => true,
        server_streaming    => true,
        name                => 'WavingHello',
        service             => 'helloworld.Greeter',
        full_name           => 'helloworld.Greeter.WavingHello',
        input               => 'helloworld.HelloRequest',
        output              => 'helloworld.HelloReply',
    });
}

sub method_attrs {
    return {
        name                => $_[0]->name,
        full_name           => $_[0]->full_name,
        service             => $_[0]->containing_service->full_name,
        input               => $_[0]->input_type->full_name,
        output              => $_[0]->output_type->full_name,
        client_streaming    => $_[0]->client_streaming,
        server_streaming    => $_[0]->server_streaming,
    };
}

xsp/introspection.xsp  view on Meta::CPAN

};

%name{Google::ProtocolBuffers::Dynamic::MethodDef} class google::protobuf::MethodDescriptor {
    std::string name();
    std::string full_name();

    %name{containing_service} const Google::ProtocolBuffers::Dynamic::ServiceDef *service();
    const Google::ProtocolBuffers::Dynamic::MessageDef *input_type();
    const Google::ProtocolBuffers::Dynamic::MessageDef *output_type();

    bool client_streaming();
    bool server_streaming();

    const Google::ProtocolBuffers::Dynamic::FileDef *file() const;

    const Google::ProtocolBuffers::Dynamic::MethodOptionsDef *options() const %code%{
        RETVAL = gpd::intr::options_make_wrapper<gpd::intr::MethodOptionsWrapper>(aTHX_ THIS);
    %};
};

%name{Google::ProtocolBuffers::Dynamic::MethodOptionsDef} class gpd::intr::MethodOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
    bool deprecated();



( run in 0.507 second using v1.01-cache-2.11-cpan-4d50c553e7e )