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 )