1818#include < cstdint>
1919#include < iterator>
2020#include < memory>
21+ #include < optional>
2122#include < string>
2223#include < utility>
2324#include < vector>
3132#include " absl/status/statusor.h"
3233#include " absl/strings/match.h"
3334#include " absl/strings/string_view.h"
34- #include " absl/types/optional.h"
3535#include " absl/types/span.h"
3636#include " absl/types/variant.h"
3737#include " base/attribute.h"
4343#include " common/expr.h"
4444#include " common/function_descriptor.h"
4545#include " common/kind.h"
46+ #include " common/legacy_value.h"
47+ #include " common/memory.h"
4648#include " common/native_type.h"
4749#include " common/type.h"
4850#include " common/value.h"
5254#include " eval/eval/direct_expression_step.h"
5355#include " eval/eval/evaluator_core.h"
5456#include " eval/eval/expression_step_base.h"
57+ #include " eval/public/cel_value.h"
58+ #include " eval/public/structs/proto_message_type_adapter.h"
5559#include " internal/casts.h"
5660#include " internal/number.h"
5761#include " internal/status_macros.h"
5862#include " runtime/internal/errors.h"
5963#include " runtime/internal/runtime_friend_access.h"
6064#include " runtime/internal/runtime_impl.h"
6165#include " runtime/runtime_builder.h"
66+ #include " runtime/runtime_options.h"
6267#include " google/protobuf/arena.h"
6368#include " google/protobuf/descriptor.h"
6469#include " google/protobuf/message.h"
@@ -74,12 +79,15 @@ using ::cel::Expr;
7479using ::cel::ExprKind;
7580using ::cel::SelectExpr;
7681using ::google::api::expr::runtime::AttributeTrail;
82+ using ::google::api::expr::runtime::CelValue;
7783using ::google::api::expr::runtime::DirectExpressionStep;
7884using ::google::api::expr::runtime::ExecutionFrame;
7985using ::google::api::expr::runtime::ExecutionFrameBase;
8086using ::google::api::expr::runtime::ExpressionStepBase;
87+ using ::google::api::expr::runtime::GetGenericProtoTypeInfoInstance;
8188using ::google::api::expr::runtime::PlannerContext;
8289using ::google::api::expr::runtime::ProgramOptimizer;
90+ using ::google::api::expr::runtime::internal::GetGenericProtoAccessApisInstance;
8391
8492// Represents a single select operation (field access or indexing).
8593// For struct-typed field accesses, includes the field name and the field
@@ -267,6 +275,57 @@ absl::StatusOr<Value> MapKeyFromQualifier(const AttributeQualifier& qual,
267275 }
268276}
269277
278+ // Helper for StructValue::GetFieldByName. Used for opting out of old reflection
279+ // implementation.
280+ absl::StatusOr<Value> WrappedStructGet (
281+ const Value& target, absl::string_view field,
282+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
283+ google::protobuf::MessageFactory* absl_nonnull message_factory,
284+ google::protobuf::Arena* absl_nonnull arena) {
285+ if (const google::protobuf::Message* message =
286+ cel::interop_internal::GetLegacyMessage (target);
287+ message != nullptr ) {
288+ CelValue::MessageWrapper message_wrapper (
289+ message, &GetGenericProtoTypeInfoInstance ());
290+ CEL_ASSIGN_OR_RETURN (
291+ CelValue cel_value,
292+ GetGenericProtoAccessApisInstance ().GetField (
293+ field, message_wrapper, ProtoWrapperTypeOptions::kUnsetProtoDefault ,
294+ MemoryManagerRef::Pooling (arena)));
295+ Value result;
296+ CEL_RETURN_IF_ERROR (cel::ModernValue (arena, cel_value, result));
297+ return result;
298+ }
299+ return target.GetStruct ().GetFieldByName (field, descriptor_pool,
300+ message_factory, arena);
301+ }
302+
303+ // Helper for StructValue::Qualify. Used for opting out of old reflection
304+ // implementation.
305+ absl::StatusOr<std::pair<Value, ssize_t >> WrappedStructQualify (
306+ const StructValue& struct_value,
307+ absl::Span<const SelectQualifier> qualifiers, bool presence_test,
308+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
309+ google::protobuf::MessageFactory* absl_nonnull message_factory,
310+ google::protobuf::Arena* absl_nonnull arena) {
311+ if (const google::protobuf::Message* message =
312+ cel::interop_internal::GetLegacyMessage (struct_value);
313+ message != nullptr ) {
314+ CelValue::MessageWrapper message_wrapper (
315+ message, &GetGenericProtoTypeInfoInstance ());
316+ CEL_ASSIGN_OR_RETURN (auto legacy_result,
317+ GetGenericProtoAccessApisInstance ().Qualify (
318+ qualifiers, message_wrapper, presence_test,
319+ MemoryManagerRef::Pooling (arena)));
320+ Value result;
321+ CEL_RETURN_IF_ERROR (cel::ModernValue (arena, legacy_result.value , result));
322+ return std::pair<Value, ssize_t >{std::move (result),
323+ legacy_result.qualifier_count };
324+ }
325+ return struct_value.Qualify (qualifiers, presence_test, descriptor_pool,
326+ message_factory, arena);
327+ }
328+
270329absl::StatusOr<Value> ApplyQualifier (
271330 const Value& operand, const SelectQualifier& qualifier,
272331 const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
@@ -280,8 +339,8 @@ absl::StatusOr<Value> ApplyQualifier(
280339 cel::runtime_internal::CreateNoMatchingOverloadError (
281340 " <select>" ));
282341 }
283- return operand. GetStruct (). GetFieldByName (
284- field_specifier. name , descriptor_pool, message_factory, arena);
342+ return WrappedStructGet ( operand, field_specifier. name ,
343+ descriptor_pool, message_factory, arena);
285344 },
286345 [&](const AttributeQualifier& qualifier) -> absl::StatusOr<Value> {
287346 if (operand.Is <ListValue>()) {
@@ -632,7 +691,7 @@ absl::StatusOr<Value> OptimizedSelectImpl::ApplySelect(
632691 auto value_or =
633692 (options_.force_fallback_implementation )
634693 ? absl::UnimplementedError (" Forced fallback impl" )
635- : struct_value. Qualify ( select_path_, presence_test_,
694+ : WrappedStructQualify (struct_value, select_path_, presence_test_,
636695 frame.descriptor_pool (),
637696 frame.message_factory (), frame.arena ());
638697
0 commit comments