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
This change adds `Sized` as a supertrait of our `SealedInternal` trait, to
ensure that our codegen traits cannot be used as trait objects (i.e. with
`dyn`). I was thinking it would be prudent to do this early so that we don't
end up accidentally forced to support `dyn` usage.
Some of the traits already disallowed `dyn` as a result of having `Sized` as an
indirect supertrait or for other reasons, but a few traits did allow trait
objects.
If we ever do want to support some kind of type-erased message, I suspect we
will want to provide our own implementation. At least for C++, we already have
a vtable in the kernel, so it would seem wasteful to have Rust duplicate it.
PiperOrigin-RevId: 692195274
This makes it possible to match views by value:
```rust
expect_that!(
response.clients(),
unordered_elements_are![
proto_eq(proto!(Client { name: "Alice" }).as_view()),
proto_eq(proto!(Client { name: "Bob" }).as_view())
]
);
```
where `clients()` return an iterator over `ClientView` values.
PiperOrigin-RevId: 692192744
Export the traits with a `Proto` prefix on them to minimize collisions (especially the high risk of confusing collision with the std prelude's AsMut).
Remove Message, MessageMut and MessageView from the prelude.
PiperOrigin-RevId: 691388401
Without this, `cargo test` tries to extract all rustdoc comments and run them as a unit test. For these snippets, we can't easily actually make such a snippet work, as they explain how codegen would be used.
PiperOrigin-RevId: 688643028
This required making a shim file for a crate to be able to re-export either the _cpp or _upb impl so that it can be one crate that conditionally delegates to the intended one.
PiperOrigin-RevId: 688639897
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
There is an old convention that a `proto_library` target with empty `srcs`
should re-export its dependencies. This is sometimes useful as a way of
creating something like an alias target, except that it can point to multiple
dependencies rather than just one.
The `rust_proto_library` aspect currently cannot handle this pattern and will
raise an error if it encounters a `proto_library` without `srcs`. This CL fixes
that problem by updating the `RustProtoInfo` provider generated by the aspect
to include a list of `DepVariantInfo` instead of just one. In the typical case
the provider will have just one `DepVariantInfo`, but this gives us the ability
to return more than one in the case where we're exporting all the dependencies
of a `src`-less `proto_library`.
One thing this CL specifically does not attempt to do is add support for a
`rust_proto_library` directly wrapping a `proto_library` without `srcs`. The
reason for that is that it appears difficult to do in a way that would respect
the layering check. It's also not obvious that we would want to encourage this
pattern anyway. It's still valuable to support `src`-less `proto_library`
targets when they're somewhere else in the transitive dependencies. This way
you can freely create a `rust_proto_library` without having to fix up all your
transitive deps first.
PiperOrigin-RevId: 687344284
When you call a map field setter, we currently make an unnecessary extra copy,
so this CL fixes that problem.
I followed the example of how we already handle this for repeated field
setters. This required adding a new move setter thunk for map fields with the
C++ kernel. Originally I tried instead to add an FFI endpoint that could swap
two `RawMap` pointers, but it turned out to be difficult to implement this in a
way that worked correctly when the two maps are not on the same arena.
PiperOrigin-RevId: 687334655
`ProtoStr` is a public type and it has a public
method `to_str`, however `to_str` returns a private
type `Utf8Error`, which triggers `private-interfaces` [1].
Exporting string::Utf8Error makes it possible for other
crates to wrap it in another error type and propagate
it with "?".
[1] https://doc.rust-lang.org/beta/rustc/lints/listing/warn-by-default.html#private-interfaces
PiperOrigin-RevId: 684477510
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
The immediate motivation for this is that it will facilitate writing a blanket
implementation of `ProxiedInMapValue` for C++-backed messages. The default
instance gives us access to the message vtable in cases where we don't already
have a message to work with.
However, it also seems generally useful just to have an implementation of
`Default`, so I implemented it for both C++ and upb-backed message views.
PiperOrigin-RevId: 677808048
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
`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
This CL doesn't unbreak the bazel tests, but is yak shaving in prep for changes that will. This makes it more straightforward how the tests are broken by having bazel test rules name rust proto library targets that don't exist in bazel repo, instead of naming targets that do exist but are bogus.
Also correct unittest_edition target to match the order of words in the .proto file name (edition_unittest)
PiperOrigin-RevId: 674295376
I realized that as long as we implement `UpbTypeConversions` for enums, we can
easily get the blanket implementation for messages to work for enums as well.
Luckily the blanket implementation also happens to work for non-generated
types, so this gets us down to just one ProxiedInMapValue implementation for
upb.
PiperOrigin-RevId: 673927343