Protocol Buffers - Google's data interchange format (grpc依赖) https://developers.google.com/protocol-buffers/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

890 lines
31 KiB

// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "google/protobuf/compiler/rust/message.h"
#include <string>
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/compiler/cpp/helpers.h"
#include "google/protobuf/compiler/cpp/names.h"
#include "google/protobuf/compiler/rust/accessors/accessor_case.h"
#include "google/protobuf/compiler/rust/accessors/accessors.h"
#include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/enum.h"
#include "google/protobuf/compiler/rust/naming.h"
#include "google/protobuf/compiler/rust/oneof.h"
#include "google/protobuf/descriptor.h"
#include "upb_generator/mangle.h"
namespace google {
namespace protobuf {
namespace compiler {
namespace rust {
namespace {
std::string UpbMinitableName(const Descriptor& msg) {
return upb::generator::MessageInit(msg.full_name());
}
void MessageNew(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit({{"new_thunk", ThunkName(ctx, msg, "new")}}, R"rs(
Self { inner: $pbr$::MessageInner { msg: unsafe { $new_thunk$() } } }
)rs");
return;
case Kernel::kUpb:
ctx.Emit({{"new_thunk", ThunkName(ctx, msg, "new")}}, R"rs(
let arena = $pbr$::Arena::new();
Self {
inner: $pbr$::MessageInner {
msg: unsafe { $new_thunk$(arena.raw()) },
arena,
}
}
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
void MessageSerialize(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit({{"serialize_thunk", ThunkName(ctx, msg, "serialize")}}, R"rs(
unsafe { $serialize_thunk$(self.raw_msg()) }
)rs");
return;
case Kernel::kUpb:
ctx.Emit({{"serialize_thunk", ThunkName(ctx, msg, "serialize")}}, R"rs(
let arena = $pbr$::Arena::new();
let mut len = 0;
unsafe {
let data = $serialize_thunk$(self.raw_msg(), arena.raw(), &mut len);
$pbr$::SerializedData::from_raw_parts(arena, data, len)
}
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
void MessageDeserialize(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit(
{
{"deserialize_thunk", ThunkName(ctx, msg, "deserialize")},
},
R"rs(
let success = unsafe {
let data = $pbr$::SerializedData::from_raw_parts(
$NonNull$::new(data.as_ptr() as *mut _).unwrap(),
data.len(),
);
$deserialize_thunk$(self.raw_msg(), data)
};
success.then_some(()).ok_or($pb$::ParseError)
)rs");
return;
case Kernel::kUpb:
ctx.Emit({{"deserialize_thunk", ThunkName(ctx, msg, "parse")}}, R"rs(
let arena = $pbr$::Arena::new();
let msg = unsafe {
$deserialize_thunk$(data.as_ptr(), data.len(), arena.raw())
};
match msg {
None => Err($pb$::ParseError),
Some(msg) => {
//~ This assignment causes self.arena to be dropped and to deallocate
//~ any previous message pointed/owned to by self.inner.msg.
self.inner.arena = arena;
self.inner.msg = msg;
Ok(())
}
}
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
void MessageExterns(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit(
{
{"new_thunk", ThunkName(ctx, msg, "new")},
{"delete_thunk", ThunkName(ctx, msg, "delete")},
{"serialize_thunk", ThunkName(ctx, msg, "serialize")},
{"deserialize_thunk", ThunkName(ctx, msg, "deserialize")},
{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")},
{"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
{"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
{"repeated_get_mut_thunk",
ThunkName(ctx, msg, "repeated_get_mut")},
{"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
{"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
{"repeated_copy_from_thunk",
ThunkName(ctx, msg, "repeated_copy_from")},
},
R"rs(
fn $new_thunk$() -> $pbi$::RawMessage;
fn $delete_thunk$(raw_msg: $pbi$::RawMessage);
fn $serialize_thunk$(raw_msg: $pbi$::RawMessage) -> $pbr$::SerializedData;
fn $deserialize_thunk$(raw_msg: $pbi$::RawMessage, data: $pbr$::SerializedData) -> bool;
fn $copy_from_thunk$(dst: $pbi$::RawMessage, src: $pbi$::RawMessage);
fn $repeated_len_thunk$(raw: $pbi$::RawRepeatedField) -> usize;
fn $repeated_add_thunk$(raw: $pbi$::RawRepeatedField) -> $pbi$::RawMessage;
fn $repeated_get_thunk$(raw: $pbi$::RawRepeatedField, index: usize) -> $pbi$::RawMessage;
fn $repeated_get_mut_thunk$(raw: $pbi$::RawRepeatedField, index: usize) -> $pbi$::RawMessage;
fn $repeated_clear_thunk$(raw: $pbi$::RawRepeatedField);
fn $repeated_copy_from_thunk$(dst: $pbi$::RawRepeatedField, src: $pbi$::RawRepeatedField);
)rs");
return;
case Kernel::kUpb:
ctx.Emit(
{
{"new_thunk", ThunkName(ctx, msg, "new")},
{"serialize_thunk", ThunkName(ctx, msg, "serialize")},
{"deserialize_thunk", ThunkName(ctx, msg, "parse")},
{"minitable", UpbMinitableName(msg)},
},
R"rs(
fn $new_thunk$(arena: $pbi$::RawArena) -> $pbi$::RawMessage;
fn $serialize_thunk$(msg: $pbi$::RawMessage, arena: $pbi$::RawArena, len: &mut usize) -> $NonNull$<u8>;
fn $deserialize_thunk$(data: *const u8, size: usize, arena: $pbi$::RawArena) -> Option<$pbi$::RawMessage>;
/// Opaque wrapper for this message's MiniTable. The only valid way to
/// reference this static is with `std::ptr::addr_of!(..)`.
static $minitable$: $pbr$::OpaqueMiniTable;
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
void MessageDrop(Context& ctx, const Descriptor& msg) {
if (ctx.is_upb()) {
// Nothing to do here; drop glue (which will run drop(self.arena)
// automatically) is sufficient.
return;
}
ctx.Emit({{"delete_thunk", ThunkName(ctx, msg, "delete")}}, R"rs(
unsafe { $delete_thunk$(self.raw_msg()); }
)rs");
}
void MessageSettableValue(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit({{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}}, R"rs(
impl<'msg> $pb$::SettableValue<$Msg$> for $Msg$View<'msg> {
fn set_on<'dst>(
self, _private: $pbi$::Private, mutator: $pb$::Mut<'dst, $Msg$>)
where $Msg$: 'dst {
unsafe { $copy_from_thunk$(mutator.inner.msg(), self.msg) };
}
}
)rs");
return;
case Kernel::kUpb:
// TODO: Add owned SettableValue impl for upb messages.
ctx.Emit({{"minitable", UpbMinitableName(msg)}}, R"rs(
impl<'msg> $pb$::SettableValue<$Msg$> for $Msg$View<'msg> {
fn set_on<'dst>(
self, _private: $pbi$::Private, mutator: $pb$::Mut<'dst, $Msg$>)
where $Msg$: 'dst {
unsafe { $pbr$::upb_Message_DeepCopy(
mutator.inner.msg(),
self.msg,
$std$::ptr::addr_of!($minitable$),
mutator.inner.arena($pbi$::Private).raw(),
) };
}
}
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
switch (ctx.opts().kernel) {
case Kernel::kCpp:
ctx.Emit(
{
{"Msg", RsSafeName(msg.name())},
{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")},
{"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
{"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
{"repeated_get_mut_thunk",
ThunkName(ctx, msg, "repeated_get_mut")},
{"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
{"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
{"repeated_copy_from_thunk",
ThunkName(ctx, msg, "repeated_copy_from")},
},
R"rs(
unsafe impl $pb$::ProxiedInRepeated for $Msg$ {
fn repeated_len(f: $pb$::View<$pb$::Repeated<Self>>) -> usize {
// SAFETY: `f.as_raw()` is a valid `RepeatedPtrField*`.
unsafe { $repeated_len_thunk$(f.as_raw($pbi$::Private)) }
}
unsafe fn repeated_set_unchecked(
mut f: $pb$::Mut<$pb$::Repeated<Self>>,
i: usize,
v: $pb$::View<Self>,
) {
// SAFETY:
// - `f.as_raw()` is a valid `RepeatedPtrField*`.
// - `i < len(f)` is promised by caller.
// - `v.raw_msg()` is a valid `const Message&`.
unsafe {
$copy_from_thunk$(
$repeated_get_mut_thunk$(f.as_raw($pbi$::Private), i),
v.raw_msg(),
);
}
}
unsafe fn repeated_get_unchecked(
f: $pb$::View<$pb$::Repeated<Self>>,
i: usize,
) -> $pb$::View<Self> {
// SAFETY:
// - `f.as_raw()` is a valid `const RepeatedPtrField&`.
// - `i < len(f)` is promised by caller.
let msg = unsafe { $repeated_get_thunk$(f.as_raw($pbi$::Private), i) };
$pb$::View::<Self>::new($pbi$::Private, msg)
}
fn repeated_clear(mut f: $pb$::Mut<$pb$::Repeated<Self>>) {
// SAFETY:
// - `f.as_raw()` is a valid `RepeatedPtrField*`.
unsafe { $repeated_clear_thunk$(f.as_raw($pbi$::Private)) };
}
fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: $pb$::View<Self>) {
// SAFETY:
// - `f.as_raw()` is a valid `RepeatedPtrField*`.
// - `v.raw_msg()` is a valid `const Message&`.
unsafe {
let new_elem = $repeated_add_thunk$(f.as_raw($pbi$::Private));
$copy_from_thunk$(new_elem, v.raw_msg());
}
}
fn repeated_copy_from(
src: $pb$::View<$pb$::Repeated<Self>>,
mut dest: $pb$::Mut<$pb$::Repeated<Self>>,
) {
// SAFETY:
// - `dest.as_raw()` is a valid `RepeatedPtrField*`.
// - `src.as_raw()` is a valid `const RepeatedPtrField&`.
unsafe {
$repeated_copy_from_thunk$(dest.as_raw($pbi$::Private), src.as_raw($pbi$::Private));
}
}
}
)rs");
return;
case Kernel::kUpb:
ctx.Emit(
{
{"minitable", UpbMinitableName(msg)},
{"new_thunk", ThunkName(ctx, msg, "new")},
},
R"rs(
unsafe impl $pb$::ProxiedInRepeated for $Msg$ {
fn repeated_len(f: $pb$::View<$pb$::Repeated<Self>>) -> usize {
// SAFETY: `f.as_raw()` is a valid `upb_Array*`.
unsafe { $pbr$::upb_Array_Size(f.as_raw($pbi$::Private)) }
}
unsafe fn repeated_set_unchecked(
mut f: $pb$::Mut<$pb$::Repeated<Self>>,
i: usize,
v: $pb$::View<Self>,
) {
// SAFETY:
// - `f.as_raw()` is a valid `upb_Array*`.
// - `i < len(f)` is promised by the caller.
let mut dest_msg = unsafe {
$pbr$::upb_Array_GetMutable(f.as_raw($pbi$::Private), i).msg
}.expect("upb_Array* element should not be NULL");
// SAFETY:
// - `dest_msg` is a valid `upb_Message*`.
// - `v.raw_msg()` and `dest_msg` both have message minitable `$minitable$`.
unsafe {
$pbr$::upb_Message_DeepCopy(
dest_msg,
v.raw_msg(),
$std$::ptr::addr_of!($minitable$),
f.raw_arena($pbi$::Private),
)
};
}
unsafe fn repeated_get_unchecked(
f: $pb$::View<$pb$::Repeated<Self>>,
i: usize,
) -> $pb$::View<Self> {
// SAFETY:
// - `f.as_raw()` is a valid `const upb_Array*`.
// - `i < len(f)` is promised by the caller.
let msg_ptr = unsafe { $pbr$::upb_Array_Get(f.as_raw($pbi$::Private), i).msg_val }
.expect("upb_Array* element should not be NULL.");
$pb$::View::<Self>::new($pbi$::Private, msg_ptr)
}
fn repeated_clear(mut f: $pb$::Mut<$pb$::Repeated<Self>>) {
// SAFETY:
// - `f.as_raw()` is a valid `upb_Array*`.
unsafe {
$pbr$::upb_Array_Resize(f.as_raw($pbi$::Private), 0, f.raw_arena($pbi$::Private))
};
}
fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: $pb$::View<Self>) {
// SAFETY:
// - `v.raw_msg()` is a valid `const upb_Message*` with minitable `$minitable$`.
let msg_ptr = unsafe {
$pbr$::upb_Message_DeepClone(
v.raw_msg(),
std::ptr::addr_of!($minitable$),
f.raw_arena($pbi$::Private),
)
}.expect("upb_Message_DeepClone failed.");
// Append new default message to array.
// SAFETY:
// - `f.as_raw()` is a valid `upb_Array*`.
// - `msg_ptr` is a valid `upb_Message*`.
unsafe {
$pbr$::upb_Array_Append(
f.as_raw($pbi$::Private),
$pbr$::upb_MessageValue{msg_val: Some(msg_ptr)},
f.raw_arena($pbi$::Private),
);
};
}
fn repeated_copy_from(
src: $pb$::View<$pb$::Repeated<Self>>,
mut dest: $pb$::Mut<$pb$::Repeated<Self>>,
) {
// SAFETY:
// - Elements of `src` and `dest` have message minitable `$minitable$`.
unsafe {
$pbr$::repeated_message_copy_from(src, dest, $std$::ptr::addr_of!($minitable$));
}
}
}
)rs");
return;
}
ABSL_LOG(FATAL) << "unreachable";
}
} // namespace
void GenerateRs(Context& ctx, const Descriptor& msg) {
if (msg.map_key() != nullptr) {
ABSL_LOG(WARNING) << "unsupported map field: " << msg.full_name();
return;
}
ctx.Emit(
{{"Msg", RsSafeName(msg.name())},
{"Msg::new", [&] { MessageNew(ctx, msg); }},
{"Msg::serialize", [&] { MessageSerialize(ctx, msg); }},
{"Msg::deserialize", [&] { MessageDeserialize(ctx, msg); }},
{"Msg::drop", [&] { MessageDrop(ctx, msg); }},
{"Msg_externs", [&] { MessageExterns(ctx, msg); }},
{"accessor_fns",
[&] {
for (int i = 0; i < msg.field_count(); ++i) {
GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::OWNED);
}
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
AccessorCase::OWNED);
}
}},
{"accessor_externs",
[&] {
for (int i = 0; i < msg.field_count(); ++i) {
GenerateAccessorExternC(ctx, *msg.field(i));
}
}},
{"oneof_externs",
[&] {
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofExternC(ctx, *msg.real_oneof_decl(i));
}
}},
{"nested_in_msg",
[&] {
// If we have no nested types, enums, or oneofs, bail out without
// emitting an empty mod SomeMsg_.
if (msg.nested_type_count() == 0 && msg.enum_type_count() == 0 &&
msg.real_oneof_decl_count() == 0) {
return;
}
ctx.Emit({{"Msg", RsSafeName(msg.name())},
{"nested_msgs",
[&] {
for (int i = 0; i < msg.nested_type_count(); ++i) {
GenerateRs(ctx, *msg.nested_type(i));
}
}},
{"nested_enums",
[&] {
for (int i = 0; i < msg.enum_type_count(); ++i) {
GenerateEnumDefinition(ctx, *msg.enum_type(i));
}
}},
{"oneofs",
[&] {
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofDefinition(ctx, *msg.real_oneof_decl(i));
}
}}},
R"rs(
#[allow(non_snake_case)]
pub mod $Msg$_ {
$nested_msgs$
$nested_enums$
$oneofs$
} // mod $Msg$_
)rs");
}},
{"raw_arena_getter_for_message",
[&] {
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
fn arena(&self) -> &$pbr$::Arena {
&self.inner.arena
}
)rs");
}
}},
{"raw_arena_getter_for_msgmut",
[&] {
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
fn arena(&self) -> &$pbr$::Arena {
self.inner.arena($pbi$::Private)
}
)rs");
}
}},
{"accessor_fns_for_views",
[&] {
for (int i = 0; i < msg.field_count(); ++i) {
GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::VIEW);
}
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
AccessorCase::VIEW);
}
}},
{"accessor_fns_for_muts",
[&] {
for (int i = 0; i < msg.field_count(); ++i) {
GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::MUT);
}
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
AccessorCase::MUT);
}
}},
{"settable_impl", [&] { MessageSettableValue(ctx, msg); }},
{"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }},
{"unwrap_upb",
[&] {
if (ctx.is_upb()) {
ctx.Emit(
".unwrap_or_else(||$pbr$::ScratchSpace::zeroed_block($pbi$::"
"Private))");
}
}},
{"upb_arena",
[&] {
if (ctx.is_upb()) {
ctx.Emit(", inner.msg_ref().arena($pbi$::Private).raw()");
}
}}},
R"rs(
#[allow(non_camel_case_types)]
//~ TODO: Implement support for debug redaction
#[derive(Debug)]
pub struct $Msg$ {
inner: $pbr$::MessageInner
}
// SAFETY:
// - `$Msg$` does not provide shared mutation with its arena.
// - `$Msg$Mut` is not `Send`, and so even in the presence of mutator
// splitting, synchronous access of an arena that would conflict with
// field access is impossible.
unsafe impl Sync for $Msg$ {}
impl $pb$::Proxied for $Msg$ {
type View<'msg> = $Msg$View<'msg>;
type Mut<'msg> = $Msg$Mut<'msg>;
}
#[derive(Debug, Copy, Clone)]
#[allow(dead_code)]
pub struct $Msg$View<'msg> {
msg: $pbi$::RawMessage,
_phantom: $Phantom$<&'msg ()>,
}
#[allow(dead_code)]
impl<'msg> $Msg$View<'msg> {
#[doc(hidden)]
pub fn new(_private: $pbi$::Private, msg: $pbi$::RawMessage) -> Self {
Self { msg, _phantom: std::marker::PhantomData }
}
fn raw_msg(&self) -> $pbi$::RawMessage {
self.msg
}
$accessor_fns_for_views$
}
// SAFETY:
// - `$Msg$View` does not perform any mutation.
// - While a `$Msg$View` exists, a `$Msg$Mut` can't exist to mutate
// the arena that would conflict with field access.
// - `$Msg$Mut` is not `Send`, and so even in the presence of mutator
// splitting, synchronous access of an arena is impossible.
unsafe impl Sync for $Msg$View<'_> {}
unsafe impl Send for $Msg$View<'_> {}
impl<'msg> $pb$::ViewProxy<'msg> for $Msg$View<'msg> {
type Proxied = $Msg$;
fn as_view(&self) -> $pb$::View<'msg, $Msg$> {
*self
}
fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$> where 'msg: 'shorter {
self
}
}
impl $pbi$::ProxiedWithRawVTable for $Msg$ {
type VTable = $pbr$::MessageVTable;
fn make_view(_private: $pbi$::Private,
mut_inner: $pbi$::RawVTableMutator<'_, Self>)
-> $pb$::View<'_, Self> {
let msg = unsafe {
(mut_inner.vtable().getter)(mut_inner.msg_ref().msg())
};
$Msg$View::new($pbi$::Private, msg$unwrap_upb$)
}
fn make_mut(_private: $pbi$::Private,
inner: $pbi$::RawVTableMutator<'_, Self>)
-> $pb$::Mut<'_, Self> {
let raw_submsg = unsafe {
(inner.vtable().mut_getter)(inner.msg_ref().msg()$upb_arena$)
};
$Msg$Mut::from_parent($pbi$::Private, inner.msg_ref(), raw_submsg)
}
}
impl $pbi$::ProxiedWithRawOptionalVTable for $Msg$ {
type OptionalVTable = $pbr$::MessageVTable;
fn upcast_vtable(_private: $pbi$::Private,
optional_vtable: &'static Self::OptionalVTable)
-> &'static Self::VTable {
&optional_vtable
}
}
impl $pb$::ProxiedWithPresence for $Msg$ {
type PresentMutData<'a> = $pbr$::MessagePresentMutData<'a, $Msg$>;
type AbsentMutData<'a> = $pbr$::MessageAbsentMutData<'a, $Msg$>;
fn clear_present_field(present_mutator: Self::PresentMutData<'_>)
-> Self::AbsentMutData<'_> {
// SAFETY: The raw ptr msg_ref is valid
unsafe {
(present_mutator.optional_vtable().clearer);
(present_mutator.msg_ref().msg());
$pbi$::RawVTableOptionalMutatorData::new($pbi$::Private,
present_mutator.msg_ref(),
present_mutator.optional_vtable())
}
}
fn set_absent_to_default(absent_mutator: Self::AbsentMutData<'_>)
-> Self::PresentMutData<'_> {
unsafe {
$pbi$::RawVTableOptionalMutatorData::new($pbi$::Private,
absent_mutator.msg_ref(),
absent_mutator.optional_vtable())
}
}
}
$settable_impl$
$repeated_impl$
#[derive(Debug)]
#[allow(dead_code)]
#[allow(non_camel_case_types)]
pub struct $Msg$Mut<'msg> {
inner: $pbr$::MutatorMessageRef<'msg>,
}
#[allow(dead_code)]
impl<'msg> $Msg$Mut<'msg> {
#[doc(hidden)]
pub fn from_parent(
_private: $pbi$::Private,
parent: $pbr$::MutatorMessageRef<'msg>,
msg: $pbi$::RawMessage)
-> Self {
Self {
inner: $pbr$::MutatorMessageRef::from_parent(
$pbi$::Private, parent, msg)
}
}
#[doc(hidden)]
pub fn new(_private: $pbi$::Private, msg: &'msg mut $pbr$::MessageInner) -> Self {
Self{ inner: $pbr$::MutatorMessageRef::new(_private, msg) }
}
fn raw_msg(&self) -> $pbi$::RawMessage {
self.inner.msg()
}
fn as_mutator_message_ref(&mut self) -> $pbr$::MutatorMessageRef<'msg> {
self.inner
}
$raw_arena_getter_for_msgmut$
$accessor_fns_for_muts$
}
// SAFETY:
// - `$Msg$Mut` does not perform any shared mutation.
// - `$Msg$Mut` is not `Send`, and so even in the presence of mutator
// splitting, synchronous access of an arena is impossible.
unsafe impl Sync for $Msg$Mut<'_> {}
impl<'msg> $pb$::MutProxy<'msg> for $Msg$Mut<'msg> {
fn as_mut(&mut self) -> $pb$::Mut<'_, $Msg$> {
$Msg$Mut { inner: self.inner }
}
fn into_mut<'shorter>(self) -> $pb$::Mut<'shorter, $Msg$> where 'msg : 'shorter { self }
}
impl<'msg> $pb$::ViewProxy<'msg> for $Msg$Mut<'msg> {
type Proxied = $Msg$;
fn as_view(&self) -> $pb$::View<'_, $Msg$> {
$Msg$View { msg: self.raw_msg(), _phantom: std::marker::PhantomData }
}
fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$> where 'msg: 'shorter {
$Msg$View { msg: self.raw_msg(), _phantom: std::marker::PhantomData }
}
}
#[allow(dead_code)]
impl $Msg$ {
pub fn new() -> Self {
$Msg::new$
}
fn raw_msg(&self) -> $pbi$::RawMessage {
self.inner.msg
}
fn as_mutator_message_ref(&mut self) -> $pbr$::MutatorMessageRef {
$pbr$::MutatorMessageRef::new($pbi$::Private, &mut self.inner)
}
$raw_arena_getter_for_message$
pub fn serialize(&self) -> $pbr$::SerializedData {
$Msg::serialize$
}
pub fn deserialize(&mut self, data: &[u8]) -> Result<(), $pb$::ParseError> {
$Msg::deserialize$
}
pub fn as_view(&self) -> $Msg$View {
$Msg$View::new($pbi$::Private, self.inner.msg)
}
pub fn as_mut(&mut self) -> $Msg$Mut {
$Msg$Mut::new($pbi$::Private, &mut self.inner)
}
$accessor_fns$
} // impl $Msg$
//~ We implement drop unconditionally, so that `$Msg$: Drop` regardless
//~ of kernel.
impl $std$::ops::Drop for $Msg$ {
fn drop(&mut self) {
$Msg::drop$
}
}
extern "C" {
$Msg_externs$
$accessor_externs$
$oneof_externs$
} // extern "C" for $Msg$
$nested_in_msg$
)rs");
if (ctx.is_cpp()) {
ctx.printer().PrintRaw("\n");
ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs(
impl $Msg$ {
pub fn __unstable_wrap_cpp_grant_permission_to_break(msg: $pbi$::RawMessage) -> Self {
Self { inner: $pbr$::MessageInner { msg } }
}
pub fn __unstable_cpp_repr_grant_permission_to_break(&mut self) -> $pbi$::RawMessage {
self.raw_msg()
}
}
)rs");
}
}
// Generates code for a particular message in `.pb.thunk.cc`.
void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
ABSL_CHECK(ctx.is_cpp());
if (msg.map_key() != nullptr) {
ABSL_LOG(WARNING) << "unsupported map field: " << msg.full_name();
return;
}
ctx.Emit(
{{"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode.
{"Msg", RsSafeName(msg.name())},
{"QualifiedMsg", cpp::QualifiedClassName(&msg)},
{"new_thunk", ThunkName(ctx, msg, "new")},
{"delete_thunk", ThunkName(ctx, msg, "delete")},
{"serialize_thunk", ThunkName(ctx, msg, "serialize")},
{"deserialize_thunk", ThunkName(ctx, msg, "deserialize")},
{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")},
{"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
{"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
{"repeated_get_mut_thunk", ThunkName(ctx, msg, "repeated_get_mut")},
{"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
{"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
{"repeated_copy_from_thunk", ThunkName(ctx, msg, "repeated_copy_from")},
{"nested_msg_thunks",
[&] {
for (int i = 0; i < msg.nested_type_count(); ++i) {
GenerateThunksCc(ctx, *msg.nested_type(i));
}
}},
{"accessor_thunks",
[&] {
for (int i = 0; i < msg.field_count(); ++i) {
GenerateAccessorThunkCc(ctx, *msg.field(i));
}
}},
{"oneof_thunks",
[&] {
for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
GenerateOneofThunkCc(ctx, *msg.real_oneof_decl(i));
}
}}},
R"cc(
//~ $abi$ is a workaround for a syntax highlight bug in VSCode. However,
//~ that confuses clang-format (it refuses to keep the newline after
//~ `$abi${`). Disabling clang-format for the block.
// clang-format off
extern $abi$ {
void* $new_thunk$() { return new $QualifiedMsg$(); }
void $delete_thunk$(void* ptr) { delete static_cast<$QualifiedMsg$*>(ptr); }
google::protobuf::rust_internal::SerializedData $serialize_thunk$($QualifiedMsg$* msg) {
return google::protobuf::rust_internal::SerializeMsg(msg);
}
bool $deserialize_thunk$($QualifiedMsg$* msg,
google::protobuf::rust_internal::SerializedData data) {
return msg->ParseFromArray(data.data, data.len);
}
void $copy_from_thunk$($QualifiedMsg$* dst, const $QualifiedMsg$* src) {
dst->CopyFrom(*src);
}
size_t $repeated_len_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
return field->size();
}
const $QualifiedMsg$& $repeated_get_thunk$(
google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field,
size_t index) {
return field->Get(index);
}
$QualifiedMsg$* $repeated_get_mut_thunk$(
google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field,
size_t index) {
return field->Mutable(index);
}
$QualifiedMsg$* $repeated_add_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
return field->Add();
}
void $repeated_clear_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
field->Clear();
}
void $repeated_copy_from_thunk$(
google::protobuf::RepeatedPtrField<$QualifiedMsg$>& dst,
const google::protobuf::RepeatedPtrField<$QualifiedMsg$>& src) {
dst = src;
}
$accessor_thunks$
$oneof_thunks$
} // extern $abi$
// clang-format on
$nested_msg_thunks$
)cc");
}
} // namespace rust
} // namespace compiler
} // namespace protobuf
} // namespace google