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
2128namespace google ::api::expr::runtime {
@@ -24,6 +31,7 @@ namespace {
2431
2532using cel::Handle;
2633using cel::MemoryManager;
34+ using cel::Type;
2735using cel::TypeFactory;
2836using cel::UniqueRef;
2937using 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
177230CelTypeRegistry::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
181236void 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+
201265std::shared_ptr<const LegacyTypeProvider>
202266CelTypeRegistry::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.
210274absl::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