Commit graph

102 commits

Author SHA1 Message Date
Protobuf Team Bot
e1c5f3ac47 rust protobuf matchers: Add a partially matcher to mirror C++
It is common to want to match only a subset of fields in large protobufs, and doing that in rust right now requires manually clearing out the fields in the `actual` message that we don't care about. This is a pain, and a worse experience when compared to C++.

Like in C++, when doing partial matching, only fields set in the expected protobuf message are compared, while extra fields set only in the actual message are ignored.

When using the C++ kernel we leverage `proto2::util::MessageDifferencer`, and for the UPB kernel we use the `kUpb_CompareOption_Partial` option.

PiperOrigin-RevId: 964125682
2026-08-13 09:24:36 -07:00
Clayton Knittel
c4be7483cb Use ClassData instead of a prototype throughout lazy field / extensions when possible.
`New` is more efficient on ClassData than on a prototype, as `New` on the prototype has to first load the class data through the prototype.

There's also a small optimization in `LazyField::MergeFromMessage` which avoids loading the class data twice. The redundancy was made more obvious by this refactor.

PiperOrigin-RevId: 953889072
2026-07-25 09:22:11 -07:00
Protobuf Team Bot
4bb2c61094 Internal change.
PiperOrigin-RevId: 951011798
2026-07-20 13:13:44 -07:00
Protobuf Team Bot
6abea2a805 RustProto: Remove redundant length checks and casts in message.cc
PiperOrigin-RevId: 932445168
2026-06-15 07:21:11 -07:00
Protobuf Team Bot
4184df38a3 Automated Code Change
PiperOrigin-RevId: 932193885
2026-06-14 20:35:06 -07:00
Protobuf Team Bot
54b62411d7 Remove unused Matcher_Eq import in rust
PiperOrigin-RevId: 927449688
2026-06-05 13:17:35 -07:00
Protobuf Team Bot
59aa92b4fa Automated Code Change
PiperOrigin-RevId: 907335237
2026-04-28 21:15:09 -07:00
Protobuf Team Bot
06afcbd65b RustProto: add serialized_len()->usize
PiperOrigin-RevId: 904638364
2026-04-23 14:34:21 -07:00
Protobuf Team Bot
0be05fd8f9 Add Private passkey to extension api that is only intended to be available for internal and gencode use.
PiperOrigin-RevId: 899554889
2026-04-14 06:48:28 -07:00
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
Joshua Haberman
f54e9a1eaf Refactor: Move interop traits to kernel-specific modules.
This change moves the `OwnedMessageInterop`, `MessageViewInterop`, and `MessageMutInterop` traits from `codegen_traits.rs` into new `interop.rs` files within both the `cpp_kernel` and `upb_kernel` directories.

The `KernelMessage`, `KernelMessageView`, and `KernelMessageMut` traits in each kernel's `message.rs` are updated to include the respective kernel-specific interop traits. This ensures that the interop functionality is tied to the specific kernel implementation.

The `shared.rs` module now re-exports the interop traits from `crate::__internal::runtime::interop`, which will resolve to the correct kernel's interop module.

It would be possible to take this farther by making the interop traits return strongly typed pointers to `upb_Message*` and `proto2::MessageLite*` instead of `c_void`, but that would be a breaking change.

PiperOrigin-RevId: 892470084
2026-03-31 12:04:34 -07:00
Protobuf Team Bot
002f830c46 Remove Copy+Clone from MessageMutInner.
MessageMutInner was Copy+Clone, which had been convenient for some internal use. But, with them being .into() SomeMessageMut this was a potential footgun, since it was very easy to into() the same one twice which would be formally unsound if it was reachable (including that you could send each of them to a different thread and concurrently modify them).

As these were implementation detail types this is only a defensive fix and no actual soundness issues were identified.

PiperOrigin-RevId: 888615057
2026-03-24 05:52:58 -07:00
Joshua Haberman
1c478d5923 Added appropriate super-traits to Enum.
The `Enum` trait now requires several other traits, including `Singular`, `Into<i32>`, `Copy`, `Proxied`, `EntityType`, and `SealedInternal`. This simplifies bounds in functions that operate on types implementing `Enum`, as they no longer need to explicitly list `+ Singular` and other common requirements.

PiperOrigin-RevId: 888286136
2026-03-23 14:40:03 -07:00
Joshua Haberman
2b3058dcff Refactor: Split upb and cpp backends into submodules
This CL contains no functional change, it is a pure splitting of the existing files.

I elected to move the C++ kernel files to `cpp_kernel/` which already contained the C++ API for the C++ kernel.  Unfortunately this required removing the existing `third_party/protobuf/rust/cpp_kernel/BUILD` file, because, the Rust parts of the cpp kernel have circular dependencies with the shared code in `third_party/protobuf/rust`.

PiperOrigin-RevId: 886884124
2026-03-20 11:13:43 -07:00
Protobuf Team Bot
a8daa95057 Trait clarity improvement on Map traits
Make a new trait "MapKey" to represent the types that are allowed as a Map Key. Without this, right now our Map<> bounds is over generalized.

Rename "ProxiedInMapValue" to "MapValue" to correspondingly represent the types that are allowed as a Map Value.

PiperOrigin-RevId: 860118222
2026-01-23 08:26:31 -08:00
Chris Kennelly
99753deb2e Suppress failure to consume parse/serialize return values.
PiperOrigin-RevId: 840725820
2025-12-05 08:01:34 -08:00
Protobuf Team Bot
b7e5d60e5d Automated Code Change
PiperOrigin-RevId: 825945840
2025-10-30 02:55:48 -07:00
Protobuf Team Bot
793dbb91b6 Expose unstable message descriptor getter to Rust.
PiperOrigin-RevId: 822582353
2025-10-22 07:43:06 -07:00
Protobuf Team Bot
a9d0fd2406 Automated rollback of commit c381fa449c.
PiperOrigin-RevId: 820944027
2025-10-17 21:32:55 -07:00
Protobuf Team Bot
c381fa449c Expose unstable message descriptor getter to Rust.
PiperOrigin-RevId: 820862343
2025-10-17 16:12:08 -07:00
Hong Shin
f2adb4d47d internal change
PiperOrigin-RevId: 819316614
2025-10-14 11:30:30 -07:00
Clayton Knittel
be2d06dd93 Pass arenas down to map methods, and avoid accessing arena_ directly in map field implementation.
Note that we can't change any public-facing API's that need an arena pointer, as this would be a breaking change. Additionally, assignment operators need the arena pointer, but can't take additional arguments.

This is in preparation for removing the arena_ member from maps.

PiperOrigin-RevId: 818979467
2025-10-13 21:20:18 -07:00
Clayton Knittel
3de6c8309f Don't call arena-enabled constructors of Map when not necessary.
PiperOrigin-RevId: 818961096
2025-10-13 20:31:34 -07:00
Adam Cozzette
3ff832936e Start testing against Rust edition 2024
This change also makes all the necessary fixes to get us compatible with
edition 2024.

I set things up so that we test edition 2024 with Bazel but keep Cargo on
edition 2021. This seems like a nice way to go since it allows us to get full
test coverage of both editions without us having to increment our minimum
supported Rust version.

PiperOrigin-RevId: 816241556
2025-10-07 09:21:51 -07:00
Adam Cozzette
529b73d6f7 Internal change
PiperOrigin-RevId: 811418305
2025-09-25 11:00:57 -07:00
Clayton Knittel
78ee1a6c71 Pass down Arena* to RepeatedPtrFieldBase::AddInternal.
PiperOrigin-RevId: 807447572
2025-09-15 17:27:17 -07:00
Clayton Knittel
477d221f9c Pass arenas down to RepeatedPtrFieldBase methods to avoid calling GetArena().
PiperOrigin-RevId: 807364895
2025-09-15 13:43:42 -07:00
Protobuf Team Bot
158312dc8c Automated Code Change
PiperOrigin-RevId: 782733463
2025-07-13 20:59:16 -07:00
Protobuf Team Bot
0efc4d1afc Fix rust-cpp parse FFI to use PtrAndLen instead of SerializedData
PiperOrigin-RevId: 764746425
2025-05-29 08:57:07 -07:00
Protobuf Team Bot
7d609666b6 Add Message_parse_dont_enforce_required to Rust C++ proto wrapper.
PiperOrigin-RevId: 755782611
2025-05-07 03:58:16 -07:00
Protobuf Team Bot
59fec72c77 Streamline creation of new elements in RepeatedPtrField (redux)
The logic to create new elements in `RepeatedPtrField` was spread across an assorted collection of specializations of `GenericTypeHandler`, individual `GenericTypeHandler` static functions, and external member and non-member functions, all living in multiple sources. Now all that logic is concentrated in three symmetric `GenericTypeHandler` specializations.

PiperOrigin-RevId: 754049107
2025-05-02 10:23:18 -07:00
Sandy Zhang
ba6b54d6bc Upgrade abseil-cpp to 20250127 and use @com_google_absl -> @abseil-cpp and com_google_googletest -> @googletest canonical BCR names.
Users still using the old `WORKSPACE` system may need to do the same or use `repo_mapping` on repositories that still use the old names. See Abseil's release notes for details: https://github.com/abseil/abseil-cpp/releases/tag/20250127.

#test-continuous

PiperOrigin-RevId: 725247849
2025-02-10 09:43:53 -08:00
Protobuf Team Bot
a5920a728d Reimplement DynamicMapField to use UntypedMapBase directly.
It uses the same nodes that Map<> would use for the respectice types.
This makes the type compatible with visitation and removes some custom types
supporting DynamicMapField.

Remove most of the vtable, since this can now be done directly in MapFieldBase without derived type support.

PiperOrigin-RevId: 717984824
2025-01-21 11:01:50 -08:00
Protobuf Team Bot
828716eb57 Use generic DeleteNode to reduce code size of erase in Map and to simplify the parsing logic in MpMap.
PiperOrigin-RevId: 704832360
2024-12-10 13:51:39 -08:00
Protobuf Team Bot
7fbb3d2cc7 Make conversion functions for into c++ string types from PtrAndLen.
The invariant is that PtrAndLen may hold ptr+len values which are legal for _either_ C++ string_view or Rust slices: constructing one from either Rust or C++ permits the laxest constraints, and care must be taken when converting a PtrAndLen into either type.

For "into Rust slice" case to handle is that len=0 ptr must be non-null, so len=0 ptr=null gets turned into an arbitrary non-null pointer as provided by std::ptr::NonNull::dangling() (any preexisting non-null ptr is kept in that direction).

For the "into C++ slice" the risk is more obscure that a Rust non-null pointer could potentially be an illegal pointer (such that ptr+0 is not a legal operation in C++), so when going into C++ we map any len=0 cases into ptr=null to avoid this as a possible risk.

PiperOrigin-RevId: 704776210
2024-12-10 11:15:00 -08:00
Protobuf Team Bot
7588e512b6 Use visitation to implement allocation/initialization/deallocation of nodes in generic code.
This simplifies Rust bindings, and the table-driven parser.

PiperOrigin-RevId: 700702876
2024-11-27 08:05:11 -08:00
Protobuf Team Bot
aa9868e137 Reimplement ClearTable using the stored TypeInfo.
Clean up the rust bindings to use this better interface.

PiperOrigin-RevId: 699199230
2024-11-22 09:54:58 -08:00
Protobuf Team Bot
d6b90bfd66 Add TypeInfo type UntypedMapBase for generic operation support.
The data is not currently used. This change is what we need to hook it up from Rust. In a future change we will start using the data to simplify the interface.

No expected performance change. The data inserted via static typing is constant evaluated, and fits in the existing padding (in 64-bit builds).

Also, fix Rust bindings to take float/double into account now that the enum lists them.

PiperOrigin-RevId: 698780360
2024-11-21 08:03:13 -08:00
Adam Cozzette
9bdafdbb0c Rust C++: remove per-message functions for repeated fields
This CL deletes the per-message C++ functions for operating on repeated fields
and replaces them with functions in the runtime that can work with arbitrary
messages.

Similar to what we did with maps, this required refactoring the code to make it
work with `RepeatedPtrFieldBase`, the untyped base class of
`RepeatedPtrField<T>`. I added a `RustRepeatedMessageHelper` class to allow us
access to the protected methods we need.

This should save a bit of linker input code size, but I think more importantly
we are going to need this eventually to enable tree shaking to work well.

PiperOrigin-RevId: 693394959
2024-11-05 10:24:35 -08:00
Adam Cozzette
cbb3edd86d Rust C++: get all map fields onto a common implementation of ProxiedInMapValue
This CL migrates messages, enums, and primitive types all onto the same blanket
implementation of the `ProxiedInMapValue` trait. This gets us to the point
where messages and enums no longer need to generate any significant amount of
extra code just in case they might be used as a map value.

There are a few big pieces to this:
 - I generalized the message-specific FFI endpoints in `rust/cpp_kernel/map.cc`
   to be able to additionally handle enums and primitive types as values. This
   mostly consisted of replacing `MessageLite*` parameters with a new `MapValue`
   tagged union.
 - On the Rust side, I added a new blanket implementation of
   `ProxiedInMapValue` in rust/cpp.rs. It relies on its value type to implement
   a new `CppMapTypeConversions` trait so that it can convert to and from the
   `MapValue` tagged union used for FFI.
 - In the Rust generated code, I deleted the generated `ProxiedInMapValue`
   implementations for messages and enums and replaced them with
   implementations of the `CppMapTypeConversions` trait.

PiperOrigin-RevId: 687355817
2024-10-18 10:52:08 -07:00
Adam Cozzette
d900d6114c Rust: remove use of MapNodeSizeInfoT from generated code
We generate these constants to enable map operations, but this is no longer
necessary now that we can get the relevant size and alignment information for
each message through its vtable.

PiperOrigin-RevId: 680712939
2024-09-30 14:13:36 -07:00
Adam Cozzette
5c3d1e8c30 Rust protobuf: remove the need for a generated placement_new thunk
We have been relying on a per-message generated `placement_new` function for
implementing map insertion, but this CL simplifies things by removing that.
Instead, we do a reflective swap if possible, or else fall back on a copy.

This will probably make insertions a bit slower, but I think it may be worth it
because it should make it much simpler to have a blanket implementation for
ProxedInMapValue that works for all map types.

It looks like it should be possible to make this faster in the future by
implementing a bitwise move that will work for any message.

PiperOrigin-RevId: 676495920
2024-09-19 11:34:17 -07:00
Adam Cozzette
dc23fedbf3 Simplify the way C++ function is passed to UntypedMapIterator::next_unchecked
`UntypedMapIterator::next_unchecked` currently expects to be passed a pointer
to a C++ function that it can use to dereference an iterator. However, this is
awkward because it's not natural for this C++ function to have the same
signature for every map type. Maps with a message as value need a
`MapNodeSizeInfo`, but other map types do not. We are working around this by
sometimes passing an ignored placeholder constant, but this is messy.

This CL replaces the `extern "C"` functions with closures. This way, we can
capture the `MapNodeSizeInfo` in the closure in cases where we need it, but
otherwise we no longer need to pass around placeholder values.

(Note: `MapNodeSizeInfo` is going away soon, but this is still relevant because
it will likely need to be replaced by a message default instance pointer.)

PiperOrigin-RevId: 676438640
2024-09-19 09:14:56 -07:00
Protobuf Team Bot
5da098b8b0 Make SerializedData into a POD struct.
PiperOrigin-RevId: 676124916
2024-09-18 14:17:14 -07:00
Mike Kruskal
5695a882bd Move -Werror to our test/dev bazelrc files.
Putting it into BUILD files unintentionally forces it on all our downstream users.  Instead, we just want to enable this during testing and let them choose for themselves in their builds.

Note, that this expands the scope of -Werror to our entire repo for CI, so a bunch of fixes and opt-outs had to be applied to get this change passing.

Closed #14714

PiperOrigin-RevId: 666903224
2024-08-23 13:26:32 -07:00
Adam Cozzette
7f395af40e Replace some per-message C++ thunks with a common implementation
This change adds delete, clear, serialize, parse, copy_from, and merge_from
operations to the runtime. Since these operations can all be implemented easily
on the `MessageLite` interface, we can use a common implementation in the
runtime instead of generating per-message thunks for all of these.

I suspect this will also make it possible to remove some of our generated trait
implementations and replace them with blanket implementations, but I will leave
that for a future change.

PiperOrigin-RevId: 665910927
2024-08-21 09:34:25 -07:00
Yamil Morales
582e80eb8a Set up for Rust-cpp Protobuf implementation message matcher.
PiperOrigin-RevId: 658397591
2024-08-01 07:52:17 -07:00
Adam Cozzette
6ab302d3a3 Rust: cut down on the amount of generated C++ code needed for maps
With the C++ kernel for Rust, we currently need to generate quite a few C++
thunks for operations on map fields. For each message we generate, we generate
these thunks for all possible map types that could have that message as a
value. These operations are for things such as insertion, removal, clearing,
iterating, etc.

The reason we do this is that templated types don't play well with FFI, so we
effectively need separate FFI endpoints for every possible combination of key
and value types used (or even potentially used) as a map field.

This CL fixes the problem by replacing the generated thunks with functions in
the runtime that can operate on `proto2::MessageLite*` without needing to care
about the specific message type.

The way it works is that we implement the operations using either
`UntypedMapBase` (the base class of all map types, which knows nothing about
the key and value types) or `KeyMapBase`, which knows the key type but not the
value type. I roughly followed the example of the table-driven parser, which
has a similar problem of needing to operate generically on maps without having
access to the concrete types.

I removed 54 thunks per message (that's 6 key types times 9 operations per
key), but had to add two new thunks per message:
 - The `size_info` thunk looks up the `MapNodeSizeInfoT`, which is stored in a
   small constant table. The important thing here is an offset indicating where
   to look for the value in each map entry. This offset can be different for
   every pair of key and value types, but we can safely assume that the result
   does not depend on the signedness of the key. As a result we only need to
   store four entries per message: one each for i32, i64, bool, and string.
 - The `placement_new` thunk move-constructs a message in place. We need this
   to be able to efficiently implement map insertion.

There are two big things that this CL does not address yet but which I plan to
follow up on:
 - Enums still generate many map-related C++ thunks that could be replaced with
   a common implementation. This should actually be much easier to handle than
   messages, because every enum has the same representation as an i32.
 - We still generate six `ProxiedInMapValue` implementations for every message,
   but it should be possible to replace these with a blanket implementation that
   works for all message types.

PiperOrigin-RevId: 657681421
2024-07-30 12:08:33 -07:00
Adam Cozzette
efb57278a9 Protobuf Rust: simplify the MakeCleanup() helper function
By changing the return type to `auto`, we can handle `std::string` and other
types in a single definition without needing a separate overload.

PiperOrigin-RevId: 653272253
2024-07-17 10:11:28 -07:00
Adam Cozzette
f712ca5d1c Rust protobuf: fix memory leaks
Our ASAN test runs have not had the heap checker enabled, so this has allowed a
few memory leaks to slip in. This CL fixes all of them so that we can turn on
the heap checker.

The first one takes place whenever we add an entry into a string-valued map
using the C++ kernel. The problem is that `InnerProtoString::into_raw()` gives
up ownership of the raw `std::string` pointer it holds, but then we never
delete that pointer. This CL fixes the problem by deleting the pointer in C++
right after we perform the map insertion. To simplify things, I created a
`MakeCleanup()` helper function that we always call in our map insertion
thunks, but it's a no-op in the cases where we don't need to free anything.

There were a couple similar memory leaks related to repeated field accessors in
the C++ kernel, and those were simple to fix just by adding the necessary
`delete` call.

Finally, there were two benign memory leaks in the upb kernel involving global
variables used for empty repeated fields and maps. It turned out that we did
not need to use `Box` at all here, so removing that simplified things and fixed
the leaks.

PiperOrigin-RevId: 652947042
2024-07-16 13:01:48 -07:00