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
This is in preparation for removing the impl Iterator on RepeatedMutIter, since we intend to make it a lending iterator which the std Iterator trait does not support.
PiperOrigin-RevId: 962265415
In Rust, enums are always closed, such that its UB to construct one that isn't the corresponding name. This is true even for #[non_exhaustive] #[repr(C)] enums.
If FFI provides such an enum, its always immediate UB in Rust if it reaches a case with no name.
PiperOrigin-RevId: 954588991
`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
These methods are one-to-three line wrappers delegating to underlying map implementations (upb/cpp_kernel). Without `#[inline]`, the compiler will not cross crate boundaries, resulting in many physical function call overheads for otherwise fully optimal code in hot loops on Map values.
PiperOrigin-RevId: 953537646
Before this, for a field in a oneof, GetOrCreateMutableMessage would read the union value without making sure it was the right case first, effectively casting blindly.
This would result in a crash in RustProto if you set any field in a oneof and then read the mutable-getter of a message-typed field in the same oneof.
PiperOrigin-RevId: 950998569
Added tests:
* One test to check that unused symbols will not be present in the final binary. This is now supported on all platforms.
* Another test to ensure the number of exception tables remains exactly same, even after adding more unused symbols in proto file. You will need to compile rust with panic=abort for this test.
For this test, we have kept proto's crate name to be identical, hence we need them in their own subdirectories.
PiperOrigin-RevId: 928340707
This is just a slightly more Rust idiomatic way of being clear that you are knowingly using unsafe to soundly extend a lifetime.
PiperOrigin-RevId: 926763735
Added fns like first(), last(), contains_key() and implement
standard traits that are supported by Vec (DoubleEndedIterator, FromIterator).
PiperOrigin-RevId: 910689041
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
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
We had already done this for one special case of an enum named XyzView with a sibling message named Xyz, but this change extends that to apply to all pairwise combination of message-or-enum XyzView and message Xyz.
Unfortunately protobuf has no holistic strategy for avoiding collisions in gencode of pairwise names, and unfortunately Rust is maximally hostile situation to collision problems. This is an incomplete fix for potential collisions of this shape, but covers a significant portion of realistic/organic collisions.
Fixes https://github.com/protocolbuffers/protobuf/issues/25736
PiperOrigin-RevId: 890070424
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
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
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
This simplifies the trait bounds in the implementation (`upb.rs` and `cpp.rs`), and solves some upcoming cases with extensions.
More cleanups can probably be performed, but this is quick initial pass.
PiperOrigin-RevId: 885668189
And same for &mut T if T impl AsMut
This matches the behavior of std::convert::AsRef which has similar blanket impls to this.
PiperOrigin-RevId: 883287790
protob::Optional was designed to be able to carry a default value in the Unset case, as in:
```message M { int32 x = 1 [default=42]; }```
Before this change: m.x_opt() would return Unset(42) if the field was unset.
After this change: m.x_opt() will return None instead. If they want to know the default value they will need to look at the accessor again, like:
if !msg.x_opt().is_none() { // or !msg.has_x()
let default_val = msg.x();
}
PiperOrigin-RevId: 883178303
Some suppressions to make our current code warning-clean. A number of these are slightly odd, because in blazel upb/rust is a separate crate and so has sensible pub fns that we don't happen to use (which is no-warning), but in Cargo where we embed it as a module in our crate without re-exporting it, it becomes a warning if we don't use those fns/constants/etc (because an unused fn on a crate-visibility struct is considered an unused fn warning).
Rust is set up so it won't show warnings from your cratesio deps, but as our
gencode is embedded in the callers crate warnings will annoy them. Tightening
this will help reduce (but not totally prevent) cases where warnings in our
code will show up to users.
PiperOrigin-RevId: 882686850
In both cases, support only try_into() not into() when going from [u8]: its intended that `string` fields maintain utf8ness invariant, so even though it is not UB if the invariant is violated, people should avoid it where feasible.
PiperOrigin-RevId: 878704268
The idea of this was to ensure that the gencode is refreshed if the generated output is modified out-of-band. However, it causes protoc to run on every single build because every time it regenerates the outputs, which in turn updates the timestamps, which causes the next build to regenerate it again.
Fixes https://github.com/protocolbuffers/protobuf/issues/26190
PiperOrigin-RevId: 878120672