Create a upb rust directory.

The intent of this directory would be for a layer of Rust bindings that directly map to upb semantics; Rust Protobuf runtime would be layer on top of that Rust, instead of directly on the upb C api.

PiperOrigin-RevId: 624282429
pull/16478/head
Protobuf Team Bot 8 months ago committed by Copybara-Service
parent 8d025c08ff
commit 2678e10c99
  1. 2
      rust/BUILD
  2. 109
      rust/cpp.rs
  3. 127
      rust/internal.rs
  4. 4
      rust/map.rs
  5. 4
      rust/repeated.rs
  6. 6
      rust/string.rs
  7. 2
      rust/test/cpp/interop/main.rs
  8. 263
      rust/upb.rs
  9. 36
      rust/upb/BUILD
  10. 7
      rust/upb/README.md
  11. 333
      rust/upb/shared.rs
  12. 2
      rust/upb/upb_api.c
  13. 15
      rust/upb_kernel/BUILD
  14. 5
      rust/vtable.rs
  15. 12
      src/google/protobuf/compiler/rust/accessors/map.cc
  16. 16
      src/google/protobuf/compiler/rust/accessors/repeated_field.cc
  17. 20
      src/google/protobuf/compiler/rust/accessors/singular_message.cc
  18. 8
      src/google/protobuf/compiler/rust/accessors/singular_scalar.cc
  19. 8
      src/google/protobuf/compiler/rust/accessors/singular_string.cc
  20. 18
      src/google/protobuf/compiler/rust/enum.cc
  21. 74
      src/google/protobuf/compiler/rust/message.cc
  22. 2
      src/google/protobuf/compiler/rust/naming.cc
  23. 2
      src/google/protobuf/compiler/rust/oneof.cc

@ -78,7 +78,7 @@ rust_library(
],
deps = [
":utf8",
"//rust/upb_kernel:upb_c_api",
"//rust/upb",
],
)

@ -7,15 +7,13 @@
// Rust Protobuf runtime using the C++ kernel.
use crate::__internal::{Enum, Private, PtrAndLen, RawMap, RawMessage, RawRepeatedField};
use crate::__internal::{Enum, Private};
use crate::{
Map, MapIter, Mut, ProtoStr, Proxied, ProxiedInMapValue, ProxiedInRepeated, Repeated,
RepeatedMut, RepeatedView, SettableValue, View,
};
use core::fmt::Debug;
use paste::paste;
use std::alloc::Layout;
use std::cell::UnsafeCell;
use std::convert::identity;
use std::ffi::{c_int, c_void};
use std::fmt;
@ -23,6 +21,111 @@ use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::ptr::{self, NonNull};
use std::slice;
/// Defines a set of opaque, unique, non-accessible pointees.
///
/// The [Rustonomicon][nomicon] currently recommends a zero-sized struct,
/// though this should use [`extern type`] when that is stabilized.
/// [nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
/// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
mod _opaque_pointees {
/// Opaque pointee for [`RawMessage`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
///
/// [`RawMessage`]: super::RawMessage
#[repr(C)]
pub struct RawMessageData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
/// Opaque pointee for [`RawRepeatedField`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
#[repr(C)]
pub struct RawRepeatedFieldData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
/// Opaque pointee for [`RawMap`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
#[repr(C)]
pub struct RawMapData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
}
/// A raw pointer to the underlying message for this runtime.
pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>;
/// A raw pointer to the underlying repeated field container for this runtime.
pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>;
/// A raw pointer to the underlying arena for this runtime.
pub type RawMap = NonNull<_opaque_pointees::RawMapData>;
/// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a
/// borrowed slice of bytes) for FFI use only.
///
/// Has semantics similar to `std::string_view` in C++ and `&[u8]` in Rust,
/// but is not ABI-compatible with either.
///
/// If `len` is 0, then `ptr` can be null or dangling. C++ considers a dangling
/// 0-len `std::string_view` to be invalid, and Rust considers a `&[u8]` with a
/// null data pointer to be invalid.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PtrAndLen {
/// Pointer to the first byte.
/// Borrows the memory.
pub ptr: *const u8,
/// Length of the `[u8]` pointed to by `ptr`.
pub len: usize,
}
impl PtrAndLen {
/// Unsafely dereference this slice.
///
/// # Safety
/// - `self.ptr` must be dereferencable and immutable for `self.len` bytes
/// for the lifetime `'a`. It can be null or dangling if `self.len == 0`.
pub unsafe fn as_ref<'a>(self) -> &'a [u8] {
if self.ptr.is_null() {
assert_eq!(self.len, 0, "Non-empty slice with null data pointer");
&[]
} else {
// SAFETY:
// - `ptr` is non-null
// - `ptr` is valid for `len` bytes as promised by the caller.
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
}
impl From<&[u8]> for PtrAndLen {
fn from(slice: &[u8]) -> Self {
Self { ptr: slice.as_ptr(), len: slice.len() }
}
}
impl From<&ProtoStr> for PtrAndLen {
fn from(s: &ProtoStr) -> Self {
let bytes = s.as_bytes();
Self { ptr: bytes.as_ptr(), len: bytes.len() }
}
}
/// Serialized Protobuf wire format data. It's typically produced by
/// `<Message>.serialize()`.

@ -16,128 +16,11 @@ pub use crate::vtable::{
RawVTableMutator, RawVTableOptionalMutatorData,
};
pub use crate::ProtoStr;
use std::ptr::NonNull;
use std::slice;
// TODO: Temporarily re-export these symbols which are now under
// __runtime under __internal since some external callers using it through
// __internal.
pub use crate::__runtime::{PtrAndLen, RawMap, RawMessage, RawRepeatedField};
/// Used to protect internal-only items from being used accidentally.
pub struct Private;
/// Defines a set of opaque, unique, non-accessible pointees.
///
/// The [Rustonomicon][nomicon] currently recommends a zero-sized struct,
/// though this should use [`extern type`] when that is stabilized.
/// [nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
/// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
mod _opaque_pointees {
/// Opaque pointee for [`RawMessage`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
///
/// [`RawMessage`]: super::RawMessage
#[repr(C)]
pub struct RawMessageData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
/// Opaque pointee for [`RawArena`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
///
/// [`RawArena`]: super::RawArena
#[repr(C)]
pub struct RawArenaData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
/// Opaque pointee for [`RawRepeatedField`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
#[repr(C)]
pub struct RawRepeatedFieldData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
/// Opaque pointee for [`RawMap`]
///
/// This type is not meant to be dereferenced in Rust code.
/// It is only meant to provide type safety for raw pointers
/// which are manipulated behind FFI.
#[repr(C)]
pub struct RawMapData {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
}
/// A raw pointer to the underlying message for this runtime.
pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>;
/// A raw pointer to the underlying arena for this runtime.
pub type RawArena = NonNull<_opaque_pointees::RawArenaData>;
/// A raw pointer to the underlying repeated field container for this runtime.
pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>;
/// A raw pointer to the underlying arena for this runtime.
pub type RawMap = NonNull<_opaque_pointees::RawMapData>;
/// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a
/// borrowed slice of bytes) for FFI use only.
///
/// Has semantics similar to `std::string_view` in C++ and `&[u8]` in Rust,
/// but is not ABI-compatible with either.
///
/// If `len` is 0, then `ptr` can be null or dangling. C++ considers a dangling
/// 0-len `std::string_view` to be invalid, and Rust considers a `&[u8]` with a
/// null data pointer to be invalid.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PtrAndLen {
/// Pointer to the first byte.
/// Borrows the memory.
pub ptr: *const u8,
/// Length of the `[u8]` pointed to by `ptr`.
pub len: usize,
}
impl PtrAndLen {
/// Unsafely dereference this slice.
///
/// # Safety
/// - `self.ptr` must be dereferencable and immutable for `self.len` bytes
/// for the lifetime `'a`. It can be null or dangling if `self.len == 0`.
pub unsafe fn as_ref<'a>(self) -> &'a [u8] {
if self.ptr.is_null() {
assert_eq!(self.len, 0, "Non-empty slice with null data pointer");
&[]
} else {
// SAFETY:
// - `ptr` is non-null
// - `ptr` is valid for `len` bytes as promised by the caller.
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
}
impl From<&[u8]> for PtrAndLen {
fn from(slice: &[u8]) -> Self {
Self { ptr: slice.as_ptr(), len: slice.len() }
}
}
impl From<&ProtoStr> for PtrAndLen {
fn from(s: &ProtoStr) -> Self {
let bytes = s.as_bytes();
Self { ptr: bytes.as_ptr(), len: bytes.len() }
}
}

@ -7,8 +7,8 @@
use crate::{
Mut, MutProxy, Proxied, SettableValue, View, ViewProxy,
__internal::{Private, RawMap},
__runtime::{InnerMap, InnerMapMut, RawMapIter},
__internal::Private,
__runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter},
};
use std::marker::PhantomData;

@ -16,8 +16,8 @@ use std::marker::PhantomData;
use crate::{
Mut, MutProxy, Proxied, SettableValue, View, ViewProxy,
__internal::{Private, RawRepeatedField},
__runtime::{InnerRepeated, InnerRepeatedMut},
__internal::Private,
__runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField},
};
/// Views the elements in a `repeated` field of `T`.

@ -9,8 +9,10 @@
#![allow(dead_code)]
#![allow(unused)]
use crate::__internal::{Private, PtrAndLen, RawMessage};
use crate::__runtime::{BytesAbsentMutData, BytesPresentMutData, InnerBytesMut};
use crate::__internal::Private;
use crate::__runtime::{
BytesAbsentMutData, BytesPresentMutData, InnerBytesMut, PtrAndLen, RawMessage,
};
use crate::macros::impl_forwarding_settable_value;
use crate::{
AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, Proxied, ProxiedWithPresence,

@ -6,7 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd
use googletest::prelude::*;
use protobuf_cpp::__internal::{PtrAndLen, RawMessage};
use protobuf_cpp::__runtime::{PtrAndLen, RawMessage};
use unittest_proto::{TestAllExtensions, TestAllTypes, TestAllTypesMut, TestAllTypesView};
macro_rules! proto_assert_eq {

@ -7,7 +7,7 @@
//! UPB FFI wrapper code for use by Rust Protobuf.
use crate::__internal::{Enum, Private, PtrAndLen, RawArena, RawMap, RawMessage, RawRepeatedField};
use crate::__internal::{Enum, Private};
use crate::{
Map, MapIter, MapMut, MapView, Mut, ProtoStr, Proxied, ProxiedInMapValue, ProxiedInRepeated,
Repeated, RepeatedMut, RepeatedView, SettableValue, View, ViewProxy,
@ -16,7 +16,6 @@ use core::fmt::Debug;
use std::alloc;
use std::alloc::Layout;
use std::cell::UnsafeCell;
use std::ffi::c_int;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{align_of, size_of, ManuallyDrop, MaybeUninit};
@ -25,6 +24,25 @@ use std::ptr::{self, NonNull};
use std::slice;
use std::sync::OnceLock;
extern crate upb;
// Temporarily 'pub' since a lot of gencode is directly calling any of the ffi
// fns.
pub use upb::*;
pub type RawArena = upb::RawArena;
pub type RawMessage = upb::RawMessage;
pub type RawRepeatedField = upb::RawArray;
pub type RawMap = upb::RawMap;
pub type PtrAndLen = upb::StringView;
impl From<&ProtoStr> for PtrAndLen {
fn from(s: &ProtoStr) -> Self {
let bytes = s.as_bytes();
Self { ptr: bytes.as_ptr(), len: bytes.len() }
}
}
/// See `upb/port/def.inc`.
const UPB_MALLOC_ALIGN: usize = 8;
const _CHECK_UPB_MALLOC_ALIGN_AT_LEAST_POINTER_ALIGNED: () =
@ -46,14 +64,6 @@ pub struct Arena {
_not_sync: PhantomData<UnsafeCell<()>>,
}
extern "C" {
// `Option<NonNull<T: Sized>>` is ABI-compatible with `*mut T`
pub fn upb_Arena_New() -> Option<RawArena>;
pub fn upb_Arena_Free(arena: RawArena);
pub fn upb_Arena_Malloc(arena: RawArena, size: usize) -> *mut u8;
pub fn upb_Arena_Realloc(arena: RawArena, ptr: *mut u8, old: usize, new: usize) -> *mut u8;
}
impl Arena {
/// Allocates a fresh arena.
#[inline]
@ -332,89 +342,6 @@ fn copy_bytes_in_arena<'msg>(arena: &'msg Arena, val: &'msg [u8]) -> &'msg [u8]
}
}
// A macro for opaque pointees.
// This wrapper is a workaround until stabilization of [`extern type`].
// TODO: convert to extern type once stabilized.
// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
macro_rules! opaque_pointee {
($name:ident) => {
#[repr(C)]
pub struct $name {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
}
};
}
// Opaque pointee for upb_MiniTable.
// TODO: consider importing a minitable struct declared in
// google3/third_party/upb/bits.
opaque_pointee!(OpaqueMiniTable);
// Opaque pointee for upb_ExtensionRegistry
opaque_pointee!(OpaqueExtensionRegistry);
extern "C" {
pub fn upb_Message_DeepCopy(
dst: RawMessage,
src: RawMessage,
mini_table: *const OpaqueMiniTable,
arena: RawArena,
);
pub fn upb_Message_DeepClone(
m: RawMessage,
mini_table: *const OpaqueMiniTable,
arena: RawArena,
) -> Option<RawMessage>;
}
// LINT.IfChange(encode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum EncodeStatus {
Ok = 0,
OutOfMemory = 1,
MaxDepthExceeded = 2,
MissingRequired = 3,
}
// LINT.ThenChange()
// LINT.IfChange(decode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum DecodeStatus {
Ok = 0,
Malformed = 1,
OutOfMemory = 2,
BadUtf8 = 3,
MaxDepthExceeded = 4,
MissingRequired = 5,
UnlinkedSubMessage = 6,
}
// LINT.ThenChange()
extern "C" {
pub fn upb_Encode(
msg: RawMessage,
mini_table: *const OpaqueMiniTable,
options: i32,
arena: RawArena,
buf: *mut *mut u8,
buf_size: *mut usize,
) -> EncodeStatus;
pub fn upb_Decode(
buf: *const u8,
buf_size: usize,
msg: RawMessage,
mini_table: *const OpaqueMiniTable,
extreg: *const OpaqueExtensionRegistry,
options: i32,
arena: RawArena,
) -> DecodeStatus;
}
/// The raw type-erased version of an owned `Repeated`.
#[derive(Debug)]
pub struct InnerRepeated {
@ -442,70 +369,13 @@ impl<'msg> InnerRepeatedMut<'msg> {
}
}
// Transcribed from google3/third_party/upb/upb/message/value.h
#[repr(C)]
#[derive(Clone, Copy)]
pub union upb_MessageValue {
pub bool_val: bool,
pub float_val: std::ffi::c_float,
pub double_val: std::ffi::c_double,
pub uint32_val: u32,
pub int32_val: i32,
pub uint64_val: u64,
pub int64_val: i64,
pub array_val: Option<RawRepeatedField>,
pub map_val: Option<RawMap>,
// TODO: Replace this `RawMessage` with the const type.
pub msg_val: Option<RawMessage>,
pub str_val: PtrAndLen,
tagged_msg_val: *const std::ffi::c_void,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union upb_MutableMessageValue {
pub array: Option<RawRepeatedField>,
pub map: Option<RawMap>,
pub msg: Option<RawMessage>,
}
// Transcribed from google3/third_party/upb/upb/base/descriptor_constants.h
#[repr(C)]
#[allow(dead_code)]
pub enum UpbCType {
Bool = 1,
Float = 2,
Int32 = 3,
UInt32 = 4,
Enum = 5,
Message = 6,
Double = 7,
Int64 = 8,
UInt64 = 9,
String = 10,
Bytes = 11,
}
extern "C" {
fn upb_Array_New(a: RawArena, r#type: std::ffi::c_int) -> RawRepeatedField;
pub fn upb_Array_Size(arr: RawRepeatedField) -> usize;
pub fn upb_Array_Set(arr: RawRepeatedField, i: usize, val: upb_MessageValue);
pub fn upb_Array_Get(arr: RawRepeatedField, i: usize) -> upb_MessageValue;
pub fn upb_Array_Append(arr: RawRepeatedField, val: upb_MessageValue, arena: RawArena);
pub fn upb_Array_Resize(arr: RawRepeatedField, size: usize, arena: RawArena) -> bool;
fn upb_Array_MutableDataPtr(arr: RawRepeatedField) -> *mut std::ffi::c_void;
fn upb_Array_DataPtr(arr: RawRepeatedField) -> *const std::ffi::c_void;
pub fn upb_Array_GetMutable(arr: RawRepeatedField, i: usize) -> upb_MutableMessageValue;
}
macro_rules! impl_repeated_base {
($t:ty, $elem_t:ty, $ufield:ident, $upb_tag:expr) => {
#[allow(dead_code)]
fn repeated_new(_: Private) -> Repeated<$t> {
let arena = Arena::new();
Repeated::from_inner(InnerRepeated {
raw: unsafe { upb_Array_New(arena.raw(), $upb_tag as c_int) },
raw: unsafe { upb_Array_New(arena.raw(), $upb_tag) },
arena,
})
}
@ -519,11 +389,11 @@ macro_rules! impl_repeated_base {
fn repeated_push(mut f: Mut<Repeated<$t>>, v: View<$t>) {
let arena = f.raw_arena(Private);
unsafe {
upb_Array_Append(
assert!(upb_Array_Append(
f.as_raw(Private),
<$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, v),
arena,
)
));
}
}
fn repeated_clear(mut f: Mut<Repeated<$t>>) {
@ -624,17 +494,17 @@ impl<'msg, T: ?Sized> RepeatedMut<'msg, T> {
}
impl_repeated_primitives!(
// proxied type, element type, upb_MessageValue field name, UpbCType variant
(bool, bool, bool_val, UpbCType::Bool),
(f32, f32, float_val, UpbCType::Float),
(f64, f64, double_val, UpbCType::Double),
(i32, i32, int32_val, UpbCType::Int32),
(u32, u32, uint32_val, UpbCType::UInt32),
(i64, i64, int64_val, UpbCType::Int64),
(u64, u64, uint64_val, UpbCType::UInt64),
// proxied type, element type, upb_MessageValue field name, upb::CType variant
(bool, bool, bool_val, upb::CType::Bool),
(f32, f32, float_val, upb::CType::Float),
(f64, f64, double_val, upb::CType::Double),
(i32, i32, int32_val, upb::CType::Int32),
(u32, u32, uint32_val, upb::CType::UInt32),
(i64, i64, int64_val, upb::CType::Int64),
(u64, u64, uint64_val, upb::CType::UInt64),
);
impl_repeated_bytes!((ProtoStr, UpbCType::String), ([u8], UpbCType::Bytes),);
impl_repeated_bytes!((ProtoStr, upb::CType::String), ([u8], upb::CType::Bytes),);
/// Copy the contents of `src` into `dest`.
///
@ -643,7 +513,7 @@ impl_repeated_bytes!((ProtoStr, UpbCType::String), ([u8], UpbCType::Bytes),);
pub unsafe fn repeated_message_copy_from<T: ProxiedInRepeated>(
src: View<Repeated<T>>,
mut dest: Mut<Repeated<T>>,
minitable: *const OpaqueMiniTable,
minitable: *const upb_MiniTable,
) {
// SAFETY:
// - `src.as_raw()` is a valid `const upb_Array*`.
@ -801,7 +671,7 @@ impl<'msg> InnerMapMut<'msg> {
}
pub trait UpbTypeConversions: Proxied {
fn upb_type() -> UpbCType;
fn upb_type() -> upb::CType;
fn to_message_value(val: View<'_, Self>) -> upb_MessageValue;
/// # Safety
@ -822,7 +692,7 @@ macro_rules! impl_upb_type_conversions_for_scalars {
$(
impl UpbTypeConversions for $t {
#[inline(always)]
fn upb_type() -> UpbCType {
fn upb_type() -> upb::CType {
$upb_tag
}
@ -846,18 +716,18 @@ macro_rules! impl_upb_type_conversions_for_scalars {
}
impl_upb_type_conversions_for_scalars!(
f32, float_val, UpbCType::Float, 0f32;
f64, double_val, UpbCType::Double, 0f64;
i32, int32_val, UpbCType::Int32, 0i32;
u32, uint32_val, UpbCType::UInt32, 0u32;
i64, int64_val, UpbCType::Int64, 0i64;
u64, uint64_val, UpbCType::UInt64, 0u64;
bool, bool_val, UpbCType::Bool, false;
f32, float_val, upb::CType::Float, 0f32;
f64, double_val, upb::CType::Double, 0f64;
i32, int32_val, upb::CType::Int32, 0i32;
u32, uint32_val, upb::CType::UInt32, 0u32;
i64, int64_val, upb::CType::Int64, 0i64;
u64, uint64_val, upb::CType::UInt64, 0u64;
bool, bool_val, upb::CType::Bool, false;
);
impl UpbTypeConversions for [u8] {
fn upb_type() -> UpbCType {
UpbCType::Bytes
fn upb_type() -> upb::CType {
upb::CType::Bytes
}
fn to_message_value(val: View<'_, [u8]>) -> upb_MessageValue {
@ -881,8 +751,8 @@ impl UpbTypeConversions for [u8] {
}
impl UpbTypeConversions for ProtoStr {
fn upb_type() -> UpbCType {
UpbCType::String
fn upb_type() -> upb::CType {
upb::CType::String
}
fn to_message_value(val: View<'_, ProtoStr>) -> upb_MessageValue {
@ -1033,14 +903,6 @@ macro_rules! impl_ProxiedInMapValue_for_key_types {
impl_ProxiedInMapValue_for_key_types!(i32, u32, i64, u64, bool, ProtoStr);
#[repr(C)]
#[allow(dead_code)]
pub enum upb_MapInsertStatus {
Inserted = 0,
Replaced = 1,
OutOfMemory = 2,
}
/// `upb_Map_Insert`, but returns a `bool` for whether insert occurred.
///
/// Returns `true` if the entry was newly inserted.
@ -1061,39 +923,12 @@ pub unsafe fn upb_Map_InsertAndReturnIfInserted(
arena: RawArena,
) -> bool {
match unsafe { upb_Map_Insert(map, key, value, arena) } {
upb_MapInsertStatus::Inserted => true,
upb_MapInsertStatus::Replaced => false,
upb_MapInsertStatus::OutOfMemory => panic!("map arena is out of memory"),
upb::MapInsertStatus::Inserted => true,
upb::MapInsertStatus::Replaced => false,
upb::MapInsertStatus::OutOfMemory => panic!("map arena is out of memory"),
}
}
extern "C" {
pub fn upb_Map_New(arena: RawArena, key_type: UpbCType, value_type: UpbCType) -> RawMap;
pub fn upb_Map_Size(map: RawMap) -> usize;
pub fn upb_Map_Insert(
map: RawMap,
key: upb_MessageValue,
value: upb_MessageValue,
arena: RawArena,
) -> upb_MapInsertStatus;
pub fn upb_Map_Get(map: RawMap, key: upb_MessageValue, value: *mut upb_MessageValue) -> bool;
pub fn upb_Map_Delete(
map: RawMap,
key: upb_MessageValue,
removed_value: *mut upb_MessageValue,
) -> bool;
pub fn upb_Map_Clear(map: RawMap);
static __rust_proto_kUpb_Map_Begin: usize;
pub fn upb_Map_Next(
map: RawMap,
key: *mut upb_MessageValue,
value: *mut upb_MessageValue,
iter: &mut usize,
) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;

@ -0,0 +1,36 @@
# Copyright 2024 Google LLC
#
# 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
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
# begin:google_only
# package(default_applicable_licenses = ["//upb:license"])
# end:google_only
rust_library(
name = "upb",
srcs = ["shared.rs"],
visibility = [
"//rust:__subpackages__",
"//src/google/protobuf:__subpackages__",
],
deps = [":upb_c_api"],
)
rust_test(
name = "upb_rs_crate_test",
crate = ":upb",
)
cc_library(
name = "upb_c_api",
srcs = ["upb_api.c"],
deps = [
"//upb:mem",
"//upb:message",
"//upb:message_copy",
],
)

@ -0,0 +1,7 @@
# Rust upb bindings
This directory contains Rust bindings for upb, attempting to be the a direct
mapping to expose upb to Rust. This should not be used directly by application
code, instead is an implementation detail for Rust Protobuf, which is still
under development but can be found here:
[here](https://github.com/protocolbuffers/protobuf/tree/main/rust).

@ -0,0 +1,333 @@
use std::ptr::NonNull;
use std::slice;
// Macro to create structs that will act as opaque pointees. These structs are
// never intended to be dereferenced in Rust.
// This is a workaround until stabilization of [`extern type`].
// TODO: convert to extern type once stabilized.
// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
macro_rules! opaque_pointee {
($name: ident) => {
#[repr(C)]
pub struct $name {
_data: [u8; 0],
_marker: std::marker::PhantomData<(*mut u8, std::marker::PhantomPinned)>,
}
};
}
opaque_pointee!(upb_Arena);
pub type RawArena = NonNull<upb_Arena>;
opaque_pointee!(upb_Message);
pub type RawMessage = NonNull<upb_Message>;
opaque_pointee!(upb_MiniTable);
pub type RawMiniTable = NonNull<upb_MiniTable>;
opaque_pointee!(upb_ExtensionRegistry);
pub type RawExtensionRegistry = NonNull<upb_ExtensionRegistry>;
opaque_pointee!(upb_Map);
pub type RawMap = NonNull<upb_Map>;
opaque_pointee!(upb_Array);
pub type RawArray = NonNull<upb_Array>;
extern "C" {
// `Option<NonNull<T: Sized>>` is ABI-compatible with `*mut T`
pub fn upb_Arena_New() -> Option<RawArena>;
pub fn upb_Arena_Free(arena: RawArena);
pub fn upb_Arena_Malloc(arena: RawArena, size: usize) -> *mut u8;
pub fn upb_Arena_Realloc(arena: RawArena, ptr: *mut u8, old: usize, new: usize) -> *mut u8;
}
extern "C" {
pub fn upb_Message_DeepCopy(
dst: RawMessage,
src: RawMessage,
mini_table: *const upb_MiniTable,
arena: RawArena,
);
pub fn upb_Message_DeepClone(
m: RawMessage,
mini_table: *const upb_MiniTable,
arena: RawArena,
) -> Option<RawMessage>;
}
// LINT.IfChange(encode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum EncodeStatus {
Ok = 0,
OutOfMemory = 1,
MaxDepthExceeded = 2,
MissingRequired = 3,
}
// LINT.ThenChange()
// LINT.IfChange(decode_status)
#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone)]
pub enum DecodeStatus {
Ok = 0,
Malformed = 1,
OutOfMemory = 2,
BadUtf8 = 3,
MaxDepthExceeded = 4,
MissingRequired = 5,
UnlinkedSubMessage = 6,
}
// LINT.ThenChange()
extern "C" {
pub fn upb_Encode(
msg: RawMessage,
mini_table: *const upb_MiniTable,
options: i32,
arena: RawArena,
buf: *mut *mut u8,
buf_size: *mut usize,
) -> EncodeStatus;
pub fn upb_Decode(
buf: *const u8,
buf_size: usize,
msg: RawMessage,
mini_table: *const upb_MiniTable,
extreg: *const upb_ExtensionRegistry,
options: i32,
arena: RawArena,
) -> DecodeStatus;
}
/// ABI compatible struct with upb_StringView.
///
/// Note that this has semantics similar to `std::string_view` in C++ and
/// `&[u8]` in Rust, but is not ABI-compatible with either.
///
/// If `len` is 0, then `ptr` is allowed to be either null or dangling. C++
/// considers a dangling 0-len `std::string_view` to be invalid, and Rust
/// considers a `&[u8]` with a null data pointer to be invalid.
#[repr(C)]
#[derive(Copy, Clone)]
pub struct StringView {
/// Pointer to the first byte.
/// Borrows the memory.
pub ptr: *const u8,
/// Length of the `[u8]` pointed to by `ptr`.
pub len: usize,
}
impl StringView {
/// Unsafely dereference this slice.
///
/// # Safety
/// - `self.ptr` must be dereferencable and immutable for `self.len` bytes
/// for the lifetime `'a`. It can be null or dangling if `self.len == 0`.
pub unsafe fn as_ref<'a>(self) -> &'a [u8] {
if self.ptr.is_null() {
assert_eq!(self.len, 0, "Non-empty slice with null data pointer");
&[]
} else {
// SAFETY:
// - `ptr` is non-null
// - `ptr` is valid for `len` bytes as promised by the caller.
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
}
impl From<&[u8]> for StringView {
fn from(slice: &[u8]) -> Self {
Self { ptr: slice.as_ptr(), len: slice.len() }
}
}
// Transcribed from google3/third_party/upb/upb/message/value.h
#[repr(C)]
#[derive(Clone, Copy)]
pub union upb_MessageValue {
pub bool_val: bool,
pub float_val: std::ffi::c_float,
pub double_val: std::ffi::c_double,
pub uint32_val: u32,
pub int32_val: i32,
pub uint64_val: u64,
pub int64_val: i64,
// TODO: Replace this `RawMessage` with the const type.
pub array_val: Option<RawArray>,
pub map_val: Option<RawMap>,
pub msg_val: Option<RawMessage>,
pub str_val: StringView,
tagged_msg_val: *const std::ffi::c_void,
}
impl upb_MessageValue {
pub fn zeroed() -> Self {
// SAFETY: zero bytes is a valid representation for at least one value in the
// union (actually valid for all of them).
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union upb_MutableMessageValue {
pub array: Option<RawArray>,
pub map: Option<RawMap>,
pub msg: Option<RawMessage>,
}
// Transcribed from google3/third_party/upb/upb/base/descriptor_constants.h
#[repr(C)]
#[allow(dead_code)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum CType {
Bool = 1,
Float = 2,
Int32 = 3,
UInt32 = 4,
Enum = 5,
Message = 6,
Double = 7,
Int64 = 8,
UInt64 = 9,
String = 10,
Bytes = 11,
}
extern "C" {
pub fn upb_Array_New(a: RawArena, r#type: CType) -> RawArray;
pub fn upb_Array_Size(arr: RawArray) -> usize;
pub fn upb_Array_Set(arr: RawArray, i: usize, val: upb_MessageValue);
pub fn upb_Array_Get(arr: RawArray, i: usize) -> upb_MessageValue;
pub fn upb_Array_Append(arr: RawArray, val: upb_MessageValue, arena: RawArena) -> bool;
pub fn upb_Array_Resize(arr: RawArray, size: usize, arena: RawArena) -> bool;
pub fn upb_Array_MutableDataPtr(arr: RawArray) -> *mut std::ffi::c_void;
pub fn upb_Array_DataPtr(arr: RawArray) -> *const std::ffi::c_void;
pub fn upb_Array_GetMutable(arr: RawArray, i: usize) -> upb_MutableMessageValue;
}
#[repr(C)]
#[allow(dead_code)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum MapInsertStatus {
Inserted = 0,
Replaced = 1,
OutOfMemory = 2,
}
extern "C" {
pub fn upb_Map_New(arena: RawArena, key_type: CType, value_type: CType) -> RawMap;
pub fn upb_Map_Size(map: RawMap) -> usize;
pub fn upb_Map_Insert(
map: RawMap,
key: upb_MessageValue,
value: upb_MessageValue,
arena: RawArena,
) -> MapInsertStatus;
pub fn upb_Map_Get(map: RawMap, key: upb_MessageValue, value: *mut upb_MessageValue) -> bool;
pub fn upb_Map_Delete(
map: RawMap,
key: upb_MessageValue,
removed_value: *mut upb_MessageValue,
) -> bool;
pub fn upb_Map_Clear(map: RawMap);
pub static __rust_proto_kUpb_Map_Begin: usize;
pub fn upb_Map_Next(
map: RawMap,
key: *mut upb_MessageValue,
value: *mut upb_MessageValue,
iter: &mut usize,
) -> bool;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arena_ffi_test() {
// SAFETY: FFI unit test uses C API under expected patterns.
unsafe {
let arena = upb_Arena_New().unwrap();
let bytes = upb_Arena_Malloc(arena, 3);
let bytes = upb_Arena_Realloc(arena, bytes, 3, 512);
*bytes.add(511) = 7;
upb_Arena_Free(arena);
}
}
#[test]
fn array_ffi_test() {
// SAFETY: FFI unit test uses C API under expected patterns.
unsafe {
let arena = upb_Arena_New().unwrap();
let array = upb_Array_New(arena, CType::Float);
assert!(upb_Array_Append(array, upb_MessageValue { float_val: 7.0 }, arena));
assert!(upb_Array_Append(array, upb_MessageValue { float_val: 42.0 }, arena));
assert_eq!(upb_Array_Size(array), 2);
assert!(matches!(upb_Array_Get(array, 1), upb_MessageValue { float_val: 42.0 }));
assert!(upb_Array_Resize(array, 3, arena));
assert_eq!(upb_Array_Size(array), 3);
assert!(matches!(upb_Array_Get(array, 2), upb_MessageValue { float_val: 0.0 }));
upb_Arena_Free(arena);
}
}
#[test]
fn map_ffi_test() {
// SAFETY: FFI unit test uses C API under expected patterns.
unsafe {
let arena = upb_Arena_New().unwrap();
let map = upb_Map_New(arena, CType::Bool, CType::Double);
assert_eq!(upb_Map_Size(map), 0);
assert_eq!(
upb_Map_Insert(
map,
upb_MessageValue { bool_val: true },
upb_MessageValue { double_val: 2.0 },
arena
),
MapInsertStatus::Inserted
);
assert_eq!(
upb_Map_Insert(
map,
upb_MessageValue { bool_val: true },
upb_MessageValue { double_val: 3.0 },
arena,
),
MapInsertStatus::Replaced,
);
assert_eq!(upb_Map_Size(map), 1);
upb_Map_Clear(map);
assert_eq!(upb_Map_Size(map), 0);
assert_eq!(
upb_Map_Insert(
map,
upb_MessageValue { bool_val: true },
upb_MessageValue { double_val: 4.0 },
arena
),
MapInsertStatus::Inserted
);
let mut out = upb_MessageValue::zeroed();
assert!(upb_Map_Get(map, upb_MessageValue { bool_val: true }, &mut out));
assert!(matches!(out, upb_MessageValue { double_val: 4.0 }));
upb_Arena_Free(arena);
}
}
}

@ -6,6 +6,8 @@
// https://developers.google.com/open-source/licenses/bsd
//
#include <stddef.h>
#define UPB_BUILD_API
#include "upb/mem/arena.h" // IWYU pragma: keep

@ -1,15 +0,0 @@
# This package contains Rust protobuf runtime implementation built on top of UPB.
cc_library(
name = "upb_c_api",
srcs = ["upb_api.c"],
visibility = [
"//rust:__subpackages__",
"//src/google/protobuf:__subpackages__",
],
deps = [
"//upb:mem",
"//upb:message",
"//upb:message_copy",
],
)

@ -5,9 +5,10 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
use crate::__internal::{Private, PtrAndLen, RawMessage};
use crate::__internal::Private;
use crate::__runtime::{
copy_bytes_in_arena_if_needed_by_runtime, InnerPrimitiveMut, MutatorMessageRef,
copy_bytes_in_arena_if_needed_by_runtime, InnerPrimitiveMut, MutatorMessageRef, PtrAndLen,
RawMessage,
};
use crate::{
AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, PrimitiveMut, Proxied,

@ -114,15 +114,15 @@ void Map::InExternC(Context& ctx, const FieldDescriptor& field) const {
[&] {
if (ctx.is_upb()) {
ctx.Emit({}, R"rs(
fn $getter_thunk$(raw_msg: $pbi$::RawMessage)
-> Option<$pbi$::RawMap>;
fn $getter_mut_thunk$(raw_msg: $pbi$::RawMessage,
arena: $pbi$::RawArena) -> $pbi$::RawMap;
fn $getter_thunk$(raw_msg: $pbr$::RawMessage)
-> Option<$pbr$::RawMap>;
fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage,
arena: $pbr$::RawArena) -> $pbr$::RawMap;
)rs");
} else {
ctx.Emit({}, R"rs(
fn $getter_thunk$(msg: $pbi$::RawMessage) -> $pbi$::RawMap;
fn $getter_mut_thunk$(msg: $pbi$::RawMessage,) -> $pbi$::RawMap;
fn $getter_thunk$(msg: $pbr$::RawMessage) -> $pbr$::RawMap;
fn $getter_mut_thunk$(msg: $pbr$::RawMessage,) -> $pbr$::RawMap;
)rs");
}
}},

@ -115,26 +115,26 @@ void RepeatedField::InExternC(Context& ctx,
if (ctx.is_upb()) {
ctx.Emit(R"rs(
fn $getter_mut_thunk$(
raw_msg: $pbi$::RawMessage,
raw_msg: $pbr$::RawMessage,
size: *const usize,
arena: $pbi$::RawArena,
) -> $pbi$::RawRepeatedField;
arena: $pbr$::RawArena,
) -> $pbr$::RawRepeatedField;
// Returns `None` when returned array pointer is NULL.
fn $getter_thunk$(
raw_msg: $pbi$::RawMessage,
raw_msg: $pbr$::RawMessage,
size: *const usize,
) -> Option<$pbi$::RawRepeatedField>;
) -> Option<$pbr$::RawRepeatedField>;
)rs");
} else {
ctx.Emit(R"rs(
fn $getter_mut_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::RawRepeatedField;
fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::RawRepeatedField;
fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::RawRepeatedField;
fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::RawRepeatedField;
)rs");
}
}},
{"clearer_thunk", ThunkName(ctx, field, "clear")}},
R"rs(
fn $clearer_thunk$(raw_msg: $pbi$::RawMessage);
fn $clearer_thunk$(raw_msg: $pbr$::RawMessage);
$getter$
)rs");
}

@ -161,32 +161,32 @@ void SingularMessage::InExternC(Context& ctx,
if (ctx.is_cpp()) {
ctx.Emit(
R"rs(
fn $getter_mut_thunk$(raw_msg: $pbi$::RawMessage)
-> $pbi$::RawMessage;)rs");
fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage)
-> $pbr$::RawMessage;)rs");
} else {
ctx.Emit(
R"rs(fn $getter_mut_thunk$(raw_msg: $pbi$::RawMessage,
arena: $pbi$::RawArena)
-> $pbi$::RawMessage;)rs");
R"rs(fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage,
arena: $pbr$::RawArena)
-> $pbr$::RawMessage;)rs");
}
}},
{"ReturnType",
[&] {
if (ctx.is_cpp()) {
// guaranteed to have a nonnull submsg for the cpp kernel
ctx.Emit({}, "$pbi$::RawMessage;");
ctx.Emit({}, "$pbr$::RawMessage;");
} else {
// upb kernel may return NULL for a submsg, we can detect this
// in terra rust if the option returned is None
ctx.Emit({}, "Option<$pbi$::RawMessage>;");
ctx.Emit({}, "Option<$pbr$::RawMessage>;");
}
}},
},
R"rs(
fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $ReturnType$;
fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $ReturnType$;
$getter_mut$
fn $clearer_thunk$(raw_msg: $pbi$::RawMessage);
fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool;
fn $clearer_thunk$(raw_msg: $pbr$::RawMessage);
fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool;
)rs");
}

@ -109,15 +109,15 @@ void SingularScalar::InExternC(Context& ctx,
[&] {
if (field.has_presence()) {
ctx.Emit(R"rs(
fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool;
fn $clearer_thunk$(raw_msg: $pbi$::RawMessage);
fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool;
fn $clearer_thunk$(raw_msg: $pbr$::RawMessage);
)rs");
}
}}},
R"rs(
$with_presence_fields_thunks$
fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $Scalar$;
fn $setter_thunk$(raw_msg: $pbi$::RawMessage, val: $Scalar$);
fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $Scalar$;
fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $Scalar$);
)rs");
}

@ -194,15 +194,15 @@ void SingularString::InExternC(Context& ctx,
[&] {
if (field.has_presence()) {
ctx.Emit(R"rs(
fn $hazzer_thunk$(raw_msg: $pbi$::RawMessage) -> bool;
fn $clearer_thunk$(raw_msg: $pbi$::RawMessage);
fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool;
fn $clearer_thunk$(raw_msg: $pbr$::RawMessage);
)rs");
}
}}},
R"rs(
$with_presence_fields_thunks$
fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::PtrAndLen;
fn $setter_thunk$(raw_msg: $pbi$::RawMessage, val: $pbi$::PtrAndLen);
fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::PtrAndLen;
fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::PtrAndLen);
)rs");
}

@ -73,14 +73,14 @@ void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) {
.WithSuffix("")},
R"rs(
extern "C" {
fn $map_new_thunk$() -> $pbi$::RawMap;
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: $ffi_key_t$, value: $name$) -> bool;
fn $map_get_thunk$(m: $pbi$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool;
fn $map_remove_thunk$(m: $pbi$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool;
fn $map_iter_thunk$(m: $pbi$::RawMap) -> $pbr$::UntypedMapIterator;
fn $map_new_thunk$() -> $pbr$::RawMap;
fn $map_free_thunk$(m: $pbr$::RawMap);
fn $map_clear_thunk$(m: $pbr$::RawMap);
fn $map_size_thunk$(m: $pbr$::RawMap) -> usize;
fn $map_insert_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: $name$) -> bool;
fn $map_get_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool;
fn $map_remove_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool;
fn $map_iter_thunk$(m: $pbr$::RawMap) -> $pbr$::UntypedMapIterator;
fn $map_iter_get_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $name$);
}
impl $pb$::ProxiedInMapValue<$key_t$> for $name$ {
@ -170,7 +170,7 @@ void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) {
$pbr$::upb_Map_New(
arena.raw(),
<$key_t$ as $pbr$::UpbTypeConversions>::upb_type(),
$pbr$::UpbCType::Enum)
$pbr$::CType::Enum)
};
$pb$::Map::from_inner(
$pbi$::Private,

@ -202,17 +202,17 @@ void MessageExterns(Context& ctx, const Descriptor& msg) {
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 $parse_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);
fn $new_thunk$() -> $pbr$::RawMessage;
fn $delete_thunk$(raw_msg: $pbr$::RawMessage);
fn $serialize_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::SerializedData;
fn $parse_thunk$(raw_msg: $pbr$::RawMessage, data: $pbr$::SerializedData) -> bool;
fn $copy_from_thunk$(dst: $pbr$::RawMessage, src: $pbr$::RawMessage);
fn $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize;
fn $repeated_add_thunk$(raw: $pbr$::RawRepeatedField) -> $pbr$::RawMessage;
fn $repeated_get_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage;
fn $repeated_get_mut_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage;
fn $repeated_clear_thunk$(raw: $pbr$::RawRepeatedField);
fn $repeated_copy_from_thunk$(dst: $pbr$::RawRepeatedField, src: $pbr$::RawRepeatedField);
)rs");
return;
@ -223,10 +223,10 @@ void MessageExterns(Context& ctx, const Descriptor& msg) {
{"minitable", UpbMinitableName(msg)},
},
R"rs(
fn $new_thunk$(arena: $pbi$::RawArena) -> $pbi$::RawMessage;
fn $new_thunk$(arena: $pbr$::RawArena) -> $pbr$::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;
static $minitable$: $pbr$::upb_MiniTable;
)rs");
return;
}
@ -487,15 +487,15 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
.WithSuffix("")},
R"rs(
extern "C" {
fn $map_new_thunk$() -> $pbi$::RawMap;
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: $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_get_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $pbi$::RawMessage);
fn $map_new_thunk$() -> $pbr$::RawMap;
fn $map_free_thunk$(m: $pbr$::RawMap);
fn $map_clear_thunk$(m: $pbr$::RawMap);
fn $map_size_thunk$(m: $pbr$::RawMap) -> usize;
fn $map_insert_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: $pbr$::RawMessage) -> bool;
fn $map_get_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $pbr$::RawMessage) -> bool;
fn $map_remove_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $pbr$::RawMessage) -> bool;
fn $map_iter_thunk$(m: $pbr$::RawMap) -> $pbr$::UntypedMapIterator;
fn $map_iter_get_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $pbr$::RawMessage);
}
impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ {
fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> {
@ -580,8 +580,8 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
},
R"rs(
impl $pbr$::UpbTypeConversions for $Msg$ {
fn upb_type() -> $pbr$::UpbCType {
$pbr$::UpbCType::Message
fn upb_type() -> $pbr$::CType {
$pbr$::CType::Message
}
fn to_message_value(
@ -590,7 +590,7 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
}
unsafe fn to_message_value_copy_if_required(
arena: $pbi$::RawArena,
arena: $pbr$::RawArena,
val: $pb$::View<'_, Self>) -> $pbr$::upb_MessageValue {
// Self::to_message_value(val)
// SAFETY: The arena memory is not freed due to `ManuallyDrop`.
@ -871,7 +871,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct $Msg$View<'msg> {
msg: $pbi$::RawMessage,
msg: $pbr$::RawMessage,
_phantom: $Phantom$<&'msg ()>,
}
@ -884,11 +884,11 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
#[allow(dead_code)]
impl<'msg> $Msg$View<'msg> {
#[doc(hidden)]
pub fn new(_private: $pbi$::Private, msg: $pbi$::RawMessage) -> Self {
pub fn new(_private: $pbi$::Private, msg: $pbr$::RawMessage) -> Self {
Self { msg, _phantom: $std$::marker::PhantomData }
}
fn raw_msg(&self) -> $pbi$::RawMessage {
fn raw_msg(&self) -> $pbr$::RawMessage {
self.msg
}
@ -1010,7 +1010,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
pub fn from_parent(
_private: $pbi$::Private,
parent: $pbr$::MutatorMessageRef<'msg>,
msg: $pbi$::RawMessage)
msg: $pbr$::RawMessage)
-> Self {
Self {
inner: $pbr$::MutatorMessageRef::from_parent(
@ -1026,7 +1026,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
#[deprecated = "This .or_default() is a no-op, usages can be safely removed"]
pub fn or_default(self) -> Self { self }
fn raw_msg(&self) -> $pbi$::RawMessage {
fn raw_msg(&self) -> $pbr$::RawMessage {
self.inner.msg()
}
@ -1072,7 +1072,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
$Msg::new$
}
fn raw_msg(&self) -> $pbi$::RawMessage {
fn raw_msg(&self) -> $pbr$::RawMessage {
self.inner.msg
}
@ -1131,10 +1131,10 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
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 {
pub fn __unstable_wrap_cpp_grant_permission_to_break(msg: $pbr$::RawMessage) -> Self {
Self { inner: $pbr$::MessageInner { msg } }
}
pub fn __unstable_leak_cpp_repr_grant_permission_to_break(self) -> $pbi$::RawMessage {
pub fn __unstable_leak_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage {
let s = std::mem::ManuallyDrop::new(self);
s.raw_msg()
}
@ -1144,12 +1144,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
//~ msg is a &mut so that the borrow checker enforces exclusivity to
//~ prevent constructing multiple Muts/Views from the same RawMessage.
pub fn __unstable_wrap_cpp_grant_permission_to_break(
msg: &'a mut $pbi$::RawMessage) -> Self {
msg: &'a mut $pbr$::RawMessage) -> Self {
Self {
inner: $pbr$::MutatorMessageRef::from_raw_msg($pbi$::Private, msg)
}
}
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbi$::RawMessage {
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage {
self.raw_msg()
}
}
@ -1158,10 +1158,10 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
//~ msg is a & so that the caller can claim the message is live for the
//~ corresponding lifetime.
pub fn __unstable_wrap_cpp_grant_permission_to_break(
msg: &'a $pbi$::RawMessage) -> Self {
msg: &'a $pbr$::RawMessage) -> Self {
Self::new($pbi$::Private, *msg)
}
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbi$::RawMessage {
pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage {
self.msg
}
}

@ -421,7 +421,7 @@ PROTOBUF_CONSTINIT const MapKeyType kMapKeyTypes[] = {
/*cc_to_ffi_key_expr=*/"cpp_key"},
{/*thunk_ident=*/"ProtoStr",
/*rs_key_t=*/"$pb$::ProtoStr",
/*rs_ffi_key_t=*/"$pbi$::PtrAndLen",
/*rs_ffi_key_t=*/"$pbr$::PtrAndLen",
/*rs_to_ffi_key_expr=*/"key.as_bytes().into()",
/*rs_from_ffi_key_expr=*/
"$pb$::ProtoStr::from_utf8_unchecked(ffi_key.as_ref())",

@ -231,7 +231,7 @@ void GenerateOneofExternC(Context& ctx, const OneofDescriptor& oneof) {
{"case_thunk", ThunkName(ctx, oneof, "case")},
},
R"rs(
fn $case_thunk$(raw_msg: $pbi$::RawMessage) -> $oneof_enum_module$$case_enum_rs_name$;
fn $case_thunk$(raw_msg: $pbr$::RawMessage) -> $oneof_enum_module$$case_enum_rs_name$;
)rs");
}

Loading…
Cancel
Save