Skip to content

Commit 6d61140

Browse files
jnthntatumcopybara-github
authored andcommitted
Add accessors for extracting legacy type from cel::LegacyStructType.
PiperOrigin-RevId: 534499645
1 parent 9cae0ab commit 6d61140

13 files changed

Lines changed: 523 additions & 96 deletions

base/type_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace cel {
3535
class TypeManager final {
3636
public:
3737
TypeManager(TypeFactory& type_factory ABSL_ATTRIBUTE_LIFETIME_BOUND,
38-
TypeProvider& type_provider ABSL_ATTRIBUTE_LIFETIME_BOUND)
38+
const TypeProvider& type_provider ABSL_ATTRIBUTE_LIFETIME_BOUND)
3939
: type_factory_(type_factory), type_provider_(type_provider) {}
4040

4141
MemoryManager& memory_manager() const {

eval/internal/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ cc_test(
5858
"//eval/public/containers:container_backed_list_impl",
5959
"//eval/public/containers:container_backed_map_impl",
6060
"//eval/public/structs:cel_proto_wrapper",
61+
"//eval/public/structs:legacy_type_info_apis",
62+
"//eval/public/structs:proto_message_type_adapter",
6163
"//eval/public/structs:trivial_legacy_type_info",
64+
"//eval/testutil:test_message_cc_proto",
6265
"//extensions/protobuf:memory_manager",
6366
"//extensions/protobuf:type",
6467
"//extensions/protobuf:value",

eval/internal/interop.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ Handle<StructType> LegacyStructTypeAccess::Create(uintptr_t message) {
248248
base_internal::LegacyStructType>(message);
249249
}
250250

251+
uintptr_t LegacyStructTypeAccess::GetStorage(
252+
const base_internal::LegacyStructType& type) {
253+
return type.msg_;
254+
}
255+
251256
Handle<StructValue> LegacyStructValueAccess::Create(
252257
const MessageWrapper& wrapper) {
253258
return Create(MessageWrapperAccess::Message(wrapper),
@@ -526,6 +531,27 @@ absl::StatusOr<CelValue> ToLegacyValue(google::protobuf::Arena* arena,
526531
ValueKindToString(value->kind()), " is not yet implemented"));
527532
}
528533

534+
Handle<StructType> CreateStructTypeFromLegacyTypeInfo(
535+
const LegacyTypeInfoApis* type_info) {
536+
return LegacyStructTypeAccess::Create(reinterpret_cast<uintptr_t>(type_info));
537+
}
538+
539+
const google::api::expr::runtime::LegacyTypeInfoApis* LegacyTypeInfoFromType(
540+
const Handle<Type>& type) {
541+
if (!type->Is<base_internal::LegacyStructType>()) {
542+
return nullptr;
543+
}
544+
uintptr_t representation = LegacyStructTypeAccess::GetStorage(
545+
type->As<base_internal::LegacyStructType>());
546+
if ((representation & base_internal::kMessageWrapperTagMask) !=
547+
base_internal::kMessageWrapperTagTypeInfoValue) {
548+
return nullptr;
549+
}
550+
551+
return reinterpret_cast<google::api::expr::runtime::LegacyTypeInfoApis*>(
552+
representation & base_internal::kMessageWrapperPtrMask);
553+
}
554+
529555
Handle<NullValue> CreateNullValue() {
530556
return HandleFactory<NullValue>::Make<NullValue>();
531557
}

eval/internal/interop.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "base/values/type_value.h"
3131
#include "eval/public/cel_value.h"
3232
#include "eval/public/message_wrapper.h"
33+
#include "eval/public/structs/legacy_type_info_apis.h"
3334

3435
namespace cel::interop_internal {
3536

@@ -45,6 +46,7 @@ struct CelMapAccess final {
4546

4647
struct LegacyStructTypeAccess final {
4748
static Handle<StructType> Create(uintptr_t message);
49+
static uintptr_t GetStorage(const base_internal::LegacyStructType& type);
4850
};
4951

5052
struct LegacyStructValueAccess final {
@@ -68,6 +70,13 @@ struct MessageWrapperAccess final {
6870
google::api::expr::runtime::MessageWrapper& wrapper);
6971
};
7072

73+
Handle<StructType> CreateStructTypeFromLegacyTypeInfo(
74+
const google::api::expr::runtime::LegacyTypeInfoApis* type_info);
75+
76+
// Nullptr is returned if this is not a legacy message type.
77+
const google::api::expr::runtime::LegacyTypeInfoApis* LegacyTypeInfoFromType(
78+
const Handle<Type>& type);
79+
7180
// Unlike ValueFactory::CreateStringValue, this does not copy input and instead
7281
// wraps it. It should only be used for interop with the legacy CelValue.
7382
Handle<StringValue> CreateStringValueFromView(absl::string_view value);

eval/internal/interop_test.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,26 @@
3939
#include "eval/public/containers/container_backed_map_impl.h"
4040
#include "eval/public/message_wrapper.h"
4141
#include "eval/public/structs/cel_proto_wrapper.h"
42+
#include "eval/public/structs/legacy_type_info_apis.h"
43+
#include "eval/public/structs/proto_message_type_adapter.h"
4244
#include "eval/public/structs/trivial_legacy_type_info.h"
4345
#include "eval/public/unknown_set.h"
46+
#include "eval/testutil/test_message.pb.h"
4447
#include "extensions/protobuf/memory_manager.h"
4548
#include "extensions/protobuf/type_provider.h"
4649
#include "extensions/protobuf/value.h"
4750
#include "internal/testing.h"
51+
#include "google/protobuf/message.h"
4852

4953
namespace cel::interop_internal {
5054
namespace {
5155

5256
using ::google::api::expr::runtime::CelProtoWrapper;
5357
using ::google::api::expr::runtime::CelValue;
5458
using ::google::api::expr::runtime::ContainerBackedListImpl;
59+
using ::google::api::expr::runtime::LegacyTypeInfoApis;
5560
using ::google::api::expr::runtime::MessageWrapper;
61+
using ::google::api::expr::runtime::TestMessage;
5662
using ::google::api::expr::runtime::UnknownSet;
5763
using testing::Eq;
5864
using testing::HasSubstr;
@@ -799,6 +805,42 @@ TEST(ValueInterop, StructFromLegacyMessageLite) {
799805
value_wrapper.legacy_type_info());
800806
}
801807

808+
TEST(ValueInterop, StructTypeFromLegacyTypeInfo) {
809+
google::protobuf::Arena arena;
810+
extensions::ProtoMemoryManager memory_manager(&arena);
811+
TypeFactory type_factory(memory_manager);
812+
TypeManager type_manager(type_factory, TypeProvider::Builtin());
813+
ValueFactory value_factory(type_manager);
814+
google::protobuf::LinkMessageReflection<google::api::expr::runtime::TestMessage>();
815+
816+
google::api::expr::runtime::ProtoMessageTypeAdapter adapter(
817+
TestMessage::descriptor(), google::protobuf::MessageFactory::generated_factory());
818+
819+
Handle<Type> type = CreateStructTypeFromLegacyTypeInfo(
820+
static_cast<const LegacyTypeInfoApis*>(&adapter));
821+
822+
EXPECT_EQ(type->name(), "google.api.expr.runtime.TestMessage");
823+
}
824+
825+
TEST(ValueInterop, StructTypeLegacyTypeInfoRoundTrip) {
826+
google::protobuf::Arena arena;
827+
extensions::ProtoMemoryManager memory_manager(&arena);
828+
TypeFactory type_factory(memory_manager);
829+
TypeManager type_manager(type_factory, TypeProvider::Builtin());
830+
ValueFactory value_factory(type_manager);
831+
google::protobuf::LinkMessageReflection<google::api::expr::runtime::TestMessage>();
832+
833+
google::api::expr::runtime::ProtoMessageTypeAdapter adapter(
834+
TestMessage::descriptor(), google::protobuf::MessageFactory::generated_factory());
835+
836+
Handle<Type> type = CreateStructTypeFromLegacyTypeInfo(
837+
static_cast<const LegacyTypeInfoApis*>(&adapter));
838+
839+
EXPECT_EQ(LegacyTypeInfoFromType(type),
840+
static_cast<const LegacyTypeInfoApis*>(&adapter));
841+
EXPECT_EQ(LegacyTypeInfoFromType(type_factory.GetBoolType()), nullptr);
842+
}
843+
802844
TEST(ValueInterop, LegacyStructRoundtrip) {
803845
google::protobuf::Arena arena;
804846
extensions::ProtoMemoryManager memory_manager(&arena);

eval/public/BUILD

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -940,16 +940,19 @@ cc_library(
940940
srcs = ["cel_type_registry.cc"],
941941
hdrs = ["cel_type_registry.h"],
942942
deps = [
943+
"//base:data",
943944
"//base:handle",
944945
"//base:memory",
945-
"//base:type",
946-
"//base:value",
947946
"//eval/internal:interop",
947+
"//eval/public/structs:legacy_type_info_apis",
948948
"//eval/public/structs:legacy_type_provider",
949+
"//internal:casts",
950+
"//runtime/internal:composed_type_provider",
949951
"@com_google_absl//absl/base:core_headers",
950952
"@com_google_absl//absl/container:flat_hash_map",
951953
"@com_google_absl//absl/container:flat_hash_set",
952954
"@com_google_absl//absl/container:node_hash_set",
955+
"@com_google_absl//absl/status:statusor",
953956
"@com_google_absl//absl/strings",
954957
"@com_google_absl//absl/synchronization",
955958
"@com_google_absl//absl/types:optional",
@@ -962,8 +965,8 @@ cc_test(
962965
srcs = ["cel_type_registry_test.cc"],
963966
deps = [
964967
":cel_type_registry",
965-
"//base:type",
966-
"//base:value",
968+
"//base:data",
969+
"//base:memory",
967970
"//eval/public/structs:legacy_type_provider",
968971
"//eval/testutil:test_message_cc_proto",
969972
"//internal:testing",
@@ -974,6 +977,22 @@ cc_test(
974977
],
975978
)
976979

980+
cc_test(
981+
name = "cel_type_registry_protobuf_reflection_test",
982+
srcs = ["cel_type_registry_protobuf_reflection_test.cc"],
983+
deps = [
984+
":cel_type_registry",
985+
"//base:data",
986+
"//base:handle",
987+
"//base:memory",
988+
"//eval/public/structs:protobuf_descriptor_type_provider",
989+
"//eval/testutil:test_message_cc_proto",
990+
"//internal:testing",
991+
"@com_google_absl//absl/types:optional",
992+
"@com_google_protobuf//:protobuf",
993+
],
994+
)
995+
977996
cc_test(
978997
name = "builtin_func_test",
979998
size = "small",

eval/public/cel_type_registry.cc

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,22 @@
77

88
#include "absl/container/flat_hash_set.h"
99
#include "absl/container/node_hash_set.h"
10+
#include "absl/status/statusor.h"
1011
#include "absl/strings/string_view.h"
1112
#include "absl/synchronization/mutex.h"
1213
#include "absl/types/optional.h"
1314
#include "base/handle.h"
1415
#include "base/memory.h"
16+
#include "base/type.h"
1517
#include "base/type_factory.h"
18+
#include "base/type_provider.h"
1619
#include "base/types/enum_type.h"
20+
#include "base/types/struct_type.h"
1721
#include "base/value.h"
1822
#include "eval/internal/interop.h"
23+
#include "eval/public/structs/legacy_type_info_apis.h"
24+
#include "eval/public/structs/legacy_type_provider.h"
25+
#include "internal/casts.h"
1926
#include "google/protobuf/descriptor.h"
2027

2128
namespace google::api::expr::runtime {
@@ -24,6 +31,7 @@ namespace {
2431

2532
using cel::Handle;
2633
using cel::MemoryManager;
34+
using cel::Type;
2735
using cel::TypeFactory;
2836
using cel::UniqueRef;
2937
using cel::Value;
@@ -54,6 +62,51 @@ cel::TypeFactory& GetDefaultTypeFactory() {
5462
return *factory;
5563
}
5664

65+
class LegacyToModernTypeProviderAdapter : public cel::TypeProvider {
66+
public:
67+
explicit LegacyToModernTypeProviderAdapter(const LegacyTypeProvider& provider)
68+
: provider_(provider) {}
69+
70+
absl::StatusOr<absl::optional<Handle<Type>>> ProvideType(
71+
TypeFactory& factory, absl::string_view name) const override {
72+
absl::optional<const LegacyTypeInfoApis*> type_info =
73+
provider_.ProvideLegacyTypeInfo(name);
74+
75+
if (!type_info.has_value() || *type_info == nullptr) {
76+
return absl::nullopt;
77+
}
78+
79+
return cel::interop_internal::CreateStructTypeFromLegacyTypeInfo(
80+
*type_info);
81+
}
82+
83+
private:
84+
const LegacyTypeProvider& provider_;
85+
};
86+
87+
// A trivial type provider for registered Enums.
88+
//
89+
// Clients manually register the expected enums available to reference in the
90+
// input expressions. These may mask other defined enumerators (e.g. reference
91+
// by a protobuf message).
92+
class EnumTypeProvider : public cel::TypeProvider {
93+
public:
94+
explicit EnumTypeProvider(const EnumMap& enum_map) : enum_map_(enum_map) {}
95+
96+
absl::StatusOr<absl::optional<Handle<Type>>> ProvideType(
97+
TypeFactory&, absl::string_view name) const override {
98+
auto iter = enum_map_.find(name);
99+
if (iter != enum_map_.end()) {
100+
return iter->second;
101+
}
102+
103+
return absl::nullopt;
104+
}
105+
106+
private:
107+
const EnumMap& enum_map_;
108+
};
109+
57110
// EnumType implementation for generic enums that are defined at runtime that
58111
// can be resolved in expressions.
59112
//
@@ -176,6 +229,8 @@ ResolveableEnumType::FindConstantByNumber(int64_t number) const {
176229

177230
CelTypeRegistry::CelTypeRegistry() : types_(GetCoreTypes()) {
178231
RegisterEnum("google.protobuf.NullValue", {{"NULL_VALUE", 0}});
232+
type_provider_impl_.AddTypeProvider(
233+
std::make_unique<EnumTypeProvider>(resolveable_enums_));
179234
}
180235

181236
void CelTypeRegistry::Register(std::string fully_qualified_type_name) {
@@ -198,18 +253,27 @@ void CelTypeRegistry::RegisterEnum(absl::string_view enum_name,
198253
resolveable_enums_[enum_name] = std::move(result_or).value();
199254
}
200255

256+
void CelTypeRegistry::RegisterTypeProvider(
257+
std::unique_ptr<LegacyTypeProvider> provider) {
258+
legacy_type_providers_.push_back(
259+
std::shared_ptr<const LegacyTypeProvider>(std::move(provider)));
260+
type_provider_impl_.AddTypeProvider(
261+
std::make_unique<LegacyToModernTypeProviderAdapter>(
262+
*legacy_type_providers_.back()));
263+
}
264+
201265
std::shared_ptr<const LegacyTypeProvider>
202266
CelTypeRegistry::GetFirstTypeProvider() const {
203-
if (type_providers_.empty()) {
267+
if (legacy_type_providers_.empty()) {
204268
return nullptr;
205269
}
206-
return type_providers_[0];
270+
return legacy_type_providers_[0];
207271
}
208272

209273
// Find a type's CelValue instance by its fully qualified name.
210274
absl::optional<LegacyTypeAdapter> CelTypeRegistry::FindTypeAdapter(
211275
absl::string_view fully_qualified_type_name) const {
212-
for (const auto& provider : type_providers_) {
276+
for (const auto& provider : legacy_type_providers_) {
213277
auto maybe_adapter = provider->ProvideLegacyType(fully_qualified_type_name);
214278
if (maybe_adapter.has_value()) {
215279
return maybe_adapter;

0 commit comments

Comments
 (0)