|
|
|
@ -30,6 +30,7 @@ |
|
|
|
|
|
|
|
|
|
#include "google/protobuf/compiler/rust/generator.h" |
|
|
|
|
|
|
|
|
|
#include <optional> |
|
|
|
|
#include <string> |
|
|
|
|
#include <utility> |
|
|
|
|
#include <vector> |
|
|
|
@ -38,7 +39,9 @@ |
|
|
|
|
#include "absl/strings/str_cat.h" |
|
|
|
|
#include "absl/strings/str_replace.h" |
|
|
|
|
#include "absl/strings/string_view.h" |
|
|
|
|
#include "absl/strings/substitute.h" |
|
|
|
|
#include "absl/types/optional.h" |
|
|
|
|
#include "google/protobuf/compiler/cpp/helpers.h" |
|
|
|
|
#include "google/protobuf/compiler/cpp/names.h" |
|
|
|
|
#include "google/protobuf/compiler/rust/upb_kernel.h" |
|
|
|
|
#include "google/protobuf/descriptor.h" |
|
|
|
@ -107,15 +110,166 @@ std::string GetUnderscoreDelimitedFullName(const Descriptor* msg) { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string GetAccessorThunkName( |
|
|
|
|
const FieldDescriptor* field, absl::string_view op, |
|
|
|
|
absl::string_view underscore_delimited_full_name) { |
|
|
|
|
return absl::Substitute("__rust_proto_thunk__$0_$1_$2", |
|
|
|
|
underscore_delimited_full_name, op, field->name()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsSupportedFieldType(const FieldDescriptor* field) { |
|
|
|
|
return !field->is_repeated() && |
|
|
|
|
(field->cpp_type() == FieldDescriptor::CPPTYPE_BOOL || |
|
|
|
|
field->cpp_type() == FieldDescriptor::CPPTYPE_INT64); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string PrimitiveRsTypeName(const FieldDescriptor* field) { |
|
|
|
|
switch (field->cpp_type()) { |
|
|
|
|
case FieldDescriptor::CPPTYPE_INT64: |
|
|
|
|
return "i64"; |
|
|
|
|
case FieldDescriptor::CPPTYPE_BOOL: |
|
|
|
|
return "bool"; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
ABSL_LOG(FATAL) << "Unsupported field type: " << field->type_name(); |
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void GenerateAccessorFns(const Descriptor* msg, google::protobuf::io::Printer& p, |
|
|
|
|
absl::string_view underscore_delimited_full_name) { |
|
|
|
|
for (int i = 0; i < msg->field_count(); ++i) { |
|
|
|
|
const FieldDescriptor* field = msg->field(i); |
|
|
|
|
if (!IsSupportedFieldType(field)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
p.Emit( |
|
|
|
|
{ |
|
|
|
|
{"field_name", field->name()}, |
|
|
|
|
{"FieldType", PrimitiveRsTypeName(field)}, |
|
|
|
|
{"hazzer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "has", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
{"getter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "", underscore_delimited_full_name)}, |
|
|
|
|
{"setter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "set", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
{"clearer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "clear", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
}, |
|
|
|
|
R"rs( |
|
|
|
|
pub fn $field_name$(&self) -> Option<$FieldType$> { |
|
|
|
|
if !unsafe { $hazzer_thunk_name$(self.msg) } { |
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|
Some(unsafe { $getter_thunk_name$(self.msg) }) |
|
|
|
|
} |
|
|
|
|
pub fn $field_name$_set(&mut self, val: Option<$FieldType$>) { |
|
|
|
|
match val { |
|
|
|
|
Some(val) => unsafe { $setter_thunk_name$(self.msg, val) }, |
|
|
|
|
None => unsafe { $clearer_thunk_name$(self.msg) }, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
)rs"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void GenerateAccessorThunkRsDeclarations( |
|
|
|
|
const Descriptor* msg, google::protobuf::io::Printer& p, |
|
|
|
|
std::string underscore_delimited_full_name) { |
|
|
|
|
for (int i = 0; i < msg->field_count(); ++i) { |
|
|
|
|
const FieldDescriptor* field = msg->field(i); |
|
|
|
|
if (!IsSupportedFieldType(field)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
p.Emit( |
|
|
|
|
{ |
|
|
|
|
{"FieldType", PrimitiveRsTypeName(field)}, |
|
|
|
|
{"hazzer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "has", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
{"getter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "", underscore_delimited_full_name)}, |
|
|
|
|
{"setter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "set", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
{"clearer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "clear", |
|
|
|
|
underscore_delimited_full_name)}, |
|
|
|
|
}, |
|
|
|
|
R"rs( |
|
|
|
|
fn $hazzer_thunk_name$(raw_msg: ::__std::ptr::NonNull<u8>) -> bool; |
|
|
|
|
fn $getter_thunk_name$(raw_msg: ::__std::ptr::NonNull<u8>) -> $FieldType$; |
|
|
|
|
fn $setter_thunk_name$(raw_msg: ::__std::ptr::NonNull<u8>, val: $FieldType$); |
|
|
|
|
fn $clearer_thunk_name$(raw_msg: ::__std::ptr::NonNull<u8>); |
|
|
|
|
)rs"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void GenerateAccessorThunksCcDefinitions( |
|
|
|
|
const Descriptor* msg, google::protobuf::io::Printer& p, |
|
|
|
|
absl::string_view underscore_delimited_full_name) { |
|
|
|
|
for (int i = 0; i < msg->field_count(); ++i) { |
|
|
|
|
const FieldDescriptor* field = msg->field(i); |
|
|
|
|
if (!IsSupportedFieldType(field)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
p.Emit( |
|
|
|
|
{{"field_name", field->name()}, |
|
|
|
|
{"FieldType", cpp::PrimitiveTypeName(field->cpp_type())}, |
|
|
|
|
{"namespace", cpp::Namespace(msg)}, |
|
|
|
|
{"hazzer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "has", underscore_delimited_full_name)}, |
|
|
|
|
{"getter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "", underscore_delimited_full_name)}, |
|
|
|
|
{"setter_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "set", underscore_delimited_full_name)}, |
|
|
|
|
{"clearer_thunk_name", |
|
|
|
|
GetAccessorThunkName(field, "clear", |
|
|
|
|
underscore_delimited_full_name)}}, |
|
|
|
|
R"cc( |
|
|
|
|
extern "C" { |
|
|
|
|
bool $hazzer_thunk_name$($namespace$::$Msg$* msg) { |
|
|
|
|
return msg->has_$field_name$(); |
|
|
|
|
} |
|
|
|
|
$FieldType$ $getter_thunk_name$($namespace$::$Msg$* msg) { |
|
|
|
|
return msg->$field_name$(); |
|
|
|
|
} |
|
|
|
|
void $setter_thunk_name$($namespace$::$Msg$* msg, $FieldType$ val) { |
|
|
|
|
msg->set_$field_name$(val); |
|
|
|
|
} |
|
|
|
|
void $clearer_thunk_name$($namespace$::$Msg$* msg) { |
|
|
|
|
msg->clear_$field_name$(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void GenerateForCpp(const FileDescriptor* file, google::protobuf::io::Printer& p) { |
|
|
|
|
for (int i = 0; i < file->message_type_count(); ++i) { |
|
|
|
|
const Descriptor* msg = file->message_type(i); |
|
|
|
|
std::string underscore_delimited_full_name = |
|
|
|
|
GetUnderscoreDelimitedFullName(msg); |
|
|
|
|
p.Emit( |
|
|
|
|
{ |
|
|
|
|
{"Msg", msg->name()}, |
|
|
|
|
{"pkg_Msg", GetUnderscoreDelimitedFullName(msg)}, |
|
|
|
|
{"pkg_Msg", underscore_delimited_full_name}, |
|
|
|
|
{"accessor_fns", |
|
|
|
|
[&] { |
|
|
|
|
GenerateAccessorFns(file->message_type(i), p, |
|
|
|
|
underscore_delimited_full_name); |
|
|
|
|
}}, |
|
|
|
|
{"accessor_thunks", |
|
|
|
|
[&] { |
|
|
|
|
GenerateAccessorThunkRsDeclarations( |
|
|
|
|
file->message_type(i), p, underscore_delimited_full_name); |
|
|
|
|
}}, |
|
|
|
|
}, |
|
|
|
|
R"rs( |
|
|
|
|
#[allow(non_camel_case_types)] |
|
|
|
|
pub struct $Msg$ { |
|
|
|
|
msg: ::__std::ptr::NonNull<u8>, |
|
|
|
|
} |
|
|
|
@ -141,12 +295,15 @@ void GenerateForCpp(const FileDescriptor* file, google::protobuf::io::Printer& p |
|
|
|
|
}; |
|
|
|
|
success.then_some(()).ok_or(::__pb::ParseError) |
|
|
|
|
} |
|
|
|
|
$accessor_fns$ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extern "C" { |
|
|
|
|
fn __rust_proto_thunk__$pkg_Msg$__new() -> ::__std::ptr::NonNull<u8>; |
|
|
|
|
fn __rust_proto_thunk__$pkg_Msg$__serialize(raw_msg: ::__std::ptr::NonNull<u8>) -> ::__pb::SerializedData; |
|
|
|
|
fn __rust_proto_thunk__$pkg_Msg$__deserialize(raw_msg: ::__std::ptr::NonNull<u8>, data: ::__pb::SerializedData) -> bool; |
|
|
|
|
|
|
|
|
|
$accessor_thunks$ |
|
|
|
|
} |
|
|
|
|
)rs"); |
|
|
|
|
} |
|
|
|
@ -155,11 +312,18 @@ void GenerateForCpp(const FileDescriptor* file, google::protobuf::io::Printer& p |
|
|
|
|
void GenerateThunksForCpp(const FileDescriptor* file, google::protobuf::io::Printer& p) { |
|
|
|
|
for (int i = 0; i < file->message_type_count(); ++i) { |
|
|
|
|
const Descriptor* msg = file->message_type(i); |
|
|
|
|
std::string underscore_delimited_full_name = |
|
|
|
|
GetUnderscoreDelimitedFullName(msg); |
|
|
|
|
p.Emit( |
|
|
|
|
{ |
|
|
|
|
{"Msg", msg->name()}, |
|
|
|
|
{"pkg_Msg", GetUnderscoreDelimitedFullName(msg)}, |
|
|
|
|
{"namespace", cpp::Namespace(msg)}, |
|
|
|
|
{"accessor_thunks", |
|
|
|
|
[&] { |
|
|
|
|
GenerateAccessorThunksCcDefinitions( |
|
|
|
|
file->message_type(i), p, underscore_delimited_full_name); |
|
|
|
|
}}, |
|
|
|
|
}, |
|
|
|
|
R"cc( |
|
|
|
|
extern "C" { |
|
|
|
@ -175,6 +339,8 @@ void GenerateThunksForCpp(const FileDescriptor* file, google::protobuf::io::Prin |
|
|
|
|
google::protobuf::rust_internal::SerializedData data) { |
|
|
|
|
return msg->ParseFromArray(data.data, data.len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$accessor_thunks$ |
|
|
|
|
} |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|