Refactor builtin map key type naming info for enums

PiperOrigin-RevId: 609434380
pull/15901/head
Alyssa Haroldsen 9 months ago committed by Copybara-Service
parent e4eac25bb3
commit b33682537b
  1. 1
      src/google/protobuf/compiler/rust/BUILD.bazel
  2. 136
      src/google/protobuf/compiler/rust/message.cc
  3. 51
      src/google/protobuf/compiler/rust/naming.cc
  4. 35
      src/google/protobuf/compiler/rust/naming.h

@ -198,6 +198,7 @@ cc_library(
":context",
":rust_field_type",
"//src/google/protobuf",
"//src/google/protobuf:port",
"//src/google/protobuf/compiler:code_generator",
"//src/google/protobuf/compiler/cpp:names_internal",
"@com_google_absl//absl/container:flat_hash_set",

@ -406,39 +406,6 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
ABSL_LOG(FATAL) << "unreachable";
}
// (
// 1) identifier used in thunk name - keep in sync with kMapKeyCppTypes!,
// 2) Rust key typename (K in Map<K, V>, so e.g. `[u8]` for bytes),
// 3) whether previous needs $pb$ prefix,
// 4) key typename as used in function parameter (e.g. `PtrAndLen` for bytes),
// 5) whether previous needs $pbi$ prefix,
// 6) expression converting `key` variable to expected thunk param type,
// 7) fn expression converting thunk param type to map key type (e.g. from
// PtrAndLen to &[u8]).
// 8) whether previous needs $pb$ prefix,
//)
struct MapKeyType {
absl::string_view thunk_ident;
absl::string_view key_t;
bool needs_key_t_prefix;
absl::string_view param_key_t;
bool needs_param_key_t_prefix;
absl::string_view key_expr;
absl::string_view from_ffi_key_expr;
bool needs_from_ffi_key_prefix;
};
constexpr MapKeyType kMapKeyTypes[] = {
{"i32", "i32", false, "i32", false, "key", "k", false},
{"u32", "u32", false, "u32", false, "key", "k", false},
{"i64", "i64", false, "i64", false, "key", "k", false},
{"u64", "u64", false, "u64", false, "key", "k", false},
{"bool", "bool", false, "bool", false, "key", "k", false},
{"string", "ProtoStr", true, "PtrAndLen", true, "key.as_bytes().into()",
"ProtoStr::from_utf8_unchecked(k.as_ref())", true},
{"bytes", "[u8]", false, "PtrAndLen", true, "key.into()", "k.as_ref()",
false}};
void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
@ -456,39 +423,13 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
{"map_iter_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "iter")},
{"map_iter_next_thunk",
RawMapThunk(ctx, msg, t.thunk_ident, "iter_next")},
{"key_expr", t.key_expr},
io::Printer::Sub({"param_key_t",
[&] {
if (t.needs_param_key_t_prefix) {
ctx.Emit({{"param_key_t", t.param_key_t}},
"$pbi$::$param_key_t$");
} else {
ctx.Emit({{"param_key_t", t.param_key_t}},
"$param_key_t$");
}
}})
{"key_expr", t.rs_to_ffi_key_expr},
io::Printer::Sub("ffi_key_t", [&] { ctx.Emit(t.rs_ffi_key_t); })
.WithSuffix(""),
io::Printer::Sub({"key_t",
[&] {
if (t.needs_key_t_prefix) {
ctx.Emit({{"key_t", t.key_t}},
"$pb$::$key_t$");
} else {
ctx.Emit({{"key_t", t.key_t}}, "$key_t$");
}
}})
io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); })
.WithSuffix(""),
io::Printer::Sub(
{"from_ffi_key_expr",
[&] {
if (t.needs_from_ffi_key_prefix) {
ctx.Emit({{"from_ffi_key_expr", t.from_ffi_key_expr}},
"$pb$::$from_ffi_key_expr$");
} else {
ctx.Emit({{"from_ffi_key_expr", t.from_ffi_key_expr}},
"$from_ffi_key_expr$");
}
}})
io::Printer::Sub("from_ffi_key_expr",
[&] { ctx.Emit(t.rs_from_ffi_key_expr); })
.WithSuffix("")},
R"rs(
extern "C" {
@ -496,11 +437,11 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
fn $map_free_thunk$(m: $pbi$::RawMap);
fn $map_clear_thunk$(m: $pbi$::RawMap);
fn $map_size_thunk$(m: $pbi$::RawMap) -> usize;
fn $map_insert_thunk$(m: $pbi$::RawMap, key: $param_key_t$, value: $pbi$::RawMessage) -> bool;
fn $map_get_thunk$(m: $pbi$::RawMap, key: $param_key_t$, value: *mut $pbi$::RawMessage) -> bool;
fn $map_remove_thunk$(m: $pbi$::RawMap, key: $param_key_t$, value: *mut $pbi$::RawMessage) -> bool;
fn $map_insert_thunk$(m: $pbi$::RawMap, key: $ffi_key_t$, value: $pbi$::RawMessage) -> bool;
fn $map_get_thunk$(m: $pbi$::RawMap, key: $ffi_key_t$, value: *mut $pbi$::RawMessage) -> bool;
fn $map_remove_thunk$(m: $pbi$::RawMap, key: $ffi_key_t$, value: *mut $pbi$::RawMessage) -> bool;
fn $map_iter_thunk$(m: $pbi$::RawMap) -> $pbr$::UntypedMapIterator;
fn $map_iter_next_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $param_key_t$, value: *mut $pbi$::RawMessage);
fn $map_iter_next_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $pbi$::RawMessage);
}
impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ {
fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> {
@ -568,7 +509,7 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
iter.as_raw_mut($pbi$::Private).next_unchecked::<$key_t$, Self, _, _>(
$pbi$::Private,
$map_iter_next_thunk$,
|k| $from_ffi_key_expr$,
|ffi_key| $from_ffi_key_expr$,
|raw_msg| $Msg$View::new($pbi$::Private, raw_msg)
)
}
@ -623,16 +564,7 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
}
)rs");
for (const auto& t : kMapKeyTypes) {
ctx.Emit({io::Printer::Sub({"key_t",
[&] {
if (t.needs_key_t_prefix) {
ctx.Emit({{"key_t", t.key_t}},
"$pb$::$key_t$");
} else {
ctx.Emit({{"key_t", t.key_t}},
"$key_t$");
}
}})
ctx.Emit({io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); })
.WithSuffix("")},
R"rs(
impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ {
@ -1261,35 +1193,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
$nested_msg_thunks$
)cc");
// (
// 1) identifier used in thunk name - keep in sync with kMapKeyTypes!,
// 2) c+ key typename (K in Map<K, V>, so e.g. `std::string` for bytes),
// 3) key typename as used in function parameter (e.g. `PtrAndLen` for
// bytes),
// 4) expression converting `key` variable to expected C++ type,
// 5) expression convering `key` variable from the C++ type back into the
// FFI type.
//)
struct MapKeyCppTypes {
absl::string_view thunk_ident;
absl::string_view key_t;
absl::string_view param_key_t;
absl::string_view key_expr;
absl::string_view to_ffi_key_expr;
};
constexpr MapKeyCppTypes kMapKeyCppTypes[] = {
{"i32", "int32_t", "int32_t", "key", "cpp_key"},
{"u32", "uint32_t", "uint32_t", "key", "cpp_key"},
{"i64", "int64_t", "int64_t", "key", "cpp_key"},
{"u64", "uint64_t", "uint64_t", "key", "cpp_key"},
{"bool", "bool", "bool", "key", "cpp_key"},
{"string", "std::string", "google::protobuf::rust_internal::PtrAndLen",
"std::string(key.ptr, key.len)",
"google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size())"},
{"bytes", "std::string", "google::protobuf::rust_internal::PtrAndLen",
"std::string(key.ptr, key.len)",
"google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size())"}};
for (const auto& t : kMapKeyCppTypes) {
for (const auto& t : kMapKeyTypes) {
ctx.Emit(
{
{"map_new_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "new")},
@ -1304,10 +1208,10 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
{"map_iter_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "iter")},
{"map_iter_next_thunk",
RawMapThunk(ctx, msg, t.thunk_ident, "iter_next")},
{"key_t", t.key_t},
{"param_key_t", t.param_key_t},
{"key_expr", t.key_expr},
{"to_ffi_key_expr", t.to_ffi_key_expr},
{"key_t", t.cc_key_t},
{"ffi_key_t", t.cc_ffi_key_t},
{"key_expr", t.cc_from_ffi_key_expr},
{"to_ffi_key_expr", t.cc_to_ffi_key_expr},
{"pkg::Msg", cpp::QualifiedClassName(&msg)},
{"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode.
},
@ -1322,7 +1226,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
return m->size();
}
bool $map_insert_thunk$(google::protobuf::Map<$key_t$, $pkg::Msg$> * m,
$param_key_t$ key, $pkg::Msg$ value) {
$ffi_key_t$ key, $pkg::Msg$ value) {
auto k = $key_expr$;
auto it = m->find(k);
if (it != m->end()) {
@ -1332,7 +1236,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
return true;
}
bool $map_get_thunk$(const google::protobuf::Map<$key_t$, $pkg::Msg$>* m,
$param_key_t$ key, const $pkg::Msg$** value) {
$ffi_key_t$ key, const $pkg::Msg$** value) {
auto it = m->find($key_expr$);
if (it == m->end()) {
return false;
@ -1342,7 +1246,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
return true;
}
bool $map_remove_thunk$(google::protobuf::Map<$key_t$, $pkg::Msg$> * m,
$param_key_t$ key, $pkg::Msg$ * value) {
$ffi_key_t$ key, $pkg::Msg$ * value) {
auto num_removed = m->erase($key_expr$);
return num_removed > 0;
}
@ -1352,7 +1256,7 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
}
void $map_iter_next_thunk$(
const google::protobuf::internal::UntypedMapIterator* iter,
$param_key_t$* key, const $pkg::Msg$** value) {
$ffi_key_t$* key, const $pkg::Msg$** value) {
auto typed_iter = iter->ToTyped<
google::protobuf::Map<$key_t$, $pkg::Msg$>::const_iterator>();
const auto& cpp_key = typed_iter->first;

@ -28,6 +28,9 @@
#include "google/protobuf/compiler/rust/rust_keywords.h"
#include "google/protobuf/descriptor.h"
// Must be included last.
#include "google/protobuf/port_def.inc"
namespace google {
namespace protobuf {
namespace compiler {
@ -386,6 +389,54 @@ absl::string_view MultiCasePrefixStripper::StripPrefix(
return name;
}
PROTOBUF_CONSTINIT const MapKeyType kMapKeyTypes[] = {
{/*thunk_ident=*/"i32", /*rs_key_t=*/"i32", /*rs_ffi_key_t=*/"i32",
/*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key",
/*cc_key_t=*/"int32_t", /*cc_ffi_key_t=*/"int32_t",
/*cc_from_ffi_key_expr=*/"key",
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"u32", /*rs_key_t=*/"u32", /*rs_ffi_key_t=*/"u32",
/*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key",
/*cc_key_t=*/"uint32_t", /*cc_ffi_key_t=*/"uint32_t",
/*cc_from_ffi_key_expr=*/"key",
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"i64", /*rs_key_t=*/"i64", /*rs_ffi_key_t=*/"i64",
/*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key",
/*cc_key_t=*/"int64_t", /*cc_ffi_key_t=*/"int64_t",
/*cc_from_ffi_key_expr=*/"key",
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"u64", /*rs_key_t=*/"u64", /*rs_ffi_key_t=*/"u64",
/*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key",
/*cc_key_t=*/"uint64_t", /*cc_ffi_key_t=*/"uint64_t",
/*cc_from_ffi_key_expr=*/"key",
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"bool", /*rs_key_t=*/"bool", /*rs_ffi_key_t=*/"bool",
/*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key",
/*cc_key_t=*/"bool", /*cc_ffi_key_t=*/"bool",
/*cc_from_ffi_key_expr=*/"key",
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"string",
/*rs_key_t=*/"$pb$::ProtoStr",
/*rs_ffi_key_t=*/"$pbi$::PtrAndLen",
/*rs_to_ffi_key_expr=*/"key.as_bytes().into()",
/*rs_from_ffi_key_expr=*/
"$pb$::ProtoStr::from_utf8_unchecked(ffi_key.as_ref())",
/*cc_key_t=*/"std::string",
/*cc_ffi_key_t=*/"google::protobuf::rust_internal::PtrAndLen",
/*cc_from_ffi_key_expr=*/
"std::string(key.ptr, key.len)", /*cc_to_ffi_key_expr=*/
"google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size())"},
{/*thunk_ident=*/"bytes",
/*rs_key_t=*/"[u8]",
/*rs_ffi_key_t=*/"$pbi$::PtrAndLen",
/*rs_to_ffi_key_expr=*/"key.into()",
/*rs_from_ffi_key_expr=*/"ffi_key.as_ref()",
/*cc_key_t=*/"std::string",
/*cc_ffi_key_t=*/"google::protobuf::rust_internal::PtrAndLen",
/*cc_from_ffi_key_expr=*/
"std::string(key.ptr, key.len)", /*cc_to_ffi_key_expr=*/
"google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size())"}};
} // namespace rust
} // namespace compiler
} // namespace protobuf

@ -106,6 +106,41 @@ class MultiCasePrefixStripper final {
std::string EnumValueRsName(const MultiCasePrefixStripper& stripper,
absl::string_view value_name);
// Describes the names and conversions for a supported map key type.
struct MapKeyType {
// Identifier used in thunk name.
absl::string_view thunk_ident;
// Rust key typename (K in Map<K, V>, so e.g. `[u8]` for bytes).
// This field may have an unexpanded `$pb$` variable.
absl::string_view rs_key_t;
// Rust key typename used by thunks for FFI (e.g. `PtrAndLen` for bytes).
// This field may have an unexpanded `$pbi$` variable.
absl::string_view rs_ffi_key_t;
// Rust expression converting `key: rs_key_t` into an `rs_ffi_key_t`.
absl::string_view rs_to_ffi_key_expr;
// Rust expression converting `ffi_key: rs_ffi_key_t` into an `rs_key_t`.
// This field may have an unexpanded `$pb$` variable.
absl::string_view rs_from_ffi_key_expr;
// C++ key typename (K in Map<K, V>, so e.g. `std::string` for bytes).
absl::string_view cc_key_t;
// C++ key typename used by thunks for FFI (e.g. `PtrAndLen` for bytes).
absl::string_view cc_ffi_key_t;
// C++ expression converting `cc_ffi_key_t key` into a `cc_key_t`.
absl::string_view cc_from_ffi_key_expr;
// C++ expression converting `cc_key_t cpp_key` into a `cc_ffi_key_t`.
absl::string_view cc_to_ffi_key_expr;
};
extern const MapKeyType kMapKeyTypes[7];
} // namespace rust
} // namespace compiler
} // namespace protobuf

Loading…
Cancel
Save