Add support for `oneof` fields in a `proto_parsing::Message`
This change adds a way for `proto_parsing::Message` implementations to handle `oneof` fields. This can be done as follows:
```c++
class OneofTestMessageTP : public Message {
public:
enum MyOneofCase {
MY_ONEOF_NOT_SET = 0,
kFieldA = 1,
kFieldB = 2,
};
OneofTestMessageTP() = default;
OneofTestMessageTP(const OneofTestMessageTP&) = default;
OneofTestMessageTP& operator=(const OneofTestMessageTP&) = default;
MyOneofCase my_oneof_case() const { return my_oneof_case_; }
// Accessors for field_a (uint32)
bool has_field_a() const { return field_a_.has_value(); }
uint32_t field_a() const { return field_a_.value(); }
void set_field_a(uint32_t val) {
BeforeFieldSet(&field_a_);
field_a_.set_value(val);
}
void clear_field_a() {
if (my_oneof_case_ == kFieldA) {
my_oneof_case_ = MY_ONEOF_NOT_SET;
}
field_a_.Clear();
}
// Accessors for field_b (bytes/string)
bool has_field_b() const { return field_b_.has_value(); }
const std::string& field_b() const { return field_b_.value(); }
void set_field_b(absl::string_view val) {
BeforeFieldSet(&field_b_);
field_b_.set_value(val);
}
void clear_field_b() {
if (my_oneof_case_ == kFieldB) {
my_oneof_case_ = MY_ONEOF_NOT_SET;
}
field_b_.Clear();
}
void Clear() override {
::tink_proto::Message::Clear();
my_oneof_case_ = MY_ONEOF_NOT_SET;
}
protected:
// Hook called by ParseFromString AND setters to enforce mutual exclusion
void BeforeFieldSet(const ::tink_proto::Field* field) override {
if (field == &field_a_ || field == &field_b_) {
MyOneofCase parsed_case = static_cast<MyOneofCase>(field->FieldNumber());
if (my_oneof_case_ == parsed_case) {
return; // Allows submessage merging if the same field is parsed again
}
if (my_oneof_case_ == kFieldA) {
field_a_.Clear();
} else if (my_oneof_case_ == kFieldB) {
field_b_.Clear();
}
my_oneof_case_ = parsed_case;
}
}
private:
size_t num_fields() const override { return 2; }
const ::tink_proto::Field* field(int i) const override {
return std::array<const ::tink_proto::Field*, 2>{{&field_a_, &field_b_}}[i];
}
::tink_proto::Uint32Field field_a_{1, ::tink_proto::ProtoFieldOptions::kExplicit};
::tink_proto::BytesField field_b_{2, ::tink_proto::ProtoFieldOptions::kExplicit};
MyOneofCase my_oneof_case_ = MY_ONEOF_NOT_SET;
};
```
PiperOrigin-RevId: 947020621
Change-Id: I2f1baeff0043723413366b72d1c992382f525fc0
| Test | GCP Ubuntu | macOS | GCP Windows |
|---|---|---|---|
| Bazel | |||
| Bazel w/ BoringCrypto (FIPS) | N/A | N/A | |
| CMake | |||
| CMake w/ OpenSSL | N/A | ||
| CMake w/ OpenSSL3 | N/A | N/A | |
| CMake w/ Installed Deps | N/A | N/A |
[!NOTE] We plan to change Tink to always require BoringSSL as a backend (instead of allowing OpenSSL), starting from Tink 3.0.0. See https://github.com/tink-crypto/tink-cc/issues/22 for details.
Using crypto in your application shouldn't have to feel like juggling chainsaws in the dark. Tink is a crypto library written by a group of cryptographers and security engineers at Google. It was born out of our extensive experience working with Google's product teams, fixing weaknesses in implementations, and providing simple APIs that can be used safely without needing a crypto background.
Tink provides secure APIs that are easy to use correctly and hard(er) to misuse. It reduces common crypto pitfalls with user-centered design, careful implementation and code reviews, and extensive testing. At Google, Tink is one of the standard crypto libraries, and has been deployed in hundreds of products and systems.
To get a quick overview of Tink's design please take a look at Tink's goals.
The official documentation is available at https://developers.google.com/tink.
If you want to contribute, please read CONTRIBUTING and send us pull requests. You can also report bugs or file feature requests.
If you'd like to talk to the developers or get notified about major product updates, you may want to subscribe to our mailing list.
Tink is maintained by (A-Z):
Alumni: