This came up as a pull request here:
https://github.com/protocolbuffers/protobuf/pull/18239.
|tmpnam| is ugly and would be nice to avoid.
We don't necessarily want to substitute out GetTemporaryDirectoryName with
|std::filesystem::temp_directory_path| -- the current setup creates a
subdirectory under the tmp directory and uses TempDirDeleter to clean it up.
We want to preserve that behaviour: the current setup plays nicely with bazel
without polluting /tmp with unbounded growth.
#test-continuous
PiperOrigin-RevId: 677843997
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
This was untested before.
Some of the test names had drifted from the code's names; update those.
These tests have surfaced some problems around inconsistent exception types thrown.
PiperOrigin-RevId: 677588477
These tests were (generally) looping over OutputType already. Some tests were looping over a subset; I've expanded many tests to loop over more OutputTypes.
But the first failure they encountered with any OutputType meant they'd halt
that test, without testing the other OutputTypes. That's frustrating.
We use `assume()` to discard tests in the matrix that are irrelevant.
There are many java parameterized test runners. I followed the lead of
third_party/java_src/protobuf/current/javatests/com/google/protobuf/IsValidUtf8FourByteTest.java,
which uses Paramaterized runner.
This means:
- We see which output type is failing in the test name.
- We don't have to always assertWithMessage(OutputType.name()). We can just use
assertThat. Nice.
- It's really easy to add new coders, and run all the tests against them. I've
done that here for NIO encoders with offset, increasing their test coverage.
PiperOrigin-RevId: 677564209
This makes it clearer that we get the arguments around the right way, so the error messages make sense.
Also get rid of toList; it doesn't seem necessary, the Truth library can compare byte[]s just fine without first turning them into List<Byte>.
This is just a refactoring to make this test nicer before I add more tests covering out of space scenarios.
PiperOrigin-RevId: 676963220
Also, change the proto used in no_field_presence_map_test into its own proto.
This should result in cleaner more isolated tests.
No other changes (other than autoformatter removing unused definitions).
PiperOrigin-RevId: 676927081
This was mistakenly gated on edition and only applied to proto2/proto3 and edition 2023.
This also cleans up some of our validation logic for ctype/string_type. Similar to other language features, ctype will only be validated by the C++ generator. This means that protos that aren't used in C++ may end up with ctype incorrectly specified, but our Prototiller transformation for 2024 will strip those anyway (since we ban ctype in 2024).
PiperOrigin-RevId: 676893004
While in practice a C++ ref and ptr will have the same ABI, since C doesn't have refs this gets flagged by -Wreturn-type-c-linkage. Note that this contrasts with the Rust side where C-ABI functions that take a pointer or ref are permitted and guaranteed to have the same ABI.
PiperOrigin-RevId: 676875775
I was working with an exotic architecture where ABSL_CACHELINE_SIZE of abseil was less than 64, so I got a compilation error about redefined symbols. I think the cc file should be adapted to the header file, so here is my change.
Closes#18193
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/18193 from jagub2:raw_ptr_fix 4958e0f85e
PiperOrigin-RevId: 676543711
To be able to run this check on protobuf generated sources.
Also changed string_field.cc from using a variable to using
the SuppressWarnings annotation, because that takes less
bytecode.
PiperOrigin-RevId: 676534547
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
The .proto.h is not emitted by default from the cc generator in OSS, rather than try to force it to emit we can just use the .pb.h
PiperOrigin-RevId: 676464651
It's possible to operate on a `Map<K, V>` without necessarily knowing at
compile time what `K` and `V` are. The way to do this is by using
`UntypedMapBase`, which `proto2::Map` inherits from. However, to do anything
useful with the map you need two important bits of information: the size of the
map entry, which is represented as a `std::pair<K, V>`, and the offset of the
value within that. These are combined together into the `MapNodeSizeInfoT`
type.
For Rust to wrap C++ maps, we currently need to store in C++ generated code an
array of `MapNodeSizeInfoT` for each message type. The Rust code has to call
into C++ to ask for the appropriate `MapNodeSizeInfoT` and then pass that back
into C++ for map operations.
Dealing with these message-specific constants is pretty awkward, so this CL
introduces a way around that. By making each message's alignment available
through the `MessageLite*` interface, we make it possible to compute the
necessary size info on the fly, instead of requiring the Rust implementation to
store it in generated code. Luckily the existing padding inside
`MessageCreator` provided enough room to store the alignment. Although this
change is mostly for the benefit of Rust, it doesn't cost C++ anything.
This change doesn't actually simplify the Rust implementation yet, but I will
leave that for a follow-up.
PiperOrigin-RevId: 676456011
`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
Maps behave in a very interesting way if they are set to be implicit-presence
fields.
They present the possibility that the key or value (or both) can be the default
zero value. When that happens, access to the key or the value is unaffected. In
this case, presence is a bit of a meaningless concept. Zero keys are valid as
map indices, and if a map entry is set to zero, it just always exists.
Reflection is a little weird too.
- If you do reflection on a normal integer field and ask if a zero-valued field
exists, it will tell you that it doesn't exist. This is consistent with what
"implicit presence" means.
- If you do reflection on a zero integer field that happens to be a map key, it
will tell you that it exists. Fetching the value of map[0] is equally valid.
(Note that this is not exactly *intended*, but it's just hard to change... and
this implementation results in simpler gencode.)
I'm adding unit tests in no_field_presence_test to cover this quirk.
PiperOrigin-RevId: 676268392