%module{Google::ProtocolBuffers::Dynamic};
#include "perl_unpollute.h"
#include "introspection.h"
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
%typemap{const Google::ProtocolBuffers::Dynamic::MessageDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::MessageOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::FieldDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::FieldOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::OneofDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::OneofOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::EnumDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::EnumOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::ServiceDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::ServiceOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::MethodDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::MethodOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::FileDef *}{simple}{
%xs_type{O_OBJECT};
};
%typemap{const Google::ProtocolBuffers::Dynamic::FileOptionsDef *}{simple}{
%xs_type{O_OBJECT};
};
%{
#define GPD_INTROSPECTION_RETURN_ARRAY(descriptor_field, package) \
int count = THIS->descriptor_field ## _count(); \
AV *array = newAV(); \
\
av_extend(array, count); \
for (int i = 0; i < count; ++i) { \
SV *item = newSV(0); \
\
sv_setref_iv( \
item, \
"Google::ProtocolBuffers::Dynamic::" #package, \
(IV) THIS->descriptor_field(i) \
);; \
av_push(array, item); \
} \
\
RETVAL = newRV_noinc((SV*) array);
%}
%name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} class gpd::intr::DescriptorOptionsWrapper {
~DescriptorOptionsWrapper();
SV *custom_option_by_name(const std::string &name);
SV *custom_option_by_number(int numbere);
SV *AUTOLOAD() %code%{
if (!THIS->get_attribute(cv, &RETVAL)) {
croak("Unknown option '%.*s'", SvCUR(cv), SvPVX(cv));
}
%};
};
%name{Google::ProtocolBuffers::Dynamic::MessageDef} class google::protobuf::Descriptor {
std::string name();
std::string full_name() const;
int field_count() const;
%name{oneof_count} int oneof_decl_count() const;
%name{find_field_by_number} const Google::ProtocolBuffers::Dynamic::FieldDef *FindFieldByNumber(uint32_t number) const;
%name{find_field_by_name} const Google::ProtocolBuffers::Dynamic::FieldDef *FindFieldByName(const std::string &name) const;
%name{find_oneof_by_name} const Google::ProtocolBuffers::Dynamic::OneofDef *FindOneofByName(const std::string &name) const;
SV* fields() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(field, FieldDef);
%};
SV* oneofs() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(oneof_decl, OneofDef);
%};
bool is_map_entry() const %code{%
RETVAL = THIS->options().map_entry();
%};
const Google::ProtocolBuffers::Dynamic::FileDef *file() const;
const Google::ProtocolBuffers::Dynamic::MessageOptionsDef *options() const %code%{
RETVAL = gpd::intr::options_make_wrapper<gpd::intr::MessageOptionsWrapper>(aTHX_ THIS);
%};
};
%name{Google::ProtocolBuffers::Dynamic::MessageOptionsDef} class gpd::intr::MessageOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
bool deprecated();
};
%name{Google::ProtocolBuffers::Dynamic::FieldDef} class google::protobuf::FieldDescriptor {
std::string name() const;
std::string full_name() const;
uint32_t number() const;
bool is_extension() const;
int label();
%name{is_packed} bool is_packed() const;
bool is_message() const %code%{
RETVAL = THIS->cpp_type() == google::protobuf::FieldDescriptor::CppType::CPPTYPE_MESSAGE;
%};
bool is_string() const %code%{
RETVAL = THIS->cpp_type() == google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING;
%};
bool is_repeated() const;
bool is_primitive() const %code{%
RETVAL = gpd::intr::field_is_primitive(THIS);
%};
bool is_map() const;
// TODO JSON name
%name{descriptor_type} int type() const;
int value_type() const %code{%
RETVAL = gpd::intr::field_value_type(THIS);
%};
SV *default_value() const %code{%
RETVAL = gpd::intr::field_default_value(aTHX_ THIS);
%};
const Google::ProtocolBuffers::Dynamic::MessageDef *containing_type() const;
const Google::ProtocolBuffers::Dynamic::OneofDef *containing_oneof() const;
#if GOOGLE_PROTOBUF_VERSION >= 3012000
const Google::ProtocolBuffers::Dynamic::OneofDef *real_containing_oneof() const;
#else
const Google::ProtocolBuffers::Dynamic::OneofDef *real_containing_oneof() const %code{% PERL_UNUSED_VAR(THIS); RETVAL = NULL; %};
#endif
const Google::ProtocolBuffers::Dynamic::EnumDef *enum_type() const;
const Google::ProtocolBuffers::Dynamic::MessageDef *message_type() const;
#if GOOGLE_PROTOBUF_VERSION >= 3012000
bool has_presence() const;
#else
bool has_presence() const %code{%
RETVAL =
!THIS->is_repeated() && (
THIS->cpp_type() == google::protobuf::FieldDescriptor::CppType::CPPTYPE_MESSAGE ||
THIS->containing_oneof() ||
THIS->file()->syntax() == google::protobuf::FileDescriptor::SYNTAX_PROTO2
);
%};
#endif
const Google::ProtocolBuffers::Dynamic::FileDef *file() const;
const Google::ProtocolBuffers::Dynamic::FieldOptionsDef *options() const %code%{
RETVAL = gpd::intr::options_make_wrapper<gpd::intr::FieldOptionsWrapper>(aTHX_ THIS);
%};
};
%name{Google::ProtocolBuffers::Dynamic::FieldOptionsDef} class gpd::intr::FieldOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
bool deprecated();
};
%name{Google::ProtocolBuffers::Dynamic::OneofDef} class google::protobuf::OneofDescriptor {
std::string name() const;
std::string full_name() const;
int field_count();
const Google::ProtocolBuffers::Dynamic::FieldDef *find_field_by_number(int number) const %code{%
RETVAL = gpd::intr::oneof_find_field_by_number(THIS, number);
%};
const Google::ProtocolBuffers::Dynamic::FieldDef *find_field_by_name(std::string name) const %code{%
RETVAL = gpd::intr::oneof_find_field_by_name(THIS, name);
%};
SV* fields() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(field, FieldDef);
%};
const Google::ProtocolBuffers::Dynamic::MessageDef *containing_type() const;
#if GOOGLE_PROTOBUF_VERSION >= 3012000
bool is_synthetic() const;
#else
bool is_synthetic() const %code{% PERL_UNUSED_VAR(THIS); RETVAL = false; %};
#endif
const Google::ProtocolBuffers::Dynamic::FileDef *file() const;
const Google::ProtocolBuffers::Dynamic::OneofOptionsDef *options() const %code%{
RETVAL = gpd::intr::options_make_wrapper<gpd::intr::OneofOptionsWrapper>(aTHX_ THIS);
%};
};
%name{Google::ProtocolBuffers::Dynamic::OneofOptionsDef} class gpd::intr::OneofOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
};
%name{Google::ProtocolBuffers::Dynamic::EnumDef} class google::protobuf::EnumDescriptor {
std::string name();
std::string full_name() const;
int default_value() const %code%{
RETVAL = gpd::intr::enum_default_value(THIS);
%};
int value_count() const;
SV *find_number_by_name(std::string name) %code{%
const google::protobuf::EnumValueDescriptor *value_descriptor = THIS->FindValueByName(name);
RETVAL = value_descriptor ? newSViv(value_descriptor->number()) : &PL_sv_undef;
%};
SV *find_name_by_number(int number) %code{%
const google::protobuf::EnumValueDescriptor *value_descriptor = THIS->FindValueByNumber(number);
if (value_descriptor) {
const std::string &name = value_descriptor->name();
RETVAL = newSVpvn(name.data(), name.size());
} else {
RETVAL = &PL_sv_undef;
}
%};
SV *values() const %code{%
HV *values = newHV();
for (int i = 0, max = THIS->value_count(); i < max; ++i) {
const google::protobuf::EnumValueDescriptor *value_descriptor = THIS->value(i);
const std::string &name = value_descriptor->name();
SV **value = hv_fetch(values, name.data(), name.size(), 1);
sv_setiv(*value, value_descriptor->number());
}
RETVAL = newRV_noinc((SV *) values);
%};
const Google::ProtocolBuffers::Dynamic::FileDef *file() const;
const Google::ProtocolBuffers::Dynamic::EnumOptionsDef *options() const %code%{
RETVAL = gpd::intr::options_make_wrapper<gpd::intr::EnumOptionsWrapper>(aTHX_ THIS);
%};
};
%name{Google::ProtocolBuffers::Dynamic::EnumOptionsDef} class gpd::intr::EnumOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
bool deprecated();
};
%name{Google::ProtocolBuffers::Dynamic::ServiceDef} class google::protobuf::ServiceDescriptor {
std::string name();
std::string full_name();
SV* methods() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(method, MethodDef);
%};
const Google::ProtocolBuffers::Dynamic::FileDef *file() const;
const Google::ProtocolBuffers::Dynamic::ServiceOptionsDef *options() const %code%{
RETVAL = gpd::intr::options_make_wrapper<gpd::intr::ServiceOptionsWrapper>(aTHX_ THIS);
%};
};
%name{Google::ProtocolBuffers::Dynamic::ServiceOptionsDef} class gpd::intr::ServiceOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
bool deprecated();
};
%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();
};
%name{Google::ProtocolBuffers::Dynamic::FileDef} class google::protobuf::FileDescriptor {
std::string name();
std::string package();
SV* dependencies() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(dependency, FileDef);
%};
SV* public_dependencies() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(public_dependency, FileDef);
%};
SV* messages() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(message_type, MessageDef);
%};
SV* enums() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(enum_type, EnumDef);
%};
SV* services() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(service, ServiceDef);
%};
SV* extensions() const %code{%
GPD_INTROSPECTION_RETURN_ARRAY(extension, FieldDef);
%};
const Google::ProtocolBuffers::Dynamic::FileOptionsDef *options() const %code%{
google::protobuf::DynamicMessageFactory *factory;
google::protobuf::Message *options_dyn;
RETVAL = NULL;
if (gpd::intr::options_make_wrapper(THIS->pool(), THIS->options(), &factory, &options_dyn)) {
RETVAL = new gpd::intr::FileOptionsWrapper(aTHX_ factory, options_dyn, &THIS->options());
}
%};
};
%name{Google::ProtocolBuffers::Dynamic::FileOptionsDef} class gpd::intr::FileOptionsWrapper : public %name{Google::ProtocolBuffers::Dynamic::DescriptorOptionsDef} gpd::intr::DescriptorOptionsWrapper {
bool deprecated();
};
%package{Google::ProtocolBuffers::Dynamic::Mapper};
%{
#undef GPD_INTROSPECTION_RETURN_ARRAY
const Google::ProtocolBuffers::Dynamic::MessageDef*
message_descriptor(SV *)
INIT:
google::protobuf::Descriptor *descriptor = (google::protobuf::Descriptor *) CvXSUBANY(cv).any_ptr;
CODE:
RETVAL = descriptor;
OUTPUT: RETVAL
const Google::ProtocolBuffers::Dynamic::EnumDef*
enum_descriptor(SV *)
INIT:
google::protobuf::EnumDescriptor *descriptor = (google::protobuf::EnumDescriptor *) CvXSUBANY(cv).any_ptr;
CODE:
RETVAL = descriptor;
OUTPUT: RETVAL
UV
constant()
CODE:
RETVAL = CvXSUBANY(cv).any_uv;
OUTPUT: RETVAL
const Google::ProtocolBuffers::Dynamic::ServiceDef*
service_descriptor(SV *)
INIT:
google::protobuf::ServiceDescriptor *descriptor = (google::protobuf::ServiceDescriptor *) CvXSUBANY(cv).any_ptr;
CODE:
RETVAL = descriptor;
OUTPUT: RETVAL
#define DESCRIPTOR_TYPE(name) \
gpd::intr::define_constant(aTHX_ "DESCRIPTOR_" #name, "descriptor", google::protobuf::FieldDescriptor::TYPE_##name);
#define VALUE_TYPE(name) \
gpd::intr::define_constant(aTHX_ "VALUE_" #name, "values", gpd::intr::VALUE_##name);
#define LABEL_TYPE(name) \
gpd::intr::define_constant(aTHX_ "LABEL_" #name, "labels", google::protobuf::FieldDescriptor::LABEL_##name);
BOOT:
LABEL_TYPE(OPTIONAL);
LABEL_TYPE(REPEATED);
LABEL_TYPE(REQUIRED);
DESCRIPTOR_TYPE(DOUBLE);
DESCRIPTOR_TYPE(FLOAT);
DESCRIPTOR_TYPE(INT64);
DESCRIPTOR_TYPE(UINT64);
DESCRIPTOR_TYPE(INT32);
DESCRIPTOR_TYPE(FIXED64);
DESCRIPTOR_TYPE(FIXED32);
DESCRIPTOR_TYPE(BOOL);
DESCRIPTOR_TYPE(STRING);
DESCRIPTOR_TYPE(GROUP);
DESCRIPTOR_TYPE(MESSAGE);
DESCRIPTOR_TYPE(BYTES);
DESCRIPTOR_TYPE(UINT32);
DESCRIPTOR_TYPE(ENUM);
DESCRIPTOR_TYPE(SFIXED32);
DESCRIPTOR_TYPE(SFIXED64);
DESCRIPTOR_TYPE(SINT32);
DESCRIPTOR_TYPE(SINT64);
VALUE_TYPE(FLOAT);
VALUE_TYPE(DOUBLE);
VALUE_TYPE(BOOL);
VALUE_TYPE(STRING);
VALUE_TYPE(BYTES);
VALUE_TYPE(MESSAGE);
VALUE_TYPE(ENUM);
VALUE_TYPE(INT32);
VALUE_TYPE(UINT32);
VALUE_TYPE(INT64);
VALUE_TYPE(UINT64);
%}