This unifies the duplicated logic that we had for each different non-repeated field to emit these same 3 methods for each of the different field types, and moves the has/clear off of upb-accessors-C-codegen and onto the upb-C-API for all cases (matching the singular scalars case which moved in a previous change). PiperOrigin-RevId: 667953223pull/17944/head
parent
182699f8fd
commit
336c9c324c
11 changed files with 355 additions and 312 deletions
@ -0,0 +1,134 @@ |
||||
#include "google/protobuf/compiler/rust/accessors/with_presence.h" |
||||
|
||||
#include <string> |
||||
|
||||
#include "absl/log/absl_check.h" |
||||
#include "google/protobuf/compiler/cpp/helpers.h" |
||||
#include "google/protobuf/compiler/rust/accessors/accessor_case.h" |
||||
#include "google/protobuf/compiler/rust/context.h" |
||||
#include "google/protobuf/compiler/rust/naming.h" |
||||
#include "google/protobuf/compiler/rust/upb_helpers.h" |
||||
#include "google/protobuf/descriptor.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace rust { |
||||
|
||||
void WithPresenceAccessorsInMsgImpl(Context& ctx, const FieldDescriptor& field, |
||||
AccessorCase accessor_case) { |
||||
ABSL_CHECK(field.has_presence()); |
||||
|
||||
std::string field_name = FieldNameWithCollisionAvoidance(field); |
||||
|
||||
ctx.Emit( |
||||
{{"field", RsSafeName(field_name)}, |
||||
{"raw_field_name", field_name}, // Never r# prefixed
|
||||
{"view_type", RsViewType(ctx, field, ViewLifetime(accessor_case))}, |
||||
{"view_self", ViewReceiver(accessor_case)}, |
||||
{"hazzer", |
||||
[&] { |
||||
if (ctx.is_cpp()) { |
||||
ctx.Emit({{"hazzer_thunk", ThunkName(ctx, field, "has")}}, |
||||
R"rs( |
||||
pub fn has_$raw_field_name$($view_self$) -> bool { |
||||
unsafe { |
||||
$hazzer_thunk$(self.raw_msg()) |
||||
} |
||||
} |
||||
)rs"); |
||||
} else { |
||||
ctx.Emit({{"upb_mt_field_index", UpbMiniTableFieldIndex(field)}}, |
||||
R"rs( |
||||
pub fn has_$raw_field_name$($view_self$) -> bool { |
||||
unsafe { |
||||
let f = $pbr$::upb_MiniTable_GetFieldByIndex( |
||||
<Self as $pbr$::AssociatedMiniTable>::mini_table(), |
||||
$upb_mt_field_index$); |
||||
$pbr$::upb_Message_HasBaseField(self.raw_msg(), f) |
||||
} |
||||
} |
||||
)rs"); |
||||
} |
||||
}}, |
||||
{"clearer", |
||||
[&] { |
||||
if (accessor_case == AccessorCase::VIEW) return; |
||||
if (ctx.is_cpp()) { |
||||
ctx.Emit({{"clearer_thunk", ThunkName(ctx, field, "clear")}}, |
||||
R"rs( |
||||
pub fn clear_$raw_field_name$(&mut self) { |
||||
unsafe { $clearer_thunk$(self.raw_msg()) } |
||||
})rs"); |
||||
} else { |
||||
ctx.Emit({{"upb_mt_field_index", UpbMiniTableFieldIndex(field)}}, |
||||
R"rs( |
||||
pub fn clear_$raw_field_name$(&mut self) { |
||||
unsafe { |
||||
let mt = <Self as $pbr$::AssociatedMiniTable>::mini_table(); |
||||
let f = $pbr$::upb_MiniTable_GetFieldByIndex( |
||||
mt, $upb_mt_field_index$); |
||||
$pbr$::upb_Message_ClearBaseField(self.raw_msg(), f); |
||||
} |
||||
})rs"); |
||||
} |
||||
}}, |
||||
{"opt_getter", |
||||
[&] { |
||||
// Cord fields don't support the _opt getter.
|
||||
if (field.options().ctype() == FieldOptions::CORD) return; |
||||
ctx.Emit( |
||||
R"rs( |
||||
pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<$view_type$> { |
||||
$pb$::Optional::new(self.$field$(), self.has_$raw_field_name$()) |
||||
} |
||||
)rs"); |
||||
}}}, |
||||
R"rs( |
||||
$hazzer$ |
||||
$clearer$ |
||||
$opt_getter$ |
||||
)rs"); |
||||
} |
||||
|
||||
void WithPresenceAccessorsInExternC(Context& ctx, |
||||
const FieldDescriptor& field) { |
||||
ABSL_CHECK(field.has_presence()); |
||||
|
||||
if (ctx.is_upb()) return; |
||||
|
||||
ctx.Emit( |
||||
{ |
||||
{"hazzer_thunk", ThunkName(ctx, field, "has")}, |
||||
{"clearer_thunk", ThunkName(ctx, field, "clear")}, |
||||
}, |
||||
R"rs( |
||||
fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; |
||||
fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); |
||||
)rs"); |
||||
} |
||||
|
||||
void WithPresenceAccessorsInThunkCc(Context& ctx, |
||||
const FieldDescriptor& field) { |
||||
ABSL_CHECK(ctx.is_cpp()); |
||||
ABSL_CHECK(field.has_presence()); |
||||
|
||||
ctx.Emit( |
||||
{ |
||||
{"field", cpp::FieldName(&field)}, |
||||
{"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, |
||||
{"hazzer_thunk", ThunkName(ctx, field, "has")}, |
||||
{"clearer_thunk", ThunkName(ctx, field, "clear")}, |
||||
}, |
||||
R"rs( |
||||
bool $hazzer_thunk$($QualifiedMsg$* msg) { |
||||
return msg->has_$field$(); |
||||
} |
||||
void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } |
||||
)rs"); |
||||
} |
||||
|
||||
} // namespace rust
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,28 @@ |
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__ |
||||
|
||||
#include "google/protobuf/compiler/rust/accessors/accessor_case.h" |
||||
#include "google/protobuf/compiler/rust/context.h" |
||||
#include "google/protobuf/descriptor.h" |
||||
|
||||
// Helper functions for generating the common accessors that any with-presence
|
||||
// field have (the hassers, clearers, and the Optional<> getter).
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace rust { |
||||
|
||||
void WithPresenceAccessorsInMsgImpl(Context& ctx, const FieldDescriptor& field, |
||||
AccessorCase accessor_case); |
||||
|
||||
void WithPresenceAccessorsInExternC(Context& ctx, const FieldDescriptor& field); |
||||
|
||||
void WithPresenceAccessorsInThunkCc(Context& ctx, const FieldDescriptor& field); |
||||
|
||||
} // namespace rust
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__
|
Loading…
Reference in new issue