dep-protobuf/rust/upb_kernel/mod.rs
Joshua Haberman 7c958618b6 Added infrastructure for Rust Extensions support, but left it disabled for now.
This code makes use of some Rust features that are not supported in Rust 1.85 (our currently supported version), so we cannot enable the codegen for this feature yet.

This CL introduces support for [Protobuf Extensions](https://engdoc.corp.google.com/eng/doc/devguide/proto/programming-guides/proto2.html#extensions) to the Rust Protobuf library, a key feature for full Proto2 API parity.

Key changes include:

1.  **Code Generation:**
    *   Added `compiler/rust/extension.cc` and `extension.h` to handle the generation of Rust code for extension definitions.
    *   Updated `generator.cc` and `message.cc` to invoke extension generation for both top-level and nested extensions.
    *   Generates `ExtensionId` constants for each extension.

2.  **Runtime API (`rust/extension.rs`):**
    *   Introduced the generic `ExtensionId<Extendee, T>` type to identify and type-check extensions.
    *   Defined traits for extension operations: `ExtHas`, `ExtGet`, `ExtSet`, `ExtClear`, and `ExtGetMut`.
    *   Implemented methods on `ExtensionId` that dispatch to the trait implementations provided by the active kernel.

3.  **Kernel Implementations:**
    *   **C++ Kernel (`rust/cpp_kernel/extension.rs`):** Implemented extension traits by calling into new C++ FFI functions (defined in `rust/cpp_kernel/extension.cc`) that interact with the C++ `ExtensionSet`.
    *   **UPB Kernel (`rust/upb_kernel/extension.rs`):** Implemented extension traits using UPB's MiniTable-based extension API. Extension MiniTables are registered at static initialization time using the `linkme` crate.

4.  **Build System:**
    *   Updated `protobuf/rust/BUILD` and `protobuf/compiler/rust/BUILD` to include new files.
    *   Added a dependency on `//third_party/rust/linkme/v0_3` for the UPB kernel's extension registration.

5.  **Testing:**
    *   Added `test/extensions.proto` and `test/extensions_separate_file.proto` to define various extension types.
    *   Added `test/shared/extensions_test.rs` with comprehensive tests covering presence, getters, setters, defaults, nested extensions, submessage extensions, repeated extensions, serialization, and `MergeFrom`.

This change enables Rust users to define and interact with Protobuf extensions in a type-safe manner, compatible with both the C++ and UPB runtimes.

PiperOrigin-RevId: 896506594
2026-04-08 08:08:46 -07:00

89 lines
2.9 KiB
Rust

// 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
//! UPB FFI wrapper code for use by Rust Protobuf.
pub mod conversions;
pub mod extension;
pub mod interop;
pub mod map;
pub mod message;
pub mod minitable;
pub mod repeated;
pub mod string;
pub use conversions::*;
pub use extension::*;
pub use interop::*;
pub use map::*;
pub use message::*;
pub use minitable::*;
pub use repeated::*;
pub use string::*;
use crate::__internal::entity_tag::*;
use crate::__internal::{EntityType, MatcherEq, Private, SealedInternal};
use crate::{
AsMut, AsView, Clear, ClearAndParse, CopyFrom, IntoProxied, Map, MapIter, MapMut, MapValue,
MapView, MergeFrom, Message, MessageMut, MessageView, Mut, ParseError, ProtoBytes, ProtoStr,
ProtoString, Proxied, Repeated, RepeatedMut, RepeatedView, Serialize, SerializeError, Singular,
TakeFrom, View,
};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem::{size_of, ManuallyDrop, MaybeUninit};
use std::ptr::{self, NonNull};
use std::slice;
use std::sync::OnceLock;
#[cfg(bzl)]
extern crate upb;
#[cfg(not(bzl))]
use crate::upb;
pub use upb::Arena;
pub use upb::AssociatedMiniTable;
pub use upb::AssociatedMiniTableEnum;
pub use upb::MessagePtr;
pub type MiniTablePtr = upb::RawMiniTable;
pub type MiniTableEnumPtr = upb::RawMiniTableEnum;
pub type MiniTableExtensionPtr = upb::RawMiniTableExtension;
pub type ExtensionRegistryPtr = upb::RawExtensionRegistry;
use upb::*;
pub fn debug_string<T: UpbGetMessagePtr>(msg: &T) -> String {
let ptr = msg.get_ptr(Private);
// SAFETY: `ptr` is legally dereferenceable.
unsafe { upb::debug_string(ptr) }
}
pub(crate) type RawRepeatedField = upb::RawArray;
pub(crate) type RawMap = upb::RawMap;
pub(crate) type PtrAndLen = upb::StringView;
/// A trait implemented by types which are allowed as keys in maps.
/// This is all types for fields except for repeated, maps, bytes, messages, enums and floating point types.
/// This trait is defined separately in cpp.rs and upb.rs to be able to set better subtrait bounds.
#[doc(hidden)]
pub trait MapKey: Proxied + EntityType + UpbTypeConversions<Self::Tag> + SealedInternal {}
thread_local! {
// We need to avoid dropping this Arena, because we use it to build mini tables that
// effectively have 'static lifetimes.
pub static THREAD_LOCAL_ARENA: ManuallyDrop<Arena> = ManuallyDrop::new(Arena::new());
}
pub mod __unstable {
// Stores a serialized FileDescriptorProto, along with references to its dependencies.
pub struct DescriptorInfo {
// The serialized FileDescriptorProto.
pub descriptor: &'static [u8],
// A reference to the DescriptorInfo associated with each .proto file that the current one
// imports.
pub deps: &'static [&'static DescriptorInfo],
}
}