Move map accessors off of upb c accessor codegen.

PiperOrigin-RevId: 668472287
pull/18004/head
Protobuf Team Bot 3 months ago committed by Copybara-Service
parent 36a969296d
commit 07b325e5d7
  1. 2
      rust/upb/lib.rs
  2. 31
      rust/upb/message.rs
  3. 21
      rust/upb/mini_table.rs
  4. 113
      src/google/protobuf/compiler/rust/accessors/map.cc

@ -41,7 +41,7 @@ pub use message_value::{upb_MessageValue, upb_MutableMessageValue};
mod mini_table;
pub use mini_table::{
upb_MiniTable, upb_MiniTableField, upb_MiniTable_FindFieldByNumber,
upb_MiniTable, upb_MiniTableField, upb_MiniTable_FindFieldByNumber, upb_MiniTable_SubMessage,
upb_MiniTable_GetFieldByIndex, RawMiniTable, RawMiniTableField,
};

@ -7,7 +7,8 @@
use super::opaque_pointee::opaque_pointee;
use super::{
upb_ExtensionRegistry, upb_MiniTable, upb_MiniTableField, RawArena, RawArray, StringView,
upb_ExtensionRegistry, upb_MiniTable, upb_MiniTableField, RawArena, RawArray, RawMap,
StringView,
};
use std::ptr::NonNull;
@ -168,13 +169,39 @@ extern "C" {
///
/// # Safety
/// - `m` and `f` must be valid to deref
/// - `f` must be a repeated field associated with `m`
/// - `f` must be a map field associated with `m`
pub fn upb_Message_GetOrCreateMutableArray(
m: RawMessage,
f: *const upb_MiniTableField,
arena: RawArena,
) -> Option<RawArray>;
/// Gets the const upb_Map* that is assigned to the field.
///
/// This may return None which must be treated the same as if it returned
/// Some of a valid RawMap that is empty.
///
/// # Safety
/// - `m` and `f` must be valid to deref
/// - `f` must be a repeated field associated with `m`
pub fn upb_Message_GetMap(m: RawMessage, f: *const upb_MiniTableField) -> Option<RawMap>;
/// Gets or creates a mutable upb_Map* assigned to the corresponding field
/// in the message.
///
/// This will only return None if the Arena allocation fails.
///
/// # Safety
/// - `m` and `f` must be valid to deref
/// - `map_entry_mini_table` must be the MiniTable associated with `f`
/// - `f` must be a map field associated with `m`
pub fn upb_Message_GetOrCreateMutableMap(
m: RawMessage,
map_entry_mini_table: *const upb_MiniTable,
f: *const upb_MiniTableField,
arena: RawArena,
) -> Option<RawMap>;
/// # Safety
/// - `m` and `f` must be valid to deref
/// - `mini_table` must be the MiniTable associated with `m`

@ -15,13 +15,34 @@ opaque_pointee!(upb_MiniTableField);
pub type RawMiniTableField = NonNull<upb_MiniTableField>;
extern "C" {
/// Finds the field with the provided number, will return NULL if no such
/// field is found.
///
/// # Safety
/// - `m` must be legal to deref
pub fn upb_MiniTable_FindFieldByNumber(
m: *const upb_MiniTable,
number: u32,
) -> *const upb_MiniTableField;
/// Gets the field with the corresponding upb field index. This will never
/// return null: the provided number must be within bounds or else this is
/// UB.
///
/// # Safety
/// - `m` must be legal to deref
/// - `number` must be a valid field index in the `m` table
pub fn upb_MiniTable_GetFieldByIndex(
m: *const upb_MiniTable,
number: u32,
) -> *const upb_MiniTableField;
/// Gets the sub-MiniTable associated with `f`.
/// # Safety
/// - `m` and `f` must be valid to deref
/// - `f` must be a mesage or map typed field associated with `m`
pub fn upb_MiniTable_SubMessage(
m: *const upb_MiniTable,
f: *const upb_MiniTableField,
) -> *const upb_MiniTable;
}

@ -7,11 +7,13 @@
#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/accessors/generator.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"
#include "google/protobuf/descriptor.pb.h"
@ -41,30 +43,33 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field,
auto& value_type = *field.message_type()->map_value();
std::string field_name = FieldNameWithCollisionAvoidance(field);
ctx.Emit({{"field", RsSafeName(field_name)},
{"raw_field_name", field_name}, // Never r# prefixed
{"Key", RsTypePath(ctx, key_type)},
{"Value", RsTypePath(ctx, value_type)},
{"view_lifetime", ViewLifetime(accessor_case)},
{"view_self", ViewReceiver(accessor_case)},
{"getter_thunk", ThunkName(ctx, field, "get")},
{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")},
{"getter",
[&] {
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
ctx.Emit(
{{"field", RsSafeName(field_name)},
{"raw_field_name", field_name}, // Never r# prefixed
{"Key", RsTypePath(ctx, key_type)},
{"Value", RsTypePath(ctx, value_type)},
{"view_lifetime", ViewLifetime(accessor_case)},
{"view_self", ViewReceiver(accessor_case)},
{"upb_mt_field_index", UpbMiniTableFieldIndex(field)},
{"getter",
[&] {
if (ctx.is_upb()) {
ctx.Emit(R"rs(
pub fn $field$($view_self$)
-> $pb$::MapView<$view_lifetime$, $Key$, $Value$> {
unsafe {
$getter_thunk$(self.raw_msg())
let f = $pbr$::upb_MiniTable_GetFieldByIndex(
<Self as $pbr$::AssociatedMiniTable>::mini_table(),
$upb_mt_field_index$);
$pbr$::upb_Message_GetMap(self.raw_msg(), f)
.map_or_else(
$pbr$::empty_map::<$Key$, $Value$>,
|raw| $pb$::MapView::from_raw($pbi$::Private, raw)
)
}
})rs");
} else {
ctx.Emit({}, R"rs(
} else {
ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, R"rs(
pub fn $field$($view_self$)
-> $pb$::MapView<$view_lifetime$, $Key$, $Value$> {
unsafe {
@ -72,48 +77,66 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field,
$getter_thunk$(self.raw_msg()))
}
})rs");
}
}},
{"getter_mut",
[&] {
if (accessor_case == AccessorCase::VIEW) {
return;
}
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
}
}},
{"getter_mut",
[&] {
if (accessor_case == AccessorCase::VIEW) {
return;
}
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
pub fn $field$_mut(&mut self)
-> $pb$::MapMut<'_, $Key$, $Value$> {
let raw = unsafe {
$getter_mut_thunk$(self.raw_msg(),
self.arena().raw())
};
let inner = $pbr$::InnerMapMut::new(
raw, self.arena());
unsafe { $pb$::MapMut::from_inner($pbi$::Private, inner) }
unsafe {
let parent_mini_table =
<Self as $pbr$::AssociatedMiniTable>::mini_table();
let f =
$pbr$::upb_MiniTable_GetFieldByIndex(
parent_mini_table,
$upb_mt_field_index$);
let map_entry_mini_table =
$pbr$::upb_MiniTable_SubMessage(
parent_mini_table,
f);
let raw_map =
$pbr$::upb_Message_GetOrCreateMutableMap(
self.raw_msg(),
map_entry_mini_table,
f,
self.arena().raw()).unwrap();
let inner = $pbr$::InnerMapMut::new(
raw_map, self.arena());
$pb$::MapMut::from_inner($pbi$::Private, inner)
}
})rs");
} else {
ctx.Emit({}, R"rs(
} else {
ctx.Emit({{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}},
R"rs(
pub fn $field$_mut(&mut self)
-> $pb$::MapMut<'_, $Key$, $Value$> {
let inner = $pbr$::InnerMapMut::new(
unsafe { $getter_mut_thunk$(self.raw_msg()) });
unsafe { $pb$::MapMut::from_inner($pbi$::Private, inner) }
})rs");
}
}},
{"setter",
[&] {
if (accessor_case == AccessorCase::VIEW) {
return;
}
ctx.Emit({}, R"rs(
}
}},
{"setter",
[&] {
if (accessor_case == AccessorCase::VIEW) {
return;
}
ctx.Emit({}, R"rs(
pub fn set_$raw_field_name$(&mut self, src: impl $pb$::IntoProxied<$pb$::Map<$Key$, $Value$>>) {
// TODO: b/355493062 - Fix this extra copy.
self.$field$_mut().copy_from(src.into_proxied($pbi$::Private).as_view());
}
)rs");
}}},
R"rs(
}}},
R"rs(
$getter$
$getter_mut$
$setter$
@ -121,6 +144,8 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field,
}
void Map::InExternC(Context& ctx, const FieldDescriptor& field) const {
if (ctx.is_upb()) return;
ctx.Emit(
{
{"getter_thunk", ThunkName(ctx, field, "get")},
@ -148,6 +173,8 @@ void Map::InExternC(Context& ctx, const FieldDescriptor& field) const {
}
void Map::InThunkCc(Context& ctx, const FieldDescriptor& field) const {
ABSL_CHECK(ctx.is_cpp());
ctx.Emit({{"field", cpp::FieldName(&field)},
{"Key", MapElementTypeName(*field.message_type()->map_key())},
{"Value", MapElementTypeName(*field.message_type()->map_value())},

Loading…
Cancel
Save