Skip to content

Commit ca2fdb3

Browse files
jnthntatumcopybara-github
authored andcommitted
Update the default type provider (protobuf reflection impl) to return a specific
type info instance instead of the generic one. PiperOrigin-RevId: 534552333
1 parent ebf8c93 commit ca2fdb3

File tree

7 files changed

+142
-19
lines changed

7 files changed

+142
-19
lines changed

eval/public/structs/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ cc_test(
259259
":legacy_type_adapter",
260260
":legacy_type_info_apis",
261261
":proto_message_type_adapter",
262+
"//eval/public:cel_options",
262263
"//eval/public:cel_value",
263264
"//eval/public:message_wrapper",
264265
"//eval/public/containers:container_backed_list_impl",

eval/public/structs/legacy_type_info_apis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class LegacyTypeMutationApis;
3131
// Provides ability to obtain field access apis, type info, and debug
3232
// representation of a message.
3333
//
34+
// The message parameter may wrap a nullptr to request generic accessors /
35+
// mutators for the TypeInfo instance if it is available.
36+
//
3437
// This is implemented as a separate class from LegacyTypeAccessApis to resolve
3538
// cyclic dependency between CelValue (which needs to access these apis to
3639
// provide DebugString and ObtainCelTypename) and LegacyTypeAccessApis (which

eval/public/structs/proto_message_type_adapter.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,34 @@ CelValue MessageCelValueFactory(const google::protobuf::Message* message) {
301301

302302
} // namespace
303303

304+
std::string ProtoMessageTypeAdapter::DebugString(
305+
const MessageWrapper& wrapped_message) const {
306+
if (!wrapped_message.HasFullProto() ||
307+
wrapped_message.message_ptr() == nullptr) {
308+
return UnsupportedTypeName();
309+
}
310+
auto* message = cel::internal::down_cast<const google::protobuf::Message*>(
311+
wrapped_message.message_ptr());
312+
return message->ShortDebugString();
313+
}
314+
315+
const std::string& ProtoMessageTypeAdapter::GetTypename(
316+
const MessageWrapper& wrapped_message) const {
317+
return descriptor_->full_name();
318+
}
319+
320+
const LegacyTypeMutationApis* ProtoMessageTypeAdapter::GetMutationApis(
321+
const MessageWrapper& wrapped_message) const {
322+
// Defer checks for misuse on wrong message kind in the accessor calls.
323+
return this;
324+
}
325+
326+
const LegacyTypeAccessApis* ProtoMessageTypeAdapter::GetAccessApis(
327+
const MessageWrapper& wrapped_message) const {
328+
// Defer checks for misuse on wrong message kind in the builder calls.
329+
return this;
330+
}
331+
304332
absl::Status ProtoMessageTypeAdapter::ValidateSetFieldOp(
305333
bool assertion, absl::string_view field, absl::string_view detail) const {
306334
if (!assertion) {

eval/public/structs/proto_message_type_adapter.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_EVAL_PUBLIC_STRUCTS_PROTO_MESSAGE_TYPE_ADAPTER_H_
1616
#define THIRD_PARTY_CEL_CPP_EVAL_PUBLIC_STRUCTS_PROTO_MESSAGE_TYPE_ADAPTER_H_
1717

18+
#include <string>
1819
#include <vector>
1920

2021
#include "google/protobuf/descriptor.h"
@@ -29,7 +30,13 @@
2930

3031
namespace google::api::expr::runtime {
3132

32-
class ProtoMessageTypeAdapter : public LegacyTypeAccessApis,
33+
// Implementation for legacy struct (message) type apis using reflection.
34+
//
35+
// Note: The type info API implementation attached to message values is
36+
// generally the duck-typed instance to support the default behavior of
37+
// deferring to the protobuf reflection apis on the message instance.
38+
class ProtoMessageTypeAdapter : public LegacyTypeInfoApis,
39+
public LegacyTypeAccessApis,
3340
public LegacyTypeMutationApis {
3441
public:
3542
ProtoMessageTypeAdapter(const google::protobuf::Descriptor* descriptor,
@@ -38,6 +45,19 @@ class ProtoMessageTypeAdapter : public LegacyTypeAccessApis,
3845

3946
~ProtoMessageTypeAdapter() override = default;
4047

48+
// Implement LegacyTypeInfoApis
49+
std::string DebugString(const MessageWrapper& wrapped_message) const override;
50+
51+
const std::string& GetTypename(
52+
const MessageWrapper& wrapped_message) const override;
53+
54+
const LegacyTypeAccessApis* GetAccessApis(
55+
const MessageWrapper& wrapped_message) const override;
56+
57+
const LegacyTypeMutationApis* GetMutationApis(
58+
const MessageWrapper& wrapped_message) const override;
59+
60+
// Implement LegacyTypeMutation APIs.
4161
absl::StatusOr<CelValue::MessageWrapper::Builder> NewInstance(
4262
cel::MemoryManager& memory_manager) const override;
4363

@@ -52,6 +72,7 @@ class ProtoMessageTypeAdapter : public LegacyTypeAccessApis,
5272
cel::MemoryManager& memory_manager,
5373
CelValue::MessageWrapper::Builder instance) const override;
5474

75+
// Implement LegacyTypeAccessAPIs.
5576
absl::StatusOr<CelValue> GetField(
5677
absl::string_view field_name, const CelValue::MessageWrapper& instance,
5778
ProtoWrapperTypeOptions unboxing_option,

eval/public/structs/proto_message_type_adapter_test.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "google/protobuf/message.h"
2121
#include "google/protobuf/message_lite.h"
2222
#include "absl/status/status.h"
23+
#include "eval/public/cel_options.h"
2324
#include "eval/public/cel_value.h"
2425
#include "eval/public/containers/container_backed_list_impl.h"
2526
#include "eval/public/containers/container_backed_map_impl.h"
@@ -671,5 +672,70 @@ TEST(ProtoMessageTypeAdapter, AdaptFromWellKnownTypeNotAMessageError) {
671672
StatusIs(absl::StatusCode::kInternal));
672673
}
673674

675+
TEST(ProtoMesssageTypeAdapter, TypeInfoDebug) {
676+
google::protobuf::Arena arena;
677+
ProtoMessageTypeAdapter adapter(
678+
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
679+
"google.api.expr.runtime.TestMessage"),
680+
google::protobuf::MessageFactory::generated_factory());
681+
ProtoMemoryManager manager(&arena);
682+
683+
TestMessage message;
684+
message.set_int64_value(42);
685+
EXPECT_THAT(adapter.DebugString(MessageWrapper(&message, &adapter)),
686+
HasSubstr(message.ShortDebugString()));
687+
688+
EXPECT_THAT(adapter.DebugString(MessageWrapper()),
689+
HasSubstr("<unknown message>"));
690+
}
691+
692+
TEST(ProtoMesssageTypeAdapter, TypeInfoName) {
693+
google::protobuf::Arena arena;
694+
ProtoMessageTypeAdapter adapter(
695+
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
696+
"google.api.expr.runtime.TestMessage"),
697+
google::protobuf::MessageFactory::generated_factory());
698+
ProtoMemoryManager manager(&arena);
699+
700+
EXPECT_EQ(adapter.GetTypename(MessageWrapper()),
701+
"google.api.expr.runtime.TestMessage");
702+
}
703+
704+
TEST(ProtoMesssageTypeAdapter, TypeInfoMutator) {
705+
google::protobuf::Arena arena;
706+
ProtoMessageTypeAdapter adapter(
707+
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
708+
"google.api.expr.runtime.TestMessage"),
709+
google::protobuf::MessageFactory::generated_factory());
710+
ProtoMemoryManager manager(&arena);
711+
712+
const LegacyTypeMutationApis* api = adapter.GetMutationApis(MessageWrapper());
713+
ASSERT_NE(api, nullptr);
714+
715+
ASSERT_OK_AND_ASSIGN(MessageWrapper::Builder builder,
716+
api->NewInstance(manager));
717+
EXPECT_NE(dynamic_cast<TestMessage*>(builder.message_ptr()), nullptr);
718+
}
719+
720+
TEST(ProtoMesssageTypeAdapter, TypeInfoAccesor) {
721+
google::protobuf::Arena arena;
722+
ProtoMessageTypeAdapter adapter(
723+
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
724+
"google.api.expr.runtime.TestMessage"),
725+
google::protobuf::MessageFactory::generated_factory());
726+
ProtoMemoryManager manager(&arena);
727+
728+
TestMessage message;
729+
message.set_int64_value(42);
730+
CelValue::MessageWrapper wrapped(&message, &adapter);
731+
732+
const LegacyTypeAccessApis* api = adapter.GetAccessApis(MessageWrapper());
733+
ASSERT_NE(api, nullptr);
734+
735+
EXPECT_THAT(api->GetField("int64_value", wrapped,
736+
ProtoWrapperTypeOptions::kUnsetNull, manager),
737+
IsOkAndHolds(test::IsCelInt64(42)));
738+
}
739+
674740
} // namespace
675741
} // namespace google::api::expr::runtime

eval/public/structs/protobuf_descriptor_type_provider.cc

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,7 @@ namespace google::api::expr::runtime {
2525

2626
absl::optional<LegacyTypeAdapter> ProtobufDescriptorProvider::ProvideLegacyType(
2727
absl::string_view name) const {
28-
const ProtoMessageTypeAdapter* result = nullptr;
29-
{
30-
absl::MutexLock lock(&mu_);
31-
auto it = type_cache_.find(name);
32-
if (it != type_cache_.end()) {
33-
result = it->second.get();
34-
} else {
35-
auto type_provider = GetType(name);
36-
result = type_provider.get();
37-
type_cache_[name] = std::move(type_provider);
38-
}
39-
}
28+
const ProtoMessageTypeAdapter* result = GetTypeAdapter(name);
4029
if (result == nullptr) {
4130
return absl::nullopt;
4231
}
@@ -47,11 +36,11 @@ absl::optional<LegacyTypeAdapter> ProtobufDescriptorProvider::ProvideLegacyType(
4736
absl::optional<const LegacyTypeInfoApis*>
4837
ProtobufDescriptorProvider::ProvideLegacyTypeInfo(
4938
absl::string_view name) const {
50-
return &GetGenericProtoTypeInfoInstance();
39+
return GetTypeAdapter(name);
5140
}
5241

53-
std::unique_ptr<ProtoMessageTypeAdapter> ProtobufDescriptorProvider::GetType(
54-
absl::string_view name) const {
42+
std::unique_ptr<ProtoMessageTypeAdapter>
43+
ProtobufDescriptorProvider::CreateTypeAdapter(absl::string_view name) const {
5544
const google::protobuf::Descriptor* descriptor =
5645
descriptor_pool_->FindMessageTypeByName(name);
5746
if (descriptor == nullptr) {
@@ -61,4 +50,17 @@ std::unique_ptr<ProtoMessageTypeAdapter> ProtobufDescriptorProvider::GetType(
6150
return std::make_unique<ProtoMessageTypeAdapter>(descriptor,
6251
message_factory_);
6352
}
53+
54+
const ProtoMessageTypeAdapter* ProtobufDescriptorProvider::GetTypeAdapter(
55+
absl::string_view name) const {
56+
absl::MutexLock lock(&mu_);
57+
auto it = type_cache_.find(name);
58+
if (it != type_cache_.end()) {
59+
return it->second.get();
60+
}
61+
auto type_provider = CreateTypeAdapter(name);
62+
const ProtoMessageTypeAdapter* result = type_provider.get();
63+
type_cache_[name] = std::move(type_provider);
64+
return result;
65+
}
6466
} // namespace google::api::expr::runtime

eval/public/structs/protobuf_descriptor_type_provider.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,13 @@ class ProtobufDescriptorProvider : public LegacyTypeProvider {
4545
absl::string_view name) const override;
4646

4747
private:
48-
// Run a lookup if the type adapter hasn't already been built.
49-
// returns nullptr if not found.
50-
std::unique_ptr<ProtoMessageTypeAdapter> GetType(
48+
// Create a new type instance if found in the registered descriptor pool.
49+
// Otherwise, returns nullptr.
50+
std::unique_ptr<ProtoMessageTypeAdapter> CreateTypeAdapter(
5151
absl::string_view name) const;
5252

53+
const ProtoMessageTypeAdapter* GetTypeAdapter(absl::string_view name) const;
54+
5355
const google::protobuf::DescriptorPool* descriptor_pool_;
5456
google::protobuf::MessageFactory* message_factory_;
5557
mutable absl::flat_hash_map<std::string,

0 commit comments

Comments
 (0)